
WordPress Bot Protection with Cloudflare: My Exact WAF Rules (Copy/Paste)
In this playbook, you’ll find the exact Cloudflare WAF security rules I use on my own sites and on client sites, designed to work within the limits of a free Cloudflare account.

This resource is about implementation.
In the public article, I explained why bot protection matters and why Cloudflare is the most effective place to stop it. Here, we’re skipping theory and going straight to execution.
Below, you’ll find the exact Cloudflare WAF security rules I use on my own sites and on client sites, designed to work within the limits of a free Cloudflare account. These rules are intended to be copied, pasted, and enabled as-is, with only minimal adjustments if your site has unique requirements.
Alongside this page is a companion video. In that video, I walk through:
- Where these rules live inside a standard Cloudflare account
- The correct order to create them
- Which rules are skip, challenge, or block
- How to safely test and deploy them
- What to tweak if something legitimate gets caught
If you follow the steps shown, you’ll end up with a layered Cloudflare WAF setup that blocks the majority of automated WordPress bot traffic before it ever reaches your server.
I will also point the way to some common exclusions and modifications you may need to make to these rules.
Using These Security Rules
These security rules will be entered inside your Cloudflare account. First things first… you need to be running your domain DNS through Cloudflare.
Set up your Cloudflare account, if you don’t already have one. Do not buy anything – you do NOT need a paid account to implement this. Set up your domain in your Cloudflare account. It will import your existing DNS from wherever you manage your DNS now. Then, when done you will get two nameservers that point to Cloudflare. Then, at your registrar, you switch over to custom nameservers and paste in those 2 Cloudflare servers. Save and…. that’s it. Cloudflare will notify you by email when the domain is LIVE from Cloudflare.
Now, the run part…
In your Cloudflare account – and inside the section for your domain – click on Security → Security Rules.
We will be using the “Custom Rules”. With a free account, you only have 5 slots. But, that’s OK because we’re going to tweak these rules to fit a lot of horsepower into those 5 slots.
For each of the 5 rules I’m about to share with you, I will be giving you an expression. It is basically a formula. With each rule, you can build it manually using the rule/logic builder. Or, you can click “Edit Expression” and then simply copy/paste these expressions. That’s a massive shortcut.
The WAF Rule Expressions (Copy/Paste)
OK, let’s do this. There are 5 rules. All of them have a name. Let’s do it one by one. They need to be in this order.
1 – White List
(ip.src eq 49.12.1.37) or (http.user_agent contains "WPRemote") or (http.user_agent contains "BlogVault") or (http.request.uri.path contains "/bv-sync/") or (http.user_agent contains "ShortPixel")
This rule is where you need to whitelist anything that should always be allowed through the firewall. In my case, this rule fits:
- Any request from the web server the website is sitting in. This IP address needs to be modified to be your hosting IP address.
- Any request from WPRemote/BlogVault (this happens to be the site manager I use to manage client sites). This likely will not apply for you.
- Any request from ShortPixel, which is the image optimization plugin I use for Concierge. You may not be using ShortPixel, but you will need to whitelist any image optimizing service you are using.
Additional Info:
- Action: Skip.
- Log Request.
- Skip All Remaining Custom Rules.
2 – Allow Good Bots
The purpose of this rule is to allow known good bots (as managed by Cloudflare), the Let’s Encrypt service, and any acme challenge.
(cf.verified_bot_category in {
"Search Engine Crawler"
"Search Engine Optimization"
"Monitoring & Analytics"
"Advertising & Marketing"
"Page Preview"
"Academic Research"
"Security"
"Accessibility"
"Webhooks"
"Feed Fetcher"
}) or (http.user_agent contains "letsencrypt" and http.request.uri.path contains ".well-known/acme-challenge")
Additional Info:
- Action: Skip.
- Log Request.
- UNcheck “All remaining custom rules” so that our remaining rules will still apply. But, check off every other box to skip those additional checks.
3 – Aggressive Crawlers
The purpose of this rule is to present a challenge to bots which are known to be particularly aggressive when it comes to hammering servers. They’re not necessarily ill-intentions, but they don’t respect your site’s performance and they can hammer your site so hard that it slows things down.
(http.user_agent contains "yandex") or (http.user_agent contains "sogou") or (http.user_agent contains "semrush") or (http.user_agent contains "ahrefs") or (http.user_agent contains "baidu") or (http.user_agent contains "python-requests") or (http.user_agent contains "neevabot") or (http.user_agent contains "CF-UC") or (http.user_agent contains "sitelock") or (http.user_agent contains "crawl" and not cf.client.bot) or (http.user_agent contains "bot" and not cf.client.bot) or (http.user_agent contains "Bot" and not cf.client.bot) or (http.user_agent contains "Crawl" and not cf.client.bot) or (http.user_agent contains "spider" and not cf.client.bot) or (http.user_agent contains "mj12bot") or (http.user_agent contains "ZoominfoBot") or (http.user_agent contains "mojeek") or (ip.src.asnum in {135061 23724 4808} and http.user_agent contains "siteaudit")
Additional Info:
- Action: Managed Challenge.
4 – Challenge Clouds / VPNs / Foreign
This rule does a lot of heavy lifting. In this rule, we’re combining a whole lot of things together (in order to fit within the 5 rules of the Cloudflare free plan). Some of that includes:
- Common cloud networks that host VPS servers known to be used by bot farms.
- Countries that may be problematic. You want to modify this rule to ensure it allows those countries where most of your traffic comes from, but we want to leave the rest to be challenged to ensure they’re real humans. We often see scam traffic from nations like China, Indonesia, African nations, Turkey, Bangladesh, etc. It is what it is. Some nations are more prone to this kind of activity than others. But, we don’t block them. We challenge them first. If they’re real people, they’ll get right on through.
- We protect the login, because hammering the WordPress login screen is common bot activity. So, we present a challenge.
(
ip.src.asnum in {7224 16509 14618 15169 8075 396982 60068 9009 16247 51332 212238 131199 22298 29761 62639 206150 210277 46562 8100 3214 206092 206074 206164 213074}
and not cf.client.bot
and not cf.verified_bot_category in {"Search Engine Crawler" "Search Engine Optimization" "Monitoring & Analytics" "Advertising & Marketing" "Page Preview" "Academic Research" "Security" "Accessibility" "Webhooks" "Feed Fetcher" "Aggregator"}
and not http.request.uri.path contains ".well-known/acme-challenge"
)
or
(
not ip.src.country in {"CA" "GB" "US" "AU"}
and not cf.client.bot
and not cf.verified_bot_category in {"Search Engine Crawler" "Search Engine Optimization" "Monitoring & Analytics" "Advertising & Marketing" "Page Preview" "Academic Research" "Security" "Accessibility" "Webhooks" "Feed Fetcher" "Aggregator"}
and not http.request.uri.path contains ".well-known/acme-challenge"
and not http.request.uri.query contains "fbclid"
and not ip.src.asnum in {32934}
)
or (http.request.uri.path contains "wp-login")
Additional Info:
- Action: Managed Challenge.
5 – Block Hosts / Paths / AI / TOR
This is the last rule in the chain. After all other rules are checked, if it gets to this rule, things will be blocked. This rule includes:
- Numerous ASNs to match common VPS clouds known to be used by spammers.
- Calls to known aspects of WordPress that are common attack points, such as XML-RPC, the old Windows Live Writer connection, or a direct call to the config file.
- It blocks Tor connections, which is from people specifically trying to hide themselves. Tor is perfectly fine and I don’t have any issue with the technology, but there’s no good served by making your site open to Tor connections.
(
ip.src.asnum in {
200373 198571 26496 31815 18450 398101 50673 7393 14061 205544
199610 21501 16125 51540 264649 39020 30083 35540 55293 36943
32244 6724 63949 7203 201924 30633 208046 36352 25264 32475
23033 212047 31898 210920 211252 16276 23470 136907 12876 210558
132203 61317 212238 37963 13238 2639 20473 63018 395954 19437
207990 27411 53667 27176 396507 206575 20454 51167 60781 62240
398493 206092 63023 213230 26347 20738 45102 24940 57523 8100
8560 6939 14178 46606 197540 397630 9009 11878
}
)
or (http.request.uri.path contains "xmlrpc")
or (http.request.uri.path contains "wp-config")
or (http.request.uri.path contains "wlwmanifest")
or (cf.verified_bot_category in {"AI Crawler" "Other"})
or (ip.src.country in {"T1"})
Additional Info:
- Action: Block.
Bonus Rules
Now, my goal was to fit the guts firewall into 5 rules so that we can use them on the free plan. But, the power of these security rules is pretty good and you can do a lot with them.
If you have a paid Cloudflare account and can run more than 5 rules, here’s a few others you can consider using. I will add more as time goes on.
If you have the extra time, you could probably combine some of these things into the other rules and still fit them into 5 rules.
Block Suspicious Request Patterns
(http.request.uri.path matches "..(php|asp|aspx|jsp|cgi|pl|sh|bat|cmd)$" and http.request.method eq "GET" and not http.request.uri.path matches "..(jpg|png|gif|css|js|ico|svg|woff|woff2|ttf|eot)$")
Rate Limit High-Risk Endpoints
(http.request.uri.path matches ".(wp-admin|wp-login|admin|login|xmlrpc)." and rate(1m) > 10)

You Need ONEPass To Access This Resource
ONEPass unlocks all protected content across this website. Access members-only videos, courses and playbooks.
Duration
22m 37s
