✦ Blog

ERR_TOO_MANY_REDIRECTS: Fix the Redirect Loop Fast

ERR_TOO_MANY_REDIRECTS means your site redirects in a loop. Find the looping hop with curl in 60 seconds, then apply the exact Cloudflare or WordPress fix.

Upmonora team9 min read

Overview - ERR_TOO_MANY_REDIRECTS: Fix the Redirect Loop Fast

ERR_TOO_MANY_REDIRECTS means your site is sending the browser round in a circle: URL A redirects to B, B redirects back to A, and after 20 hops Chrome gives up. The page never loads for anyone. The fastest fix is to read the redirect chain with curl, spot which hop repeats, and remove one side of the loop.

Chrome's page reads "This page isn't working. example.com redirected you too many times." Firefox says "The page isn't redirecting properly." Safari says "Too many redirects occurred trying to open". All three mean the same thing, and it is almost never the visitor's fault.

What ERR_TOO_MANY_REDIRECTS means (and why the page never loads)

A redirect is a 301, 302, 307 or 308 response with a Location header. Browsers follow it automatically. Chromium's network stack caps a single navigation at kMaxRedirects = 20, following the WHATWG Fetch standard, which says that when the redirect count reaches twenty the fetch returns a network error. That network error is code -310, ERR_TOO_MANY_REDIRECTS, in the Chromium error list.

Three things follow from that:

  • The site is effectively down. No HTML is ever delivered, so a redirect loop is an outage even though the server is up and answering.
  • Clearing cookies rarely helps. It only works when a cookie decides where the site redirects you (a language or login cookie, for example). Server-side loops hit every visitor.
  • Google notices too. Googlebot follows up to 10 redirect hops, per Google Search Central, then treats the URL as a redirect error. Pages in a loop drop out of the index if it lasts.

Find the loop in 60 seconds with curl -IL or a redirect checker

Do not guess. Print the chain and read it. From any terminal:

curl -sIL --max-redirs 10 https://example.com/ | grep -iE '^(HTTP|location)'

-I asks for headers only, -L follows redirects, and --max-redirs 10 stops early (curl's default is 50). A healthy site prints one or two hops and then a 200. A loop looks like this:

HTTP/2 301
location: https://example.com/
HTTP/2 301
location: http://example.com/
HTTP/2 301
location: https://example.com/
...

The pattern tells you the cause:

Chain you seeMost likely causeJump to
http://a → https://a → http://aCloudflare Flexible SSL or a proxy that strips HTTPS, plus an origin HTTPS redirectFix 1
https://a → https://a (same URL repeats)WordPress Site URL, or an app that thinks it is on HTTP behind a proxyFix 2
www → non-www → wwwTwo www rules in .htaccess, nginx, a plugin or a Cloudflare ruleFix 3
/page → /page/ → /pageTrailing-slash rules from the CMS and the web server disagreeFix 3
Chain is fine with curl, loops only in a browserHSTS or a cookie-driven redirectFix 4 and the visitor section

If you prefer not to use a terminal, paste the URL into the free redirect checker, which lists every hop and status, or the narrower HTTPS redirect checker and www redirect checker. Test both the bare domain and the www hostname, over http and https: four URLs. Loops often live in only one of them.

Fix 1: Cloudflare SSL mode mismatch and Always Use HTTPS

This is the single most common cause in 2026. Cloudflare's own troubleshooting page lists the combinations that loop. The main ones:

  1. Flexible mode plus an origin HTTPS redirect. In Flexible mode the visitor talks HTTPS to Cloudflare, but Cloudflare talks plain HTTP to your server. Your server sees HTTP, redirects to HTTPS, Cloudflare fetches that over HTTP again, and so on. Fix: in SSL/TLS > Overview set the encryption mode to Full (strict). That needs a valid certificate on the origin: Let's Encrypt or a free Cloudflare Origin CA certificate both work. Plain Full also stops the loop but skips certificate validation, so prefer strict.
  2. Full mode plus an origin HTTP redirect. The reverse: Cloudflare sends HTTPS to the origin and something on the origin redirects HTTPS back to HTTP (an old rule, a cheap-hosting "SSL off" toggle). Fix: remove the HTTP redirect on the origin.
  3. Always Use HTTPS plus an origin redirect to HTTP. The edge forces HTTPS, the origin forces HTTP. Fix: remove the origin rule, or turn off Always Use HTTPS under SSL/TLS > Edge Certificates.

Cloudflare's advice is to do the HTTP to HTTPS redirect at the edge (Always Use HTTPS) and not at the origin at all. If you are on WordPress behind Cloudflare, install the Cloudflare plugin and turn on Automatic HTTPS Rewrites; this fixes mixed content once the loop is gone. After changing the SSL mode, re-run the curl command. Cloudflare applies the change within seconds.

Fix 2: WordPress Site URL and Home URL disagree with the server

WordPress compares the address you requested with its stored Site Address and redirects to the canonical one. If the stored address says http://example.com and the site is served on https://www.example.com, WordPress redirects to the stored URL, the server redirects back, and you have a loop. The same URL repeating in the curl output is the giveaway.

Set both values explicitly in wp-config.php, above the "That's all, stop editing" line, to the exact scheme and host you serve:

define( 'WP_HOME', 'https://www.example.com' );
define( 'WP_SITEURL', 'https://www.example.com' );

These constants override the database values (they do not change them), which is useful because you cannot reach the admin area while the loop exists. The wp-config reference documents both.

If WordPress runs behind a proxy, load balancer or Cloudflare Flexible SSL, it may not know the original request was HTTPS, so is_ssl() returns false and it redirects to HTTPS forever. Tell it to trust the forwarded-protocol header, also in wp-config.php:

if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) &&
     strpos( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https' ) !== false ) {
    $_SERVER['HTTPS'] = 'on';
}

Only do this when a proxy you control sets that header; otherwise anyone can spoof it. Then disable redirect and SSL plugins by renaming their folders in wp-content/plugins/ over SFTP, and check again. The WordPress site down checklist covers the rest of the recovery order.

Fix 3: Conflicting .htaccess, nginx or plugin redirects

A www loop or a trailing-slash loop is two rules that each undo the other. Pick one canonical form, write one rule for it, and delete every other rule that touches scheme or host.

Apache (.htaccess), one rule for HTTPS plus www, placed before the WordPress block:

RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [L,R=301]

Behind a proxy that terminates TLS, %{HTTPS} is always off, which creates the loop. Use the forwarded header instead:

RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://www.example.com%{REQUEST_URI} [L,R=301]

nginx, one server block for port 80 that only redirects, and a second for 443 that only serves:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl;
    server_name www.example.com;
    # no scheme redirects in here
    ...
}

The nginx mistake that loops is an if ($scheme != "https") redirect inside the 443 block when nginx sits behind a proxy and only ever sees HTTP. Replace it with a check on $http_x_forwarded_proto, or move the redirect to the proxy.

Finally, search the application layer. WordPress plugins (Really Simple SSL, Redirection, Yoast's redirect manager), Laravel's forceScheme, Rails' force_ssl and Django's SECURE_SSL_REDIRECT all add a redirect that can fight the web server's rule. Keep the redirect in exactly one place.

Fix 4: HSTS, Page Rules and redirect rules fighting each other

Two Cloudflare-side causes are easy to miss because curl may not reproduce them.

HSTS. Once a browser has seen a Strict-Transport-Security header, it upgrades every future request to HTTPS before sending it. If your origin then redirects HTTPS to HTTP, the browser upgrades again and loops, while curl (which ignores HSTS) looks fine. Cloudflare's docs say to remove the origin's HTTP redirect and keep the encryption mode at Flexible or higher; the real fix is to serve the site on HTTPS everywhere, since visitors who already cached the HSTS policy keep it until max-age expires or they receive a new header with max-age=0 over HTTPS.

Redirect Rules and Page Rules. A rule that sends a.example.com to b.example.com over HTTP, next to one that sends it back over HTTPS, is a loop. Open Rules > Overview and list every redirect rule and legacy Page Rule. Rules products take precedence over Page Rules, so an old Page Rule can be silently overridden and then reappear when you edit the newer rule. Bulk Redirects at the account level count too.

If your site also goes through a second CDN or a host-level "force HTTPS" switch (common on managed WordPress hosts), that is another layer that can issue its own redirect. Count the layers: browser, Cloudflare, host proxy, web server, application. Each one should either redirect or serve, and only one of them should redirect.

Visitor-side causes you cannot fix for them

When curl and the redirect checker show a clean chain but one person still sees the error, the loop is local to their browser:

  • A stale cookie steering a login, language or region redirect. Clearing cookies for the site fixes it, which is why Chrome suggests it.
  • A browser extension that rewrites URLs (HTTPS enforcers, ad blockers with redirect rules, VPN extensions).
  • A cached 301. Browsers cache permanent redirects aggressively; a loop you fixed an hour ago can live on in one browser until its cache is cleared.
  • A corporate proxy or captive portal injecting its own redirects.

Ask the person to try an incognito window. If that works, it is one of the above and your site is fine. If it fails everywhere, go back to the curl output.

How to catch redirect loops automatically next time

Redirect loops appear after changes: enabling Cloudflare, switching to HTTPS, migrating hosts, installing a plugin. They are also invisible to a naive uptime check that treats any 3xx as "up". Three habits prevent repeat incidents:

  1. Monitor the final response, not the first. Use a monitor that follows redirects and validates each hop. Upmonora follows up to 5 redirects and checks every hop, so an HTTP to HTTPS or www loop fails the check instead of passing as a 301.
  2. Monitor all four entry URLs. http and https, with and without www. Most loops only affect one of them, usually the one you never type.
  3. Set an expected status of 200. With expected status codes configured per monitor, a chain that ends in anything else alerts you, and the incident timeline shows the exact minute it started, which usually matches the change that caused it.

Related failures look similar from a browser but have different fixes: Cloudflare's 520 to 524 errors are origin connection problems, and a long but non-looping chain is covered in redirect chains: how to find and fix them. The status code cheat sheet explains the 3xx family.

Upmonora checks your site as often as every 30 seconds, validates every redirect hop and opens one incident per outage. Start free with 5 monitors, no card needed.

Key takeaways

  • ERR_TOO_MANY_REDIRECTS is a server-side loop until proven otherwise. Chrome stops at 20 hops; the page never loads.
  • curl -sIL shows the chain in seconds. The repeating pair of URLs names the cause.
  • Cloudflare Flexible SSL plus an origin HTTPS redirect is the most common loop. Set Full (strict) with a valid origin certificate.
  • In WordPress, pin WP_HOME and WP_SITEURL in wp-config.php and trust X-Forwarded-Proto behind a proxy.
  • Keep exactly one scheme/host redirect across Cloudflare, host, web server and application.
  • Monitor all four entry URLs with a check that validates every redirect hop.

Frequently asked questions

What causes ERR_TOO_MANY_REDIRECTS?

ERR_TOO_MANY_REDIRECTS is caused by two or more redirect rules that send the browser back and forth, for example an HTTP to HTTPS redirect on the origin server combined with Cloudflare Flexible SSL, a WordPress Site URL that disagrees with the real address, or a www rule that fights a non-www rule. The browser follows the chain until it hits its limit and gives up.

How do I fix a redirect loop in WordPress?

Open wp-config.php and set WP_HOME and WP_SITEURL to the exact scheme and hostname the site is served on, including https:// and www or not. If the site sits behind a proxy or Cloudflare Flexible SSL, add the HTTP_X_FORWARDED_PROTO check so WordPress knows the request was HTTPS. Then rename .htaccess to rule out an old rewrite rule and disable redirect and SSL plugins.

Why does Cloudflare cause too many redirects?

Cloudflare causes a redirect loop when its SSL/TLS mode is Flexible, so it connects to your origin over plain HTTP, while your origin redirects every HTTP request to HTTPS. Each hop looks like HTTP to the origin, so it redirects again. The fix is to set the SSL/TLS mode to Full (strict) with a valid certificate on the origin, or to remove the origin redirect.

How many redirects are too many?

Chrome stops after 20 redirects in one chain, the limit written into the Fetch standard, and then shows ERR_TOO_MANY_REDIRECTS. curl follows 50 by default with -L. Googlebot follows up to 10 hops before it gives up. Any chain longer than two hops is worth fixing, and a chain that revisits the same URL is a loop.