ERR_TOO_MANY_REDIRECTS: Fix the Redirect Loop (Nginx)

ERR_TOO_MANY_REDIRECTS means two rules keep sending the browser back and forth. Trace the chain with curl -sIL, find the two rules that conflict and remove one.
"This page isn't working. example.com redirected you too many times." It usually appears right after you add SSL, put the site behind Cloudflare, change www to non-www, or move to a new server. The good news: a redirect loop is pure configuration, nothing is broken or lost, and once you can see the chain the fix is often a single setting. This is the routine I use when I move client sites behind Cloudflare and Nginx, including this one.
Key takeaways
- See the loop first:
curl -sIL https://example.com | grep -iE '^(HTTP|location)'prints every hop and where it points. - Cloudflare Flexible SSL is the #1 cause: Cloudflare talks to your server over HTTP, your server redirects to HTTPS, forever. Use Full (strict).
- Behind a proxy, the app must trust
X-Forwarded-Proto, or it thinks every request is HTTP and keeps redirecting. - Force HTTPS and www in one place only. Two layers both "fixing" the URL is how loops are born.
- Clear cookies and test in a private window after fixing: browsers cache 301s.
Step 1: Trace the redirect chain
Browsers give up after about 20 hops and hide the details. curl shows them:
curl -sIL --max-redirs 10 https://example.com | grep -iE '^(HTTP|location|server)'
Read the location lines. You'll see one of three patterns:
- The same URL over and over (
https://example.com/tohttps://example.com/): your server thinks the request is HTTP when it's already HTTPS. That's cause 1 or 2. - Two URLs swapping (
wwwto apex and back, or/pageto/page/and back): two rules disagree about the canonical form. That's cause 3. - The loop happens only when logged in, or only on
/dashboard: the app's auth redirects are fighting. That's cause 4.
The server header tells you who answered each hop. cloudflare on every line doesn't mean Cloudflare made the redirect; check whether the loop also happens when you hit your server directly:
curl -sIk --resolve example.com:443:YOUR.SERVER.IP https://example.com | head -5
Cause 1: Cloudflare SSL mode is "Flexible"
This is the one I see most. With Flexible, Cloudflare serves HTTPS to the visitor but connects to your origin over plain HTTP on port 80. Your Nginx (or WordPress, or app) sees HTTP and returns a 301 to HTTPS. Cloudflare passes that to the browser, the browser asks again over HTTPS, Cloudflare connects to the origin over HTTP again, and round it goes.
The fix:
- Make sure the origin has a valid certificate. A free Let's Encrypt cert from certbot works, or a Cloudflare Origin Certificate if all traffic goes through Cloudflare.
- In the Cloudflare dashboard, go to SSL/TLS, Overview and set the mode to Full (strict).
- Keep "Always Use HTTPS" on in Cloudflare or the redirect in Nginx. Either is fine now, because both sides speak HTTPS.
If certbot renewals are failing on the origin, fix that first (my certbot renewal guide covers the Cloudflare cases). The full settings I use are in my Cloudflare + VPS setup checklist.
Cause 2: The app doesn't know it's behind HTTPS
When Nginx terminates TLS and proxies to Node, PHP or Python on 127.0.0.1, the app receives plain HTTP. If the app also forces HTTPS (Express middleware, Laravel's URL::forceScheme, Django's SECURE_SSL_REDIRECT, WordPress plugins), it redirects every request even though the visitor is on HTTPS. Pass the original scheme from Nginx:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Then tell the app to trust it:
- Express:
app.set('trust proxy', 1), thenreq.secureis correct. - Django:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https'). - Laravel: configure trusted proxies so it reads the forwarded headers.
- WordPress: if
$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https', set$_SERVER['HTTPS'] = 'on'inwp-config.php, and make sure the Site URL settings usehttps://.
Simplest of all: if Nginx already redirects HTTP to HTTPS, switch off the app's own HTTPS redirect. One layer is enough.
Cause 3: www and non-www (or trailing slash) rules disagree
A loop between www.example.com and example.com means one layer forces www and another forces the apex. Typical combinations: a Cloudflare redirect rule plus an Nginx return 301, or Nginx plus the CMS "site address" setting, or a framework config. Pick one canonical host and enforce it in one place. In Nginx, a clean setup with a separate block per host looks like this:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
# ssl_certificate lines here
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
# ssl_certificate lines + your site here
}
Every wrong form reaches the final URL in one hop, which is also what Google prefers. The same idea applies to trailing slashes: Next.js has trailingSlash in next.config, and if Nginx adds a slash that Next.js removes, you get a loop. Let the framework own it. Getting this right matters for SEO too; my guide on redesigning without losing rankings explains why redirect chains cost you.
Cause 4: Login or middleware redirects
If the loop only happens on protected pages, the auth layer is redirecting a logged-in user to the login page, and the login page redirects them back because they're logged in. Usual causes:
- The session cookie is set with
Securebut the app thinks the request is HTTP (cause 2 again), so it never sees the cookie. - The cookie domain doesn't match (
example.comvswww.example.com). - Middleware or Next.js
proxy.tsmatches the login route itself. Exclude it from the matcher. - Auth.js / NextAuth has the wrong
NEXTAUTH_URLorAUTH_URL(http vs https, or the wrong host). See my NextAuth host errors guide.
Step 2: Clear the browser cache and verify
Browsers cache 301 redirects, sometimes for a long time. After fixing the server, test with curl again, then in a private window. If a normal window still loops, clear cookies and cached data for the site. If you use Cloudflare, purge the cache too. A good result looks like this:
curl -sIL http://example.com | grep -iE '^(HTTP|location)' HTTP/1.1 301 Moved Permanently location: https://www.example.com/ HTTP/2 200
One redirect, then a 200. If you've just moved the site to a new server, my zero-downtime migration guide covers DNS and SSL order so this doesn't happen mid-move.
Frequently asked questions
What causes ERR_TOO_MANY_REDIRECTS?
Two redirect rules that undo each other, so the browser never reaches a page. The most common case is Cloudflare's Flexible SSL mode combined with an HTTPS redirect on the server, followed by conflicting www and non-www rules.
How do I fix too many redirects with Cloudflare?
Install a certificate on your server and set Cloudflare's SSL/TLS mode to Full (strict) instead of Flexible. Then make sure only one place forces HTTPS and only one place forces www or non-www.
Does clearing cookies fix ERR_TOO_MANY_REDIRECTS?
Only if the loop comes from a stale cookie or a cached redirect. If curl also shows the loop, the problem is on the server or CDN and clearing cookies won't help.
Why does my site redirect too many times only after adding SSL?
Your server now redirects HTTP to HTTPS, but something in front of it (Cloudflare Flexible, a load balancer) still connects over HTTP, or your app doesn't trust the forwarded protocol header. Fix the proxy mode or pass X-Forwarded-Proto.
Can a redirect loop hurt SEO?
Yes. Googlebot can't reach the page, so it drops out of the index if the loop lasts. Long redirect chains also waste crawl budget, so aim for a single hop to the final URL.
Want it fixed today?
I set up Nginx, SSL and Cloudflare for business sites so redirects, caching and certificates just work, and I fix loops like this usually within the hour. See my DevOps services or contact me with your domain.
Written by
MD Rakibul Islam Rakib
Full-stack developer, DevOps engineer and Linux system administrator with 5+ years of production experience. I deploy, harden and fix servers and web apps for clients worldwide, and everything in this article runs on real servers I manage, including this site.
- ERR_TOO_MANY_REDIRECTS
- redirect loop
- Cloudflare Flexible SSL
- Nginx redirect
- X-Forwarded-Proto
- www redirect
- HTTPS redirect


