ERR_TOO_MANY_REDIRECTS: what it means and how to fix it
Kofi Agyem, Founder and CEO, CloudzyroPublished · 5 min read
On this page
ERR_TOO_MANY_REDIRECTS means a page keeps redirecting in a loop. Fix it as a visitor, and find the loop as an owner, including Cloudflare's Flexible SSL.
1. The short answer
ERR_TOO_MANY_REDIRECTS means the site sent your browser in a circle: address A redirects to B, and B redirects back to A. Browsers follow up to 20 redirects for a page, then stop and show this error instead of looping forever.
As a visitor, clear the site's cookies and try again. As the site owner, the loop is almost always two settings fighting: HTTP versus HTTPS, www versus the bare domain, or Cloudflare's Flexible SSL mode with a server that forces HTTPS.
2. What you'll see
- Chrome: This page isn't working. example.com redirected you too many times. Try deleting your cookies. ERR_TOO_MANY_REDIRECTS.
- Edge: This page isn't working right now, with the same code.
- Firefox: The page isn't redirecting properly. Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
- Safari: Safari can't open the page because too many redirects occurred.
- curl:
Maximum (50) redirects followedwith-L.
3. What causes it
- Cloudflare Flexible SSL with a server that forces HTTPS. In Flexible mode, visitors reach Cloudflare over HTTPS but Cloudflare reaches your server over plain HTTP. Your server sees HTTP, redirects to
https://, Cloudflare passes the redirect to the browser, the browser asks again over HTTPS, and round it goes. - HTTP and HTTPS rules that disagree, such as a host setting that forces HTTPS while the app redirects HTTPS back to HTTP.
- www and the bare domain redirecting to each other. For example, your DNS host forwards
example.comtowww.example.com, and your app redirectswwwback toexample.com. - An app behind a proxy that can't tell it's on HTTPS. The proxy terminates HTTPS and talks HTTP to the app; the app thinks the visit is insecure and redirects. It should trust the proxy's
X-Forwarded-Protoheader. - WordPress address settings (WordPress Address and Site Address) that don't match the real address.
- Cookie or login loops. A login page redirects to the dashboard, which can't read the session cookie and redirects back.
- Redirect rules that match their own target, such as a rule sending every path to
/en/that also matches/en/.
4. Fixes for visitors, quickest first
- Open the page in an incognito window. If it works, a cookie is the problem.
- Clear the site's cookies. In Chrome, click the icon left of the address, then Cookies and site data, and delete them. Or Settings, Privacy and security, Third-party cookies, See all site data and permissions, and search for the site.
- Check your date and time, since expired-looking cookies can cause login loops.
- Turn off extensions that change how pages load, such as HTTPS or privacy add-ons.
- If it still loops, the site is misconfigured. Tell the owner.
5. Fixes for site owners
- Trace the chain with curl (below) to see the exact loop.
- On Cloudflare, set SSL/TLS encryption mode to Full (strict) and make sure your server has a valid certificate. That's the fix for the Flexible loop, and it encrypts the hop to your server too. If you use Cloudflare's Always Use HTTPS, remove any rule on your server that redirects HTTPS back to HTTP.
- Pick one main address,
https://www.example.comorhttps://example.com, and redirect everything else to it in one place only. See www vs non-www. - Behind a proxy, make the app trust
X-Forwarded-Proto. In Express,app.set("trust proxy", true). In Laravel, the TrustProxies middleware. In Django,SECURE_PROXY_SSL_HEADER. - In WordPress, make the WordPress Address and Site Address both the real HTTPS address. If you're locked out, set
WP_HOMEandWP_SITEURLinwp-config.php. - Check redirect rules in
.htaccess, nginx, your framework and your host, and make sure no rule matches its own target. - For login loops, check the session cookie's
Domain,SecureandSameSitesettings match the address people use.
6. On a Cloudzyro site
On Cloudzyro Sites & Apps, HTTPS is handled for you, and the bare domain's A record to 173.234.137.167 forwards visitors to https://www.example.com, keeping the rest of the address. So if your main address is www, don't also redirect www to the bare domain in your app or framework settings, or visitors will bounce between the two. Either keep www as the main address, or add the bare domain to the site directly, which needs a DNS provider that supports CNAME, ALIAS, ANAME or flattened records on the bare domain. The custom domain docs explain both options.
If your DNS is at Cloudflare, set the records for your Cloudzyro domain to DNS only (gray cloud), not Proxied. Your site still gets Cloudflare's protection through us.
7. A worked example
A site owner moves DNS to Cloudflare with the orange cloud on. The site, which already forces HTTPS in nginx, now shows ERR_TOO_MANY_REDIRECTS.
curl -sIL https://www.example.com/shows301withlocation: https://www.example.com/, again and again, each withserver: cloudflare.- Cloudflare's SSL/TLS mode is Flexible, so Cloudflare fetches the page from nginx over plain HTTP, and nginx answers with its redirect to HTTPS every time.
- The server already has a valid certificate, so they set the mode to Full (strict).
- Cloudflare now connects over HTTPS, nginx serves the page instead of redirecting, and the loop is gone.
8. How to check
# Follow the redirects and print each step's status and Location
curl -sIL --max-redirs 10 https://example.com/ | grep -iE "^HTTP|^location"
# Start from plain HTTP and the other host name too
curl -sIL --max-redirs 10 http://example.com/ | grep -iE "^HTTP|^location"
curl -sIL --max-redirs 10 https://www.example.com/ | grep -iE "^HTTP|^location"
# Windows PowerShell: use curl.exe, not the curl alias
curl.exe -sIL --max-redirs 10 https://example.com/A loop shows as the same two location: values repeating. The server: header on each response tells you which layer sent each redirect, for example cloudflare or nginx, so you know where to change the rule. In Chrome DevTools, tick Preserve log in the Network panel and reload to see the same chain.