How to Fix Redirect Chains and Loops (Step-by-Step)
A redirect chain is what happens when nobody cleans up after a migration. Every time someone renames a URL, fixes a slug, or bolts on an HTTPS rule, a new hop gets added, and the old ones never get retired. Two years later a single request to /blog/post-1 quietly bounces through four URLs before it lands. Users barely notice. Googlebot notices, your crawl budget notices, and your LCP on mobile notices.
This is a troubleshooting guide: how to spot chains and loops, diagnose where each hop comes from, and flatten them without breaking the backlinks you've earned. If you're still deciding which redirect code to use in the first place, start with 301 vs 302: which to use.
Chain vs loop: they fail differently
A chain is two or more hops between the requested URL and the final 200 response:
GET /blog/post-1 → 301 → /blog/post-one
GET /blog/post-one → 301 → https://site.com/blog/post-one
GET ... → 301 → https://site.com/blog/post-one/ (200 at last)
It still works (the user gets there), but every hop is a wasted round trip.
A loop never resolves. Two rules point at each other and the browser gives up:
GET /a → 301 → /b
GET /b → 301 → /a
Chrome throws ERR_TOO_MANY_REDIRECTS after about 20 hops. A loop is a hard outage for that URL; it returns nothing crawlable and nothing viewable.
Why chains quietly cost you
- Crawl budget. Every hop is a separate request Googlebot has to make. On a large site, thousands of chained URLs mean Google spends its budget following redirects instead of discovering and refreshing real content.
- LCP and mobile speed. Each hop is a full DNS-or-TLS-and-round-trip before the browser even starts fetching the real page. On a 4G connection a three-hop chain can add hundreds of milliseconds before the first byte of actual HTML. That delay lands squarely in Largest Contentful Paint.
- Signal attrition. Modern Google generally follows chains and consolidates equity, but it's documented to stop after roughly 10 hops, and the longer the chain, the more chances for one misconfigured hop (a stray 302, a hop to a 404) to break consolidation. Treat chains as lossy and you'll never get burned.
Diagnose: see every hop
You can't fix what you can't see. The fastest way to read a full chain is curl:
curl -ILs https://example.com/blog/post-1 | grep -iE "^HTTP|^location"
-Ifetches headers only,-Lfollows redirects,-ssilences the progress meter.- The
grepkeeps just the status lines andLocationheaders, so you get a clean hop-by-hop trace.
Output for the chain above looks like:
HTTP/2 301
location: /blog/post-one
HTTP/2 301
location: https://site.com/blog/post-one
HTTP/2 301
location: https://site.com/blog/post-one/
HTTP/2 200
Three 301s before the 200: that's three hops where there should be one. If you'd rather not touch the terminal, paste the URL into our Redirect Checker; it renders the same hop chain with each status code laid out, which is also the artifact to keep when you go hunting for the source rule.
Diagnose: find where each hop is born
The hard part isn't seeing the chain; it's locating the rule that created each hop, because they're usually spread across layers added at different times:
| Hop typically comes from | Look in |
|---|---|
| http→https, www→non-www | CDN (Cloudflare page rules), load balancer, or server-level rewrite |
| Trailing-slash normalization | Framework config (Next.js trailingSlash), Nginx, or .htaccess |
| Old slug → new slug | CMS plugin (Redirection, Yoast), app middleware, or a redirects table |
| Legacy path → new structure | .htaccess entries left over from past migrations |
The classic three-hop chain is the stacking trio: one layer forces HTTPS, another forces non-www, a third adds a trailing slash, each handled by a different system, each firing as its own 301. None is wrong individually; together they're a chain.
Flatten a chain: point every source at the final URL
The fix is mechanical once you have the trace. Walk it end to end, take the final 200 URL, and rewrite every intermediate source to point directly there.
Before
/post/123 → /blog/old-slug → /blog/new-slug
/blog/old-slug → /blog/new-slug
After
/post/123 → /blog/new-slug
/blog/old-slug → /blog/new-slug
Two rules to remember:
- Keep the legacy URLs as redirects, don't delete them. External backlinks still point at
/post/123, and you want that link equity to flow. You're not removing the redirect, you're shortening it to one hop. - Fix the stacking trio at the edge. For the HTTPS + www + trailing-slash case, do all three normalizations in one rule at your outermost layer (the CDN), so the very first response is already the final canonical URL. One hop, done.
Break a loop
- Run the URL through
curlor the Redirect Checker and note the two URLs that ping-pong. - List every redirect rule that touches either URL, across CDN, server config, and app. A loop almost always means two layers disagree about the canonical form (one forces a trailing slash, the other strips it).
- Pick the canonical form, then remove or correct the rule that contradicts it so the destination URL returns 200, not another redirect.
- Purge CDN and browser caches. Redirects, especially 301s, cache hard, and a fixed loop can keep looping from cache for hours otherwise.
Stop chains from coming back
- Audit before you ship a migration. Run representative URLs through the Redirect Checker on staging so you catch a new chain before production crawls it.
- One source of truth. Keep redirect rules in a single place per concern; the fastest way to grow a chain is adding a CDN redirect that duplicates one already in your app config.
- Log every URL change as "old → new (301)" so the next rename points at the current canonical URL instead of piling another hop on top.
Frequently Asked Questions
How many hops in a chain is acceptable?
One redirect (the source straight to the destination) is the target. Google tolerates short chains and usually still consolidates equity up to about 10 hops, but every extra hop adds latency and a chance for the chain to break. Aim for zero intermediate hops.
Do redirect chains really hurt Core Web Vitals?
Yes. Each hop is a round trip that happens before the browser fetches the actual page, so it pushes back the start of rendering and inflates LCP, most noticeably on mobile networks. Flattening a three-hop chain to one hop can shave meaningful time off time-to-first-byte.
Why does my redirect loop only appear on HTTPS or with a trailing slash?
Because two rules are fighting. One layer forces HTTPS (or a trailing slash) and another forces the opposite, so each "fix" triggers the other rule. Test each rule in isolation (disable one and watch whether the loop resolves) to find the conflicting pair.
Can I find chains across my whole site at once?
Yes. Site crawlers like Screaming Frog, Sitebulb, and Ahrefs flag redirect chains and loops across every URL they reach. Use those for full-site sweeps and the Redirect Checker for fast spot checks on a specific URL.
If I flatten a chain, do I delete the old redirect rules?
No. Shorten them, don't delete them. Each legacy URL should still redirect (in one hop) to the final destination so external backlinks keep passing equity. Deleting the rule turns those backlinks into 404s.
Will fixing a chain recover lost rankings immediately?
Improvement follows the next crawl, not the moment you deploy. Once Google recrawls the now-single-hop redirect it consolidates faster and wastes less budget, but give it a few crawl cycles. The win is mostly preventing further loss and speeding up consolidation.