Table of contents
Cloudflare's Bot Fight Mode and its "block AI bots" switch can answer your RSS feed with a 403 challenge page, and a feed reader or AI agent has no way to solve one. On 1 November 2026 we requested 29 live feeds with three client identities. Two of the 12 behind Cloudflare refused us. None of the 17 others did. This guide shows how to see which kind of refusal you have, and the narrow fix that keeps your bot protection on.
Quick summary
| If you see | It means | Fix | Time |
|---|---|---|---|
403 and cf-mitigated: challenge on /feed/ | A Cloudflare challenge page, not your feed | Skip rule scoped to the feed paths | 10 minutes |
| Only Bot Fight Mode is on (Free plan) | WAF custom rules cannot skip it | Turn it off, or move to Super Bot Fight Mode | 5 minutes |
403 with no cf-mitigated header | Your host, a WordPress security plugin or a WAF | Allow the feed path in that tool | 10 minutes |
200, but the body is HTML | The feed path serves your homepage or a login | Fix the href, see the feed hub guide | 5 minutes |
Direct answer: request the feed with curl -sI, read the status and the cf-mitigated header, then add one Cloudflare custom rule with the Skip action that matches only your feed paths. Do not allow-list the whole site.
Why a working feed returns 403
A feed is a plain file, but Cloudflare's bot products judge the requester, not the file. According to Cloudflare's own Bot Fight Mode documentation, the product issues challenges to traffic that matches known bot patterns, and it "may challenge API or mobile app traffic." A feed reader is that kind of traffic. Open RSS made the same point in October 2024: with Bot Fight Mode or the "AI scrapers and crawlers" option on, readers get a human-verification page they can never complete.
Check E5 looks for a feed at the usual paths and for a <link rel="alternate"> that declares it, per the content checks documentation. A declared feed that answers with a challenge page is declared and unreadable. Our feed census of 340 sites lists "feed refused to bots" as one of five failure types and notes the scanner may not see it. This post is the fix for that row.
Test your feed in 30 seconds
Run the scan first: npx aiscan-cli yoursite.com, then read the E5 line in the content dimension. The scan tells you whether a feed is found and declared. It cannot tell you what a feed reader sees from its own network, so check by hand as well:
FEED=https://example.com/feed/
for UA in "Mozilla/5.0 Chrome/140.0" "Feedly/1.0 (+http://www.feedly.com/fetcher.html)" "curl/8.5.0"; do
echo "== $UA"
curl -s -o /dev/null -D - -A "$UA" "$FEED" | grep -iE '^(HTTP|content-type|cf-mitigated|server)'
done
A healthy feed prints 200 and content-type: application/rss+xml (or application/atom+xml, application/xml, application/feed+json). A challenged one prints 403, content-type: text/html and cf-mitigated: challenge. Cloudflare documents that header: every Challenge Page response carries cf-mitigated set to challenge, whatever the challenge type.
What we measured
We fetched 30 feed URLs on 1 November 2026, one request per identity, from one datacenter address. One URL (a Google blog feed path) returned 404 for all three and was dropped, leaving 29. Redirects were followed.
| Group | Feeds | Refused with 403 | How |
|---|---|---|---|
Served by Cloudflare (server: cloudflare) | 12 | 2 | Both cf-mitigated: challenge |
| Served by anything else | 17 | 0 | One 429 for plain curl at Reddit |
The two refusals differ. Indie Hackers returned 403 to all three identities. Search Engine Land returned 200 to a Feedly-style user agent and 403 to the Chrome string and to curl. So a rule keyed on the user agent can let a named reader in and shut out everything else, which is the opposite of what a verified-bot check is meant to do.
Limits: Both sites also challenged their homepages from our address, so what we saw is a site-wide challenge for one datacenter IP, not proof of a rule scoped to the feed. We cannot tell you how often a residential feed reader is refused. Ten of the 12 Cloudflare feeds answered normally, so the failure needs a bot setting someone turned on.
Fix it: Cloudflare
Which fix applies depends on the product that is blocking you, and the plan you are on decides which products you have.
| Product | Plan | Can a WAF skip rule exempt the feed? |
|---|---|---|
| Bot Fight Mode | Free | No. According to the docs, it runs outside the Ruleset Engine, so Skip, Bypass and Allow have no effect |
| Super Bot Fight Mode | Pro, Business, Enterprise | Yes, with the option All Super Bot Fight Mode Rules |
| Browser Integrity Check | All | Yes, with Skip products |
| "Block AI bots" / AI crawler blocking | Varies | Not stated in the docs we read. Test after you add the rule |
Option 1, Pro plan or above: a skip rule on the feed paths.
- Go to Security > Security rules in the dashboard and select Create rule > Custom rules.
- Name it
Allow feed fetchers. - Under When incoming requests match, choose Edit expression and paste:
(http.request.uri.path in {"/feed/" "/feed.xml" "/rss.xml" "/atom.xml" "/index.xml"}) - Under Then take action, choose Skip.
- Tick All Super Bot Fight Mode Rules. If the feed still fails, also tick Browser Integrity Check under the products list.
- Leave Log matching requests on, then select Deploy.
Use your real feed path from the <link> tag, not this list. Cloudflare's skip options page says you can skip phases or specific products, and that skipping a phase does not skip products outside the Ruleset Engine. That is why the second tick matters.
Option 2, Free plan: Bot Fight Mode cannot be skipped. Your choices are to turn it off under Security > Settings (filter by Bot traffic), or to upgrade. According to Open RSS, allow-listing a reader by IP address is safer than by user agent, because user agents can be faked. That works for a rule on a paid plan, not for Bot Fight Mode.
Do not write a site-wide allow. A rule on /feed/ exposes one cheap, public file. A rule on everything removes the protection you turned on.
Fix it: other blockers
| Blocker | Where to look | Fix |
|---|---|---|
| Host or hosting WAF | Host dashboard firewall log | Allow the feed path in the rule that matched |
| WordPress security plugin | Its firewall or bot log, filtered to /feed/ | Exempt the feed URL, or turn off feed blocking if the plugin has that option |
| Feed disabled on purpose | Plugin or theme setting for feeds | Re-enable it. Our census found WordPress sites with no feed after a plugin or theme change |
Rate limit on /feed/ | Cloudflare Security events or your server log | Raise the limit for that path, see rate limiting without blocking AI crawlers |
Verify the fix
- Re-run the three-identity loop above. All three should print
200with an XML or JSON content type and nocf-mitigatedline. - Run
npx aiscan-cli yoursite.comand read E5. A declared, reachable feed should report pass. - Check Security > Events for the skip rule. Matches should appear within minutes of a fetch.
- Validate the feed against RFC 4287 for Atom, or the JSON Feed 1.1 spec, if the XML itself is suspect.
If it still returns 403, the first debugging step is the cf-mitigated header. Present means Cloudflare is still challenging, so recheck the path in your expression. Absent means the refusal comes from your origin or another layer.
Maintenance
Re-run the loop after any change to bot settings and once a quarter. Every Cloudflare setting above was verified on 1 November 2026 against pages fetched from developers.cloudflare.com, and their last-updated dates run from May to October 2026. A new managed rule can undo a skip.
Next step
Scan your site at aiscan.site and read the E5 line, then browse the other fixes in /guides. If the feed is fine but the crawlers are blocked elsewhere, the Cloudflare AI Crawl Control guide covers per-crawler rules, and the blocked-probe study shows how often a firewall, not the site, caused a failing score.
Frequently asked questions
Why does my RSS feed return 403 when the page itself loads in my browser?
A bot product such as Cloudflare Bot Fight Mode judges the requester, not the file. A browser can pass the check or solve a challenge. A feed reader cannot, so it receives the 403 challenge page. Request the feed with curl -sI and look for cf-mitigated: challenge.
How do I tell a Cloudflare challenge from a missing feed?
A missing feed returns 404. A Cloudflare challenge returns 403 with content-type text/html and a cf-mitigated: challenge header. Cloudflare documents that header as present on every Challenge Page response.
My skip rule is deployed but the feed still returns 403. What now?
Check which product is blocking. Bot Fight Mode cannot be skipped by any WAF rule, so a Free plan needs it turned off. On a paid plan, tick All Super Bot Fight Mode Rules and Browser Integrity Check in the skip options, and confirm the expression matches the exact feed path.
AIScan shows E5 as partial or failing but my feed opens in a browser. Why?
E5 grades whether a feed exists at a conventional path and whether a link tag declares it. Partial usually means the feed is found but not declared. If the feed opens for you but a request from a datacenter gets a challenge, run the three-identity curl test to see what a crawler receives.
Can I skip Bot Fight Mode on the Free plan for just the feed?
No. Cloudflare's documentation says Bot Fight Mode runs outside the Ruleset Engine, so Skip, Bypass and Allow actions have no effect. Turn it off or move to Super Bot Fight Mode on a Pro plan or above.
Is it safe to allow bots on my feed path?
For a public feed, yes. The path serves a small public file that already lists your newest posts. Scope the rule to the feed paths only. A site-wide allow removes the protection you turned on.
The feed returns 403 but there is no cf-mitigated header. Where is it coming from?
Not from a Cloudflare challenge. Check your host's firewall log, a WordPress security plugin's bot or firewall log filtered to /feed/, and any rate limit. Allow the feed path in the rule that matched.
Does blocking AI bots also block my feed?
It can. Open RSS reported that Cloudflare's AI scrapers and crawlers option blocks RSS readers along with AI bots. Cloudflare's documentation we read does not say whether a skip rule covers that option, so test the feed with the curl loop after you add the rule.

About the author
M Asif Rahman
Entrepreneur, curious about AI
I have been building companies for a long time, and lately most of my curiosity goes to AI. AIScan is a small personal project I built on a flight from Dubai to Narita. I use it to understand how ready the web is for AI agents, and I share what the scans teach me.
Related guides
ChatGPT Says It Can't Access Your Website: Five Causes and How to Tell Which
When ChatGPT says it cannot open your page, one of five things happened, and a short script of four curl requests sorts four of them in about a minute. The fifth is that ChatGPT never tried. This…
Block Fake AI Crawlers From Probing .env and .git Files
Some of the traffic that calls itself GPTBot or ClaudeBot is not a crawler. It is a scanner that borrowed a famous name and asks your server for /.env, a .git folder or a wpconfig.php.bak. The fix is…
AI readiness setup guide by platform (2026)
Verified 17, 18, 20 and 22 October 2026. Updated on 22 October 2026. An AIready site needs six things: a robots.txt that names AI crawlers D1, B2, a sitemap D2, a declared feed E5, an llms.txt C2,…
