Tutorials

ERR_TOO_MANY_REDIRECTS: How to Break a Redirect Loop

By Published 10 min read
ERR_TOO_MANY_REDIRECTS: How to Break a Redirect Loop

TL;DR

The browser gave up on a redirect loop. Fix it as a visitor in two minutes, see the loop with curl, and repair the server rules causing it.

On this page

What ERR_TOO_MANY_REDIRECTS Means#

A redirect is a normal, healthy instruction: the server answers with a 3xx status and a Location header, and the browser goes where it points, as specified in the HTTP redirection semantics. ERR_TOO_MANY_REDIRECTS appears when following those instructions never ends: page A sends the browser to page B, B sends it back to A, and after roughly twenty hops the browser concludes no content is coming and gives up. Chrome, Edge, and Firefox all enforce a limit in that neighborhood, and HTTP clients do the same; the recorded lab behind this article watched a plain fetch abort a two-URL loop with a redirect-count error while a normal three-hop chain resolved fine.

That distinction is the whole mental model: redirects are not the problem, circles are. Sites legitimately redirect from HTTP to HTTPS, from the bare domain to www, from old URLs to new ones, and each hop costs one round trip but arrives somewhere. The error fires only when two or more redirect rules disagree about the final destination and keep handing the visitor to each other forever.

Who can fix it depends on where the circle lives. A loop conditioned on your cookies is fixable from your chair in two minutes, and the next section does exactly that. A loop baked into the site's redirect rules or its CDN configuration loops for every visitor on Earth, and no amount of cache clearing on your side will change what the server keeps answering.

EF-04 / Failure pointWhere ERR_TOO_MANY_REDIRECTS happens in the request path
ERR_TOO_MANY_REDIRECTSLocation loop

Client

browser or CLI

DNS

name → address

TCP

SYN / SYN-ACK

TLS

handshake + cert

Origin

3xx answers chase each other

Hops after the highlighted failure never run — everything downstream is ruled out before you start.

Every hop works — the origin keeps answering with redirects that point at each other until the browser gives up.

Fix It as a Visitor: the Two-Minute Version#

Start with the test that tells you whether you can fix it at all: open the same URL in a private or incognito window. Incognito starts with no cookies for the site, so if the page loads there, the loop is conditioned on stale state in your normal profile and you can clear it; if it loops in incognito too, the site is broken for everyone and your only moves are waiting or telling the owner.

When incognito works, clear cookies for that one site rather than nuking your whole browser history. In Chrome, the tune icon left of the address bar leads to site settings and a per-site delete; the browser's clear-data dialog also accepts a single domain. The lab shows mechanically why this works: its login route answers with a self-redirect for as long as a stale session cookie is presented, and returns 200 the moment the cookie is gone. Expired or contradictory session state is exactly what real sites loop on, and deleting the site's cookies replaces the poisoned state with a clean first visit. Expect to be signed out of that site afterward; that is the fix working, not a side effect to avoid.

Two lesser causes round out the visitor list. Extensions that rewrite requests, force HTTPS, or manage cookies can fight a site's own rules, so retry with extensions off before blaming the site. And check the URL you actually typed or bookmarked: an old bookmark pointing at a retired hostname can enter a redirect pair the site no longer maintains coherently.

See the Loop Yourself#

You do not have to guess what the loop looks like; two tools print it. The quickest is curl with a small redirect budget, which follows the chain and shows every hop:

curl -sIL --max-redirs 8 https://example.test/a

HTTP/1.1 302 Found
Location: /b

HTTP/1.1 302 Found
Location: /a

curl: (47) Maximum (8) redirects followed

Read the Location lines top to bottom: the moment a URL repeats, you are holding the circle in your hands, and the pair of rules that disagree are named right there. The lab's manual-mode check records the same thing programmatically: /a answers 302 toward /b, /b answers 302 toward /a, and no content ever arrives.

In the browser, DevTools' Network tab with "Preserve log" enabled shows the same chain as a stack of 301 and 302 rows before the error page. Two details are worth reading off it. The status codes matter: 301 responses are cached aggressively by browsers, so a fixed site can keep looping for returning visitors until they clear cache, one more reason a loop that survives your fix attempt may still be repaired server-side. And the cookie column tells you whether each hop is setting or expecting state, which is the signature of the login-loop family from the previous section.

Site-Owner Causes, Ranked#

On the server side, almost every loop is two well-intentioned rules disagreeing, and the ranking is stable across stacks. The champion is the CDN SSL-mode conflict described in Cloudflare's too-many-redirects guide: the CDN fetches from your origin over plain HTTP while your origin forces HTTPS, so the origin redirects every CDN fetch back to HTTPS, forever. The fix is making the CDN-to-origin leg encrypted (full SSL mode with a certificate on the origin) instead of stacking more redirects.

Second place: canonicalization rules fighting across layers. The CDN redirects www to the bare domain while the origin redirects the bare domain to www, or one layer strips trailing slashes while another adds them. Each rule is fine alone; together they are a tennis match. Decide each canonical form in exactly one layer.

Third: application-level HTTPS enforcement that cannot see it is already behind a TLS-terminating layer, covered in its own section next. Fourth: authentication flows that bounce between a login page and a protected page whose session validation disagrees, the server-side twin of the visitor cookie loop. And fifth: geo, language, or A/B redirects whose conditions overlap so two variants claim the same visitor. The repair discipline is the same for all of them: enumerate every layer that can redirect (CDN, load balancer, web server, framework, plugin), list each rule's condition and target, and make one layer own each decision, per the general model in MDN's redirections guide.

The X-Forwarded-Proto Trap#

One server-side cause earns its own section because it hides in plain sight on every stack that sits behind a CDN, load balancer, or reverse proxy. The TLS-terminating layer talks to your application over plain HTTP, so from the application's point of view every request is insecure. If the application enforces HTTPS by inspecting its own connection, it redirects every request to HTTPS, the proxy fetches the HTTPS version by making another plain-HTTP request to the app, and the circle is complete without any rule looking wrong in isolation.

Intermediaries announce the original scheme in a forwarded header, most commonly X-Forwarded-Proto, and the fix is teaching the application to trust it instead of the socket it sees. Every serious framework has the switch: trusted-proxy settings that make request-is-secure checks read the forwarded header, a one-line change that ends the loop. Cloud platforms and WordPress installs behind CDNs hit this constantly, which is why plugin-stacked HTTPS enforcement plus a CDN so reliably reproduces the error.

Two cautions come with the switch. Trust the header only when a proxy you control sets it, because trusting arbitrary client-supplied forwarded headers lets visitors lie about their scheme and address. And after the fix, remove the now-redundant redirect from the layer that should not own it, so the decision lives in exactly one place. For the wider picture of what intermediaries change about a request on its way through, the proxy fundamentals guide traces the full path.

Redirect Budgets in Code and Collection Pipelines#

Everything above also applies when the client is your own software rather than a browser, with one addition: you choose the redirect budget. Fetch in Node and browsers gives up after about twenty hops, curl's --max-redirs flag sets the cap explicitly, and Python's requests library defaults to thirty. The lab's first check is exactly this behavior: the client followed the loop until its budget ran out, then failed with a redirect-count error rather than hanging forever. That is the correct design to copy: a finite budget, a loud error naming the last URLs, and no retry, because a loop retried is just the same loop again.

For data-collection pipelines, redirect handling is quietly a correctness and budget issue. Every hop is a full round trip that counts against your per-source request budget, so a source whose URLs all bounce through a canonicalization hop costs double until you collapse the chain and store final URLs instead of entry URLs. Logging the chain per fetch pays for itself the first time a source restructures: a spike in hops per page is an early warning that entry URLs went stale. And a sudden appearance of loops on a source that worked yesterday usually means your stored session state went stale, the pipeline twin of the visitor cookie fix, so clearing the cookie jar for that source belongs in the standard remediation list before anything heavier.

One boundary stays firm: when a redirect loop guards authentication, the fix is valid session handling through the source's sanctioned flow, never crafting state to slip past it.

Frequently Asked Questions

How do I fix ERR_TOO_MANY_REDIRECTS?
Test the page in an incognito window first. If it loads there, clear cookies for that specific site and retry; stale session cookies are the classic visitor-side cause. If it loops in incognito too, the site's own redirect rules are circular, and only the site owner can repair that, most often a CDN SSL-mode or www-versus-bare-domain conflict.
What causes ERR_TOO_MANY_REDIRECTS?
Two or more redirect rules that disagree about the final destination and keep handing the request to each other: HTTPS enforcement fighting a TLS-terminating proxy, www and bare-domain rules in different layers, expired session cookies bouncing between login and protected pages, or overlapping geo and language redirects. The browser follows about twenty hops, then gives up.
Does clearing cookies for the site log me out?
Yes, for that site only. Clearing a single site's cookies discards its session state, which is precisely the point: the loop was conditioned on stale state the server kept rejecting. You sign back in once and the fresh session works. Your other sites, passwords, and history are untouched if you clear per-site rather than the whole browser.
Why does the error mention Cloudflare so often?
Because the most common server-side loop is a CDN SSL-mode conflict: the CDN fetches the origin over plain HTTP while the origin forces HTTPS, so every fetch gets redirected back at itself. Cloudflare fronts a large share of the web, so its flexible-SSL misconfiguration shows up constantly. The owner-side fix is encrypting the CDN-to-origin leg, not adding more redirects.
Why does a streaming or shopping app show a redirect error?
App webviews carry their own cookie stores, so the same stale-state loop happens inside the app. Clearing the app's storage or cache, or signing out and back in, is the app equivalent of clearing site cookies. If every device and account loops at once, the service's own redirect rules broke, and waiting is the only client-side option.
Are redirects bad for performance or SEO?
Chains cost one round trip per hop, so collapsing multi-hop chains to a single redirect is worth doing on both counts. Loops are simply broken: crawlers abandon them the way browsers do, and pages behind a loop drop out of search once recrawled. Keep necessary redirects, one hop each, each decision owned by exactly one layer.

Related reading

Ready to scale your data collection?

Join 8,000+ customers on Databay: 34M+ residential IPs across 200+ countries, pay as you go.

Pricing, order minimums, and traffic validity vary by product.