ERR_TOO_MANY_REDIRECTS means the browser followed a chain of redirects that never resolved to an actual page — either looping back to a URL it already visited, or exceeding the browser's maximum redirect count (typically around 20) — and this almost always points to a genuine misconfiguration somewhere in your redirect logic, reverse proxy, or CDN settings.
This error means a sequence of HTTP redirects (3xx responses with a Location header) formed a cycle or exceeded the browser's redirect limit before ever reaching a final, non-redirecting response — the browser gives up and reports this rather than looping indefinitely.
Why This Error Happens
Redirect loops most commonly happen from conflicting configuration between layers that each think they're responsible for enforcing a specific protocol or domain — a CDN or load balancer redirecting HTTP to HTTPS, while the origin server behind it (seeing the request arrive as HTTP internally, even though the client used HTTPS) redirects it back to HTTP again, creating an infinite back-and-forth. Similar patterns occur with www vs. non-www redirect logic implemented inconsistently across multiple layers, or authentication/login redirect logic that redirects unauthenticated users to a login page that itself incorrectly requires authentication.
Reproducing the Error
A CDN and origin server disagreeing about the protocol:
CDN/Load Balancer: force HTTP -> HTTPS redirect
Origin server (behind CDN, sees request as HTTP due to how the proxy forwards it): also force HTTP -> HTTPS redirect
Result: browser gets redirected HTTPS -> HTTPS -> HTTPS -> ... infinitely,
since the origin never sees the request as "already HTTPS"
Conflicting www redirect rules across layers:
# nginx: redirect non-www to www
server {
server_name example.com;
return 301 https://www.example.com$request_uri;
}
# CDN/DNS-level rule (elsewhere): redirect www to non-www
# Result: example.com -> www.example.com -> example.com -> ... loop
Core Concepts Behind This Error
The most common real-world cause is a mismatch between what protocol your CDN/proxy sees versus what your origin server thinks it's handling, particularly around SSL termination — many CDNs terminate HTTPS at the edge and forward plain HTTP to the origin, and if your origin server doesn't check the X-Forwarded-Proto header (instead checking the request's literal protocol, which now appears as HTTP) it incorrectly re-triggers an HTTPS redirect.
Redirect rules configured at multiple layers (DNS/CDN, load balancer, application framework, .htaccess) can easily conflict without any single layer being "wrong" in isolation — each individual rule might be reasonable, but together they form a cycle; diagnosing this requires tracing the actual redirect chain, not just reviewing each layer's configuration separately.
Application-level authentication redirect loops are a distinct but related pattern — redirecting unauthenticated users to a login route that itself is incorrectly gated behind the same authentication check, creating a loop entirely within application logic rather than infrastructure configuration.
Browser cache of a previous redirect response can make a fix appear not to work immediately, since a cached 301 (permanent) redirect might be served by the browser without even re-checking the server — clearing cache or testing in an incognito window is necessary to confirm a fix actually took effect.
Fixing "ERR_TOO_MANY_REDIRECTS"
Fix 1: Trace the actual redirect chain to see exactly where the loop occurs, using a tool that shows each hop rather than guessing:
curl -IL https://example.com
# Shows the full chain of redirects and their Location headers, revealing the loop
Fix 2: For CDN/SSL-termination mismatches, configure your origin server to respect the X-Forwarded-Proto header rather than checking the request's literal protocol:
// Express example, trusting the proxy's forwarded protocol header
app.set("trust proxy", true);
app.use((req, res, next) => {
if (req.secure || req.headers["x-forwarded-proto"] === "https") {
return next(); // already HTTPS as far as the client is concerned — don't redirect
}
res.redirect(`https://${req.headers.host}${req.url}`);
});
Fix 3: For www/non-www conflicts, consolidate the redirect rule to a single layer (DNS/CDN or application, not both), removing the duplicate/conflicting rule elsewhere:
# Single source of truth for this redirect, at the layer closest to the client
server {
server_name example.com;
return 301 https://www.example.com$request_uri;
}
# Ensure no other layer (CDN rule, app middleware) also redirects www -> non-www
Fix 4: For application-level authentication loops, verify the login route itself is excluded from the authentication check that redirects to it:
if (!isAuthenticated(req) && req.path !== "/login") {
return res.redirect("/login"); // "/login" itself must be excluded from this condition
}
Why Does Clearing the Browser Cache Sometimes Fix This When the Server-Side Fix Didn't Seem to Work?
Because permanent (301) redirects are aggressively cached by browsers — once a browser has cached a 301 redirect for a URL, it may reuse that cached redirect without even contacting the server again to check if the configuration changed, meaning your server-side fix is genuinely correct but the browser is still acting on stale, cached redirect information. Testing in an incognito window (or explicitly clearing cache) confirms whether a fix actually resolved the loop versus just being masked by cache.
Preventing This Error in Production
Consolidate redirect logic (protocol enforcement, www normalization, trailing slashes) to a single, well-documented layer rather than spreading it across CDN, load balancer, and application code where conflicts are easy to introduce unnoticed. When using a CDN or reverse proxy that terminates SSL, always configure your origin application to trust and check forwarded protocol headers rather than the request's literal connection protocol, and test redirect changes with curl -IL (bypassing browser cache) to verify server behavior directly.
If you hit this error, use curl -IL to see the actual redirect chain first — it reveals exactly where the loop occurs and which layer's rule needs fixing, rather than guessing based on configuration review alone.