TechnicalSEO

Redirect Loops: Find and Fix Them Fast

Redirect loops happen when redirect rules send a request in a circle, so URL A leads to B, B leads back to A, and the page never loads. Browsers give up and show an error, and search engine crawlers give up too. The fix is almost never “add another redirect.” It is finding the two rules that disagree and deleting one.

This guide is for site owners, marketers and developers who just met ERR_TOO_MANY_REDIRECTS and want the cause, not a vague checklist. It covers the usual culprits (HTTPS, www, trailing slash, CMS plugins, CDN settings) and the curl commands that show which rule is looping. For the wider theory of status codes, see redirects SEO. Chains that resolve but waste hops belong there too.

On this page

What is a redirect loop?

A redirect loop is a sequence of redirects that never reaches a page that returns content. MDN’s guide to HTTP redirections describes it as a loop “that will never be finished and no page will ever be found.”

Two things decide what you see:

  • The server may catch it. MDN says that if the server detects the loop it may send back a 500 Internal Server Error, and that a 500 soon after a configuration change is likely a redirect loop.
  • The browser catches it when the server cannot. A loop can spread across several servers that each lack the full picture. Chrome then shows its redirect-loop message and Firefox reports that the server is redirecting the request “in a way that will never terminate.”

The diagram below shows the single most common loop on sites behind a CDN: the CDN asks for HTTP, and the origin insists on HTTPS.

An HTTPS loop between a CDN and an origin server Four steps in a circle. Step 1: the visitor requests https. Step 2: the CDN, in Flexible mode, forwards the request to the origin over plain http. Step 3: the origin answers with a redirect to https. Step 4: the visitor follows it and the cycle repeats until the browser stops with ERR_TOO_MANY_REDIRECTS. The fix is to make only one layer force HTTPS, or to encrypt the CDN to origin connection. The classic HTTPS loop Each layer behaves correctly alone. Together they never finish. 1. Visitor asks for https://example.com/ 2. CDN, Flexible mode asks origin over http 3. Origin replies 301 to https 4. Visitor follows the redirect. Back to step 1. Browser stops: ERR_TOO_MANY_REDIRECTS

Scroll the diagram sideways to see all of it.

Source: Ambeltek diagram based on Cloudflare's documentation on ERR_TOO_MANY_REDIRECTS.

Why do redirect loops hurt SEO?

A loop stops a crawler from ever reaching a final URL, so the page cannot be indexed and nothing pointing at it can pass signals. Conductor’s explainer on redirect loops says crawlers stop following the redirects once they realize they are stuck, and that the ranking signals are lost. Ahrefs’ help page on the redirect loop issue in Site Audit says the final URL never resolves.

Nobody has published how long Google takes to drop a looping URL, so treat any specific timeline you read as a guess. What you can count on is the user side: visitors see an error, and the pages affected are the ones you wanted found.

Loops are different from chains. A chain passes through several hops and ends on a working page. Google’s site move guidance says Googlebot can follow up to 10 hops and advises redirecting straight to the final destination, keeping chains “ideally no more than 3 and fewer than 5” when you cannot. A chain costs speed. A loop costs the page. We cover chains and the 301 vs 302 choice in redirects SEO, and the audit-level view of both in technical SEO issues.

How do you find which rule is looping?

Request the URL with curl, follow redirects with a low limit, and read the sequence of Location headers. The repeating pair of URLs is the loop. Browser dev tools give the same picture, but curl is faster, scriptable, and does not carry your cookies.

Start with headers only. In the curl manual, -I fetches the headers only, -L makes curl redo the request at the new location, and --max-redirs caps the number of redirects (the default limit is 50). Set a small cap so a loop fails quickly:

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

The -s flag silences the progress meter, and the grep keeps only the status lines and the Location headers. A loop looks like the same two URLs alternating, each with a 301 or 302. Read them as pairs: status, then where it sent you.

For a one-line summary of where a request ended, use -w, which makes curl print information after the transfer. The manual lists num_redirects (redirects followed), url_effective (the URL fetched last) and response_code:

curl -sIL --max-redirs 8 -o /dev/null -w "%{num_redirects} hops, last %{url_effective}, status %{response_code}\n" https://example.com/page

To test one hop at a time, drop -L and read what each response says. The variable redirect_url shows the URL a redirect would have gone to:

curl -sI -o /dev/null -w "%{response_code} -> %{redirect_url}\n" http://example.com/page

Run that on all four variants of the URL: http://example.com/, http://www.example.com/, https://example.com/ and https://www.example.com/. The variant whose answer points back toward the one you started from is where the loop lives.

Two caveats that are our own reasoning, not from the manual. -I sends a HEAD request, and a few servers or plugins answer HEAD differently from GET, so if the result looks wrong, repeat with -s -o /dev/null -D - instead. And a clean curl result with a browser error often means the loop depends on a cookie or login state. MDN lists mismatched cache or cookies as one case where the problem sits on the visitor’s side, so clear site cookies before concluding anything.

A four-step method for tracing a redirect loop Step 1: run curl with -sIL and a low max-redirs to list the status and Location of each hop. Step 2: find the two URLs that repeat. Step 3: test the four variants, http and https with and without www, one hop at a time with redirect_url. Step 4: for the variant that points back, find which layer owns that redirect: CDN, server config, CMS plugin or application, and remove the duplicate. Trace the loop in four steps From error message to the single rule to delete 1 List the hops curl -sIL with a low --max-redirs, keep status and Location 2 Spot the repeat Two URLs alternate. That pair is the fight to resolve 3 Test four variants http and https, with and without www, one hop each, no -L 4 Find the owner CDN, server, plugin or app. Keep one rule, delete the rest Rule of thumb: every redirect should have exactly one owner. A loop means two layers each think they own it. Test after each change with the same curl command, not the browser, which may cache a 301.

Scroll the diagram sideways to see all of it.

Source: Ambeltek diagram based on the curl manual.

HTTPS and CDN loops

HTTPS loops come from two layers that both enforce the scheme, or from a layer that cannot see the scheme the visitor used. Cloudflare’s troubleshooting page for ERR_TOO_MANY_REDIRECTS names a misconfigured SSL/TLS encryption mode, various Edge Certificate settings and a misconfigured redirect rule as the common causes. Its specifics are useful beyond Cloudflare:

  • Flexible mode. The CDN sends plain HTTP to the origin, so a loop occurs if the origin redirects all HTTP requests to HTTPS. Cloudflare’s fix: remove the HTTPS redirect from the origin, or move to Full or higher (which needs a certificate on the origin).
  • Full or Full (strict). The CDN sends HTTPS to the origin, so a loop occurs if the origin redirects HTTPS back to HTTP. Remove that HTTP redirect.
  • Always Use HTTPS and HSTS. Both push visitors to https, so a loop appears if the origin sends them back to http.

The same shape appears with load balancers and reverse proxies. The Apache documentation on remapping and redirects warns that %{HTTPS} queries mod_ssl directly, and behind a load balancer or SSL terminator it always reports off, which can cause a redirect loop. A rule like this one then redirects forever:

RewriteEngine On
RewriteCond "%{HTTPS}" !=on
RewriteRule "^(.*)" "https://%{SERVER_NAME}$1" [R=301,L]

For that setup Apache’s recipe keys on the forwarded header instead, and warns that you should trust X-Forwarded-Proto only if you control the proxy and it overwrites the header on every request:

RewriteEngine On
RewriteCond "%{HTTP:X-Forwarded-Proto}" =http [NC]
RewriteRule "^(.*)" "https://%{SERVER_NAME}$1" [R=301,L]

Apache’s own preferred method avoids the problem: a Redirect permanent in a dedicated port-80 virtual host, because that host only ever sees plain HTTP requests. The decision of which layer owns HTTPS is worth making once, in writing, for the whole stack.

www and trailing slash loops

Both are the same bug in different clothes: one rule adds something, another removes it. A rule that sends example.com to www.example.com loops with a rule that sends www.example.com back to example.com. A rule that adds a trailing slash loops with one that strips it.

The www case usually appears after a migration or a DNS change, when a hosting panel, a CDN and the application each carry their own preferred host. Apache’s Canonical Hostnames recipe calls a Redirect in a virtual host for the non-canonical name “the very best way” and advises mod_rewrite only when you are limited to .htaccess. Note that its mod_rewrite samples redirect to http://, so change the scheme if your site uses HTTPS, or you create the HTTPS fight from the previous section.

On nginx, rewrite loops have a built-in brake. The rewrite module documentation says the rewrite cycle repeats when a request URI is rewritten, but not more than 10 times, and its example shows that using last inside a location makes nginx run 10 cycles and return a 500 error. That is an internal loop, not a browser-visible one, but the symptom is the same: a page that never loads. The flags matter: permanent returns a 301, while redirect returns a 302 when the replacement does not start with http://, https:// or $scheme.

For trailing slashes, the pattern to look for in curl output is a URL that gains a slash on one hop and loses it on the next. We have not found a primary source that documents the exact rule pair for each stack, so confirm in your own config which directive adds the slash and which removes it. Then keep one. The URL you keep should match your canonical tags, as covered in our canonical tag guide, and your internal links, so nothing triggers a redirect to begin with. Our internal linking guide explains why linking straight to the final URL matters.

CMS plugin and WordPress loops

On a CMS, the loop often lives in a plugin that competes with a server rule or another plugin. Redirect managers, SEO plugins, security plugins, caching plugins and “force HTTPS” plugins can all issue redirects. Your server config, your host’s control panel and your CDN may do the same.

WordPress has one more trap. The WordPress developer documentation on migrating a site says both WordPress Address and Site Address “should include the https:// part and should not have a slash” at the end, and warns that people who change them “discover that their site no longer works properly.” If those two settings disagree on scheme or host, WordPress may keep redirecting between them.

A sensible order for a WordPress site:

  1. Clear cookies for the site, or test in a private window.
  2. Run the four-variant curl test above and note which variant bounces.
  3. Check WordPress Address and Site Address for matching scheme and host.
  4. Disable redirect-capable plugins one at a time and re-run curl after each.
  5. Check the CDN and host panel for “force HTTPS” or “force www” switches that duplicate a plugin.
  6. Check .htaccess or the server block for rules left from a previous setup.

Plugins that rewrite sitewide rules are one reason we are cautious about stacking them. Our WordPress SEO guide covers what a lean setup looks like.

Four layers that can own a redirect, from edge to application A stack of four layers. Layer 1, CDN or edge: Flexible and Full modes, Always Use HTTPS, HSTS, page and redirect rules. Layer 2, web server: Apache or nginx rules, virtual hosts, htaccess. Layer 3, CMS plugins: redirect managers, SEO, security and caching plugins. Layer 4, application settings: WordPress Address and Site Address. A loop appears when any two layers both claim the same redirect. The fix is to keep one owner per redirect. Who owns the redirect? A loop needs two owners. Aim for one per redirect. 1. CDN / edge SSL mode, Always Use HTTPS, HSTS, redirect and page rules 2. Web server Apache or nginx rules, virtual hosts, .htaccess 3. CMS plugins Redirect managers, SEO, security, caching and force-HTTPS plugins 4. Application WordPress Address and Site Address, framework URL settings Two layers claiming the same redirect is the loop.

Scroll the diagram sideways to see all of it.

Source: Ambeltek diagram.

Causes, signatures and fixes at a glance

Match what curl prints to the likely cause, then fix the layer named in the last column. The signatures are patterns to look for, not guarantees, so confirm each in your own config.

CauseWhat curl showsUsual fixSource for the rule
CDN in Flexible mode, origin forces HTTPShttps request to CDN, then repeated 301 to httpsRemove the origin HTTPS redirect, or use Full or higherCloudflare docs
CDN in Full mode, origin forces HTTPRepeated 301 toward httpRemove the origin HTTP redirectCloudflare docs
%{HTTPS} rule behind a load balancerSame https URL redirecting to itselfTest X-Forwarded-Proto instead, or redirect in a port-80 hostApache docs
www rule against non-www ruleTwo hostnames alternatingKeep one canonical host ruleApache docs
Trailing slash added and strippedSame path with and without slash alternatingKeep one rule, match canonicals and linksAmbeltek pattern, verify in your config
WordPress Address differs from Site AddressAlternating hosts or schemesMake both match, with https and no trailing slashWordPress docs
Plugin against server ruleRedirect appears with plugin on, gone with it offDisable one, keep one ownerAmbeltek pattern
nginx rewrite ... last re-matching its own location500 error, not a redirectRewrite the rule so it no longer re-matchesnginx docs

A loop that you fix leaves tidy-up behind. Browsers may cache permanent redirects, so test fixes with curl or a private window. Then check the XML sitemap lists only final, 200-status URLs (see XML sitemaps), and run a crawl to see whether other pages still link to URLs that redirect. For removed pages that should not redirect at all, 410 Gone vs 404 and the 404 errors guide cover the alternatives.

Keeping redirect loops from coming back

Write down which layer owns each redirect, and change that owner list before changing any rule. The loops in this post all come from two reasonable rules written by different people at different times.

A few habits keep them from returning:

  • Own HTTPS in one place. Decide whether the CDN or the origin enforces it, and set the SSL mode to match.
  • Own the canonical host in one place. Pick www or non-www, and make DNS, server and application agree.
  • Link to final URLs. Internal links, the sitemap and canonicals should all point at the URL you want indexed, so redirects are for old links only.
  • Re-run the four-variant curl test after every migration. It takes a minute, and our website migration SEO checklist and the technical SEO audit checklist both treat redirect checks as part of launch.
  • Re-test after plugin and CDN changes. These are where new owners appear.

If redirect problems keep returning after launches or redesigns, the cause is usually process, not syntax. Our web development service includes mapping and testing redirects at server level before a site goes live, so the owner list exists before anything breaks.

Frequently asked questions

What is a redirect loop?

A redirect loop is a cycle where URL A redirects to B and B sends the request back to A, directly or through more steps, so the final page never loads. Browsers detect it and stop with an error such as ERR_TOO_MANY_REDIRECTS. Crawlers give up too, so the page cannot be indexed or pass any signals.

What causes a redirect loop?

Two or more rules that disagree about the correct URL. The usual pairs are an origin server forcing HTTPS while a CDN talks to it over HTTP, a www rule fighting a non-www rule, a trailing slash rule fighting its opposite, and a CMS plugin fighting server rules. Mismatched WordPress Address and Site Address settings can do the same.

How do I find which redirect is looping?

Request the URL with curl, follow redirects with a low limit, and print each response status and Location header. The URLs repeat in the output, and the repeating pair shows which two rules are fighting. Browser developer tools show the same sequence on the Network tab.

Do redirect loops hurt SEO?

Yes. A crawler that hits a loop never reaches a final page, so the URL cannot be indexed and any signals pointing to it are lost. A loop on a high-traffic URL also means visitors cannot reach the page at all. Chains eventually resolve, loops never do.

How do I fix ERR_TOO_MANY_REDIRECTS on a WordPress site?

Clear cookies for the site first, then check that WordPress Address and Site Address match and both use https. Next, disable redirect or SEO plugins one at a time, and check whether a CDN or host also forces HTTPS or www. Remove the duplicate rule so only one layer owns each redirect.

Is a redirect loop the same as a redirect chain?

No. A chain passes through several redirects and then ends on a page that loads, while a loop never ends. Chains waste time and should be shortened to one hop, but they still work. Loops break the page completely.

OK

Olga Kunger

Founder & Lead Strategist, Ambeltek

Olga leads Ambeltek's web development, AI SEO, and GEO work — helping brands rank on Google and get cited by AI engines. More about Olga →

Want structured data that engines trust?

We audit, design and ship connected JSON-LD for your whole site, validated and monitored.