A redirect chain is when URL A redirects to URL B, which redirects to URL C, which redirects to URL D. Each hop is a wasted request. Google follows up to 5 hops then gives up; users wait longer; crawl budget is wasted. A redirect loop is worse — the chain returns to a previous URL and never resolves. Both are common on long-lived sites where redirects accumulate without cleanup. This guide walks through diagnosis, collapsing chains to single 301s, fixing loops, and the edge-vs-origin conflict that hides chains from naive audits.
The Site Crawler reports every internal URL that requires more than one hop to resolve.
curl -ILs --max-redirs 10 https://yourdomain.com/old-path/ 2>&1 | grep -iE "^(http|location)"Expected good output: one
HTTP/2 301, one location: https://..., one HTTP/2 200. Anything more is a chain.
For each chain A → B → C → D, write a new direct rule A → D. Remove the intermediate rules.
/old-A/ → /old-B/ → /final/: edit the first rule to point directly at /final/, then delete the middle rule.
# BEFORE (chain) rewrite ^/old-a$ /old-b permanent; rewrite ^/old-b$ /final permanent; # AFTER (single hop) rewrite ^/old-a$ /final permanent; rewrite ^/old-b$ /final permanent;Keep the rule for /old-b in case external links exist. Reload nginx:
nginx -t && nginx -s reload
# BEFORE (chain) Redirect 301 /old-a /old-b Redirect 301 /old-b /final # AFTER (single hop) Redirect 301 /old-a /final Redirect 301 /old-b /finalSave the .htaccess file. Changes apply immediately.
If you use Cloudflare or another CDN/edge layer, redirects can exist in TWO places that fire in sequence.
www.yourdomain.com → yourdomain.com. Then origin server redirects yourdomain.com/old/ → yourdomain.com/new/. Result: 2-hop chain even though each rule is correct. The fix: consolidate at one layer.curl -ILs https://www.yourdomain.com/old/ 2>&1 | grep -iE "^(http|server|location|cf-ray)"The
cf-ray header confirms Cloudflare was involved. server: cloudflare on the 301 response means Cloudflare did it. server: nginx means origin did it.
A loop is a chain that never resolves — Google gives up, users see a browser error.
curl -ILs --max-redirs 10 https://yourdomain.com/path/ 2>&1 | grep -i "^location"If the same URL appears twice in the location list, you have a loop. Common cause: HTTP-to-HTTPS rule plus a non-HTTPS canonical somewhere.
After collapsing chains, internal links that still point at the chain start now hit the 301. Better to update the links directly so visits go straight to the final URL with no redirect at all.
Use the bulk-fix techniques from the broken links guide: WordPress Better Search Replace, Shopify theme code search, headless CMS API scripts.
After collapsing chains and updating internal links, re-run the Site Crawler. Chain count should be at or near zero.