Redirect Loop Doctoran ARLing tool

ERR_TOO_MANY_REDIRECTS? Find the loop between Cloudflare, your server and your app.

Paste the redirect chain from curl -IL (or a browser Network tab), your Cloudflare SSL mode, and your server and app's HTTPS/www/trailing-slash settings. Get the exact pair of rules fighting each other, and the fix.

01

Three reasons two correct-looking rules cancel each other out.

A redirect loop is almost never one broken rule. It's two rules, in two different layers, each individually reasonable, disagreeing about the same request.

  1. Cloudflare vs. origin.

    Flexible SSL sends every request to your origin as plain HTTP. If your origin then redirects HTTP to HTTPS, Cloudflare sends the next request as HTTP again. Forever.

  2. App vs. proxy header.

    An app that forces HTTPS by checking its own connection's scheme, instead of the X-Forwarded-Proto header, always sees HTTP behind a proxy and always redirects.

  3. Server vs. app canonical URL.

    Your server redirects to www while WordPress's siteurl (or another app's base URL) points at the apex domain, or the two disagree on a trailing slash.

02

Paste what you see. Get the exact repeating pair.

Nothing you type is sent anywhere, and this tool never fetches your URL itself. The check runs in your browser, against documented Cloudflare, nginx, WordPress, Laravel, Django, Rails, Vercel and Netlify behaviour.

fn RedirectLoopDoctor.diagnose(config)
client-side, no network
The loop
Paste curl -sIL output directly, or a list of URLs, one per line. This finds the exact repeating pair, not just that something loops.
Cloudflare
Paste the rule text as shown in the dashboard. Only used to spot a rule that forwards to itself.
Server / reverse proxy
App
Result · idle
Fill in the form and press Diagnose or ⌘↵ to see the result.
status
idle
not run yet

03

One function. Config in, diagnosis out.

No server, no API key, no signup. doctor-loop.js is plain JavaScript: read it, fork it, or run it in your own scripts or CI.

doctor-loop.js 0 dependencies
import { diagnose } from './doctor-loop.js';
// or, loaded globally: const { diagnose } = window.RedirectLoopDoctor;

const result = diagnose({
  url:        'https://example.com/',
  chain:      'HTTP/1.1 301 ...\nLocation: ...',
  cloudflare: { proxied, sslMode, alwaysHttps, pageRules },
  server:     { type, forcesHttps, trustsXForwardedProto, wwwRule },
  app:        { type, siteUrl, forcesHttps, trailingSlash },
});

// result
{
  "status":     "fail" | "warn" | "pass",
  "summary":    "…",
  "expected":   { sslMode, cloudflareToOriginScheme, recommendedSslMode, … },
  "problems":   [ { severity, code, message, path, value, fix } ],
  "fixes":      [ { title, value, where } ],
  "checklist":  [ "…" ],
  "disclaimer": "…"
}

Everything runs client-side. The form above calls this exact function in your browser. There is no backend, no API key, and this tool never fetches the URL you're diagnosing.

If you paste a chain, it parses every Location: header and URL, finds the first exact repeat, and diffs the two hops on either side of it to say precisely what's flipping: scheme, www vs. apex, or trailing slash. It also checks your Cloudflare/server/app settings directly for the usual structural causes, even without a chain.

Free and open source. Found a case it gets wrong? Open a GitHub issue on the repo. No ads, and no tracking beyond anonymous usage counts.

04

Free.

No account, no payment, no usage limit: it runs as a static page in your browser, so there is no server to bill for.

05

Questions developers actually search for.

Straight answers to the same ERR_TOO_MANY_REDIRECTS questions this tool diagnoses, for when you just need the answer, not the checker.

What causes ERR_TOO_MANY_REDIRECTS?

Two or more layers in front of your site each redirect the request in a way the other layer immediately undoes: Cloudflare's SSL mode versus your origin's own HTTPS redirect, your server's www/apex or trailing-slash rule versus your app's own canonical URL, or your app forcing HTTPS without trusting the X-Forwarded-Proto header from whatever is proxying it. The browser gives up after roughly 20 hops and shows ERR_TOO_MANY_REDIRECTS.

Why does Cloudflare Flexible SSL create a redirect loop?

In Flexible mode, Cloudflare always sends the request to your origin as plain HTTP, regardless of what the visitor used. If your origin (web server or app) then redirects that HTTP request to HTTPS, Cloudflare sends the next request as HTTP again, and the two sides bounce forever. Cloudflare's own fix is to switch to Full or Full (strict) once your origin has a TLS certificate, rather than removing the origin's HTTPS redirect.

How do I fix a WordPress redirect loop behind Cloudflare?

Check three things: Cloudflare's SSL/TLS mode should be Full (strict), not Flexible, if your origin forces HTTPS; WordPress's own siteurl and home options (Settings > General, or WP_HOME/WP_SITEURL in wp-config.php) must use the same scheme and www/apex host your server already redirects to; and if WordPress is behind a proxy, wp-config.php needs to trust X-Forwarded-Proto so it doesn't redirect http-as-seen-by-PHP back to https forever.

Why does my app redirect to https in a loop behind a load balancer?

A load balancer or reverse proxy that terminates TLS forwards your app plain HTTP on the inside, even for an originally-HTTPS visit. If your app decides whether to force HTTPS by looking at its own connection's scheme (nginx's $scheme, Django's request.is_secure(), etc.) instead of the X-Forwarded-Proto header the proxy sets, it always sees http and always redirects, and the proxy always downgrades the next request back to http. Fix it by trusting X-Forwarded-Proto: SECURE_PROXY_SSL_HEADER in Django, TrustProxies in Laravel, HTTP_X_FORWARDED_PROTO in WordPress, config.force_ssl with trusted proxies in Rails.

How do I see the redirect chain?

Run curl -sIL https://your-url/ in a terminal: it prints every hop's status code and Location header until it stops or gives up. Paste that whole output into this tool's chain field. You can also open your browser's Network tab, reload with "Preserve log" on, and copy the sequence of requested URLs.

Does this tool fetch my site?

No. Everything runs in your browser as plain JavaScript. It never makes a network request to the URL you're diagnosing; it only reads the config fields and chain text you paste in and compares them against documented Cloudflare, nginx, WordPress, Laravel, Django, Rails, Vercel, and Netlify behaviour.