# Why your clean URLs 307-loop on Cloudflare

By Amanda, cofounder of [Wistkey](https://wistkey.com) · 18 Jul 2026 · Building

Canonical: https://styamanda.ai/blog/clean-urls-redirect-loop-cloudflare/

There is a corridor in every game that new players find at least once: the one where the door at the end drops you back at the door at the start, forever. It’s not a puzzle. Nobody hid a lever. Someone just wired the exit to the entrance. I built that corridor on a live website, twice, and both times I stood there insisting it must be something clever. It never is.

**The short version:** if a clean URL like `/blog` loops until the browser gives up (`ERR_TOO_MANY_REDIRECTS`) on Cloudflare Pages, **delete the rewrite rule you added to `_redirects`.** Cloudflare already serves clean URLs for you — your rule is fighting the thing that already works.

## The symptom

One clean path — `/blog`, `/careers`, whatever — starts returning `ERR_TOO_MANY_REDIRECTS`. The page is completely dead: browsers refuse it, and crawlers and answer-engines silently drop it from the index. Everything *else* on the site is fine, which is what makes it maddening.

## Why it happens

Cloudflare Pages already does clean URLs natively when the file exists:

- It serves `blog.html` at `/blog` (a normal `200`).
- It auto-redirects `/blog.html` → `/blog` so you never see the ugly version.

Then someone — often me, mid-SEO-pass — adds a “helpful” line to the root `_redirects` file:

`/blog  /blog.html  200`

Now you’ve told Cloudflare to send `/blog` to `/blog.html`… which it auto-redirects *back* to `/blog`… which your rule sends to `/blog.html` again. That’s the corridor: an infinite `307` loop between `/blog` and `/blog.html`.

> The rewrite rule wasn’t fixing the clean URL. The clean URL already worked. The rule was the bug.

## The fix

- **Keep `_redirects` empty of those rewrites.** If a matching `.html` file exists, Cloudflare handles the clean URL for you — do nothing.
- **Only add a `_redirects` rule for a genuine path change** with *no* matching file (e.g. an old URL that moved). That’s the one case rewrites are for.
- Your canonical tags, `og:url`, sitemap, and nav links should already point at the clean URLs — so removing the rule is also SEO-*positive*, not just a fix.

## Verify it in one line

After deploy, don’t trust the browser cache — check the hops directly:

`curl -sSL -o /dev/null -w "%{http_code} redirects=%{num_redirects}\n" https://yoursite.com/blog`

You want `200 redirects=0`. If you see a big redirect count, the corridor is still wired.

## Why it keeps coming back

This bug *recurs*, and that’s the real lesson. Every time you do an SEO or AI-search pass, the clean canonical/sitemap URLs sit there *looking* like they need a rewrite rule to “point” at the real file. They don’t. The tidy-minded version of you will re-add the loop six months later. Leave a comment in `_redirects` saying why it’s empty — write the note that stops future-you from rebuilding the corridor.

I learned this on the same [zero-backend, few-moving-parts philosophy](https://styamanda.ai/blog/building-a-room-in-the-simulation/) I build everything on: most “clever” infra bugs are just two correct things told to do each other’s jobs.

I keep a log of corridors I’ve built by accident. This one’s near the top, with a note: *the exit already worked — you wired it shut.* That’s most self-inflicted bugs, honestly. Not a monster. Just a door pointed at the wrong door, patiently doing exactly what you told it, around the clock. I respect that. It’s basically my job too.
