---
title: "Your RSS Feed Returns 403 to Feed Readers and Agents: Cloudflare and Firewall Rules That Block It"
slug: rss-feed-403-cloudflare-bot-protection
published: 2026-11-01T13:12:24.822719+00:00
updated: 2026-11-01T13:12:24.822719+00:00
author: "M Asif Rahman"
author_url: https://ar.bd
category: "AI Readiness"
tags: check:E5, platform:cloudflare, platform:wordpress, RSS, Cloudflare, bot protection, troubleshooting
description: "Your RSS feed returns 403 to feed readers and agents? Cloudflare Bot Fight Mode, AI-bot blocks and firewalls can cause it. Test with curl, then fix one path."
url: https://aiscan.site/blog/rss-feed-403-cloudflare-bot-protection
---

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](/blog/add-rss-feed-declare-in-head) | 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](https://developers.cloudflare.com/bots/get-started/bot-fight-mode/), 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](https://openrss.org/blog/using-cloudflare-on-your-website-could-be-blocking-rss-users): 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](/docs/checks/content). A declared feed that answers with a challenge page is declared and unreadable. Our [feed census of 340 sites](/blog/rss-atom-json-feed-census) 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:

```bash
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](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/detect-response/): 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](https://developers.cloudflare.com/bots/get-started/bot-fight-mode/), 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.**

1. Go to **Security > Security rules** in the dashboard and select **Create rule > Custom rules**.
2. Name it `Allow feed fetchers`.
3. Under **When incoming requests match**, choose **Edit expression** and paste:
   `(http.request.uri.path in {"/feed/" "/feed.xml" "/rss.xml" "/atom.xml" "/index.xml"})`
4. Under **Then take action**, choose **Skip**.
5. Tick **All Super Bot Fight Mode Rules**. If the feed still fails, also tick **Browser Integrity Check** under the products list.
6. 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](https://developers.cloudflare.com/waf/custom-rules/skip/options/) 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](/blog/rate-limit-ai-crawlers-without-blocking) |

## Verify the fix

1. Re-run the three-identity loop above. All three should print `200` with an XML or JSON content type and no `cf-mitigated` line.
2. Run `npx aiscan-cli yoursite.com` and read **E5**. A declared, reachable feed should report pass.
3. Check **Security > Events** for the skip rule. Matches should appear within minutes of a fetch.
4. Validate the feed against [RFC 4287](https://www.rfc-editor.org/rfc/rfc4287) for Atom, or the [JSON Feed 1.1 spec](https://www.jsonfeed.org/version/1.1/), 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](https://aiscan.site/) and read the E5 line, then browse the other fixes in [/guides](/guides). If the feed is fine but the crawlers are blocked elsewhere, [the Cloudflare AI Crawl Control guide](/blog/cloudflare-ai-crawl-control-setup) covers per-crawler rules, and [the blocked-probe study](/blog/blocked-probe-share-of-failures) shows how often a firewall, not the site, caused a failing score.

