This page isn't working example.com redirected you too many times. ERR_TOO_MANY_REDIRECTS
ERR_TOO_MANY_REDIRECTS means the browser followed a chain of redirects that never arrived anywhere and gave up - Chrome stops after about twenty hops. Almost always, two rules disagree about which URL is canonical and each sends the request back to the other.
Is This You or the Site?
Step 1: Try a private window
Open the URL in an incognito or InPrivate window.
| Result | Meaning | Go to |
|---|---|---|
| Loads in private, loops in your normal window | A cookie on your profile drives the loop | Visitor-side fix |
| Loops in private too | The site is misconfigured | Site-owner fixes |
Private windows start with no cookies, which isolates by far the most common visitor-side cause in a single step.
Step 2: Trace the chain
This is the step most guides skip, and it usually names the culprit outright:
curl -sIL https://example.com | grep -Ei "^(HTTP|Location)"
Typical output for a loop:
HTTP/2 301
location: https://www.example.com/
HTTP/2 301
location: https://example.com/
HTTP/2 301
location: https://www.example.com/
Two rules, each undoing the other. Our redirect chain checker shows the same chain from outside your network if you would rather not use a terminal.
Watch for the pattern where the scheme flips between http and https on alternate hops - that points at the TLS termination causes below rather than at a rewrite rule.
Visitor-Side Fix
If it loads in a private window, clear cookies for that one site rather than everything.
Chrome / Edge: click the icon at the left of the address bar → Cookies and site data → Manage on-device site data → delete the entries for that site. Or open chrome://settings/content/all, search the domain, and remove it.
Then reload. If it now works, a stale session cookie was the cause - typically an application that redirects to a login page, sets a cookie, rejects that same cookie, and redirects again.
If clearing cookies does not help and private mode also loops, the problem is not on your machine and there is nothing further you can safely do as a visitor.
Site-Owner Fixes
1. Cloudflare (or any CDN) SSL mode
The single most common cause of a scheme-flipping loop.
With Cloudflare's SSL mode set to Flexible, Cloudflare connects to your origin over plain HTTP. If your origin also redirects HTTP to HTTPS, it sends the visitor back to Cloudflare, which connects over HTTP again - forever.
Fix: install a certificate on the origin and set SSL mode to Full (strict) in the Cloudflare dashboard under SSL/TLS. Flexible mode leaves the Cloudflare-to-origin leg unencrypted regardless, so this is worth fixing on its own merits.
Watch for the same shape with any proxy that speaks HTTP to the backend.
2. Load balancer terminating TLS
The same loop without a CDN. The load balancer terminates TLS and forwards plain HTTP; the application sees http, decides the request is insecure, and redirects to https.
The fix is to make the application trust the forwarded scheme header.
Express:
app.set('trust proxy', 1);
Django:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
nginx as the proxy:
proxy_set_header X-Forwarded-Proto $scheme;
3. WordPress siteurl and home mismatch
WordPress redirects to its configured canonical URL. If siteurl and home disagree with what the server serves - one http, the other https, or one with www and one without - the two redirect at each other.
wp option get siteurl
wp option get home
Both should be the exact canonical URL, matching in scheme and in www. Set them:
wp option update siteurl 'https://example.com'
wp option update home 'https://example.com'
If the site loops badly enough to lock you out of the admin, pin the values in wp-config.php temporarily:
define('WP_HOME', 'https://example.com');
define('WP_SITEURL', 'https://example.com');
4. Rewrite rules fighting
Pick one canonical form and enforce it in one place. The loop appears when a rule in .htaccess, another in the nginx server block, and a third in the application each have an opinion.
A single correct nginx redirect:
# One server block redirects everything to the canonical host over HTTPS
server {
listen 80;
listen 443 ssl;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
# ... real site config
}
Grep for competing rules before adding another:
grep -rn "return 30\|rewrite\|Redirect" /etc/nginx/ /var/www/example.com/.htaccess 2>/dev/null
5. Trailing slash rules
A rule adding a trailing slash combined with a framework stripping it produces /path → /path/ → /path indefinitely. Decide which form is canonical and make sure only one layer enforces it.
Verify the Fix
# Should show at most one redirect, ending in 200
curl -sIL https://example.com | grep -Ei "^(HTTP|Location)"
# Confirm the final URL
curl -sIL -o /dev/null -w '%{num_redirects} redirects -> %{url_effective}\n' https://example.com
Expected:
1 redirects -> https://example.com/
Then load the site in a private window from a device that has never visited it. Test the apex, the www form, and an http:// URL - a fix that resolves one entry point while another still loops is easy to miss.
Prevention
- Choose one canonical hostname and one scheme, document the choice, and enforce it in exactly one layer.
- Use Full (strict) on Cloudflare and equivalent end-to-end TLS on other CDNs. Flexible mode causes this loop and leaves the origin leg unencrypted.
- Set
trust proxyor the equivalent whenever an application sits behind a terminating proxy, at the time you introduce the proxy rather than after the first outage. - Add a redirect check to deployment smoke tests: assert that the canonical URL returns 200 in at most one hop.
- After any HTTPS migration or domain change, test all four entry points -
http://example.com,http://www.example.com,https://example.com,https://www.example.com- before considering the change complete.