The link you click is often not the page you get. In between there can be an HTTPS upgrade, a host change, a tracking service, a URL shortener and a CMS rule that adds a trailing slash, each one a separate request your browser makes without telling you.
This guide explains how to see those steps with TrueURL, curl and browser DevTools, what each part of a redirect chain means, and how to fix the most common problems.
What a redirect chain is
A redirect happens when a server answers with a 3xx status code and a Location header naming another URL. The client, a browser or a crawler, then requests that URL, and repeats the process until a response arrives that is not a redirect.
Each request and its response form one hop. The whole sequence from the first URL to the final response is the redirect chain:
# URL Status Location
1 http://example.com/Shoes 301 https://example.com/Shoes
2 https://example.com/Shoes 301 https://www.example.com/Shoes
3 https://www.example.com/Shoes 302 /shoes/
4 https://www.example.com/shoes/ 200That is three redirects and four requests to reach one page. The Location on hop 3 is relative: clients resolve it against the URL they just requested, as RFC 9110 specifies, so it means https://www.example.com/shoes/. Ideally, every one of these addresses would reach the final URL in a single hop.
A page can also redirect after answering 200 OK, with a <meta http-equiv="refresh"> tag or JavaScript. These client-side redirects belong to the chain too, but tools that only read HTTP headers, such as curl, stop at that page.
Why checking redirects matters
SEO: canonical signals and crawl budget
Search engines read a redirect as a statement about which URL to index. Google treats permanent redirects (301 and 308) as a strong signal that the target should be canonical, and temporary ones (302, 303 and 307) as a weak signal. A page that moved for good behind a 302 may therefore keep its old URL in search results.
Length matters too. Googlebot follows up to 10 redirect hops; if it has no content by then, Search Console reports a redirect error. Google's crawl budget guide also advises avoiding long redirect chains, which it says have a negative effect on crawling.
Page speed
The final page cannot start loading until the last redirect has been answered. Every hop costs a network round trip, and a hop to a new host also needs a DNS lookup, a new connection and, for HTTPS, a TLS handshake. On mobile connections, three or four redirects can add several hundred milliseconds before the first byte of the real page. The Redirect Latency Checker shows what each hop costs.
Security of short and unknown links
Short links and many tracking links in emails hide their destination. Phishing campaigns also abuse open redirects on well-known domains, so a link that starts on a trusted site can end somewhere else entirely. The Short URL Expander reveals every domain along the way, and whether any hop drops from HTTPS to plain HTTP, before you click.
Affiliate and tracking links
Marketing links often pass through several services before the landing page, and each must forward the query string, or UTM parameters, click IDs and affiliate tags are silently lost. The final URL shows whether they survived and whether the link still reaches the intended page.
Migrations, HTTPS and the canonical host
After a redesign, a domain move or an HTTPS switch, every old URL should reach its new equivalent in one permanent redirect. The four basic variants of a site (http:// and https://, with and without www) should all land on one canonical address. These rules break quietly: a new CDN rule, a plugin update or a server move can add a hop or a loop without anyone noticing.
How to check a redirect with TrueURL
TrueURL runs every check on Cloudflare's edge network, so you can inspect links you do not trust without opening them in your browser. The URL Redirect Checker on the home page handles a single URL; the Redirect Chain Checker and the other specialized tools use the same engine.
Step 1: Enter the URL
Paste the URL and run the check. Without a scheme, https:// is assumed; type http:// to test plain HTTP.
Step 2: Adjust Advanced Settings when needed
By default the checker sends a GET request with a current desktop Chrome User-Agent, no cookies and a limit of 20 redirects. Advanced Settings changes that:
- HTTP Method: GET, HEAD or POST. HEAD is lighter, but some servers answer it differently, and without a body client-side redirects cannot be detected. POST sends the request body you enter, for form handlers and APIs. Later hops follow browser rules: after a POST, a 301 or 302 continues as GET, a 303 always does, and 307 and 308 keep the method and body.
- Max Hops: the number of redirects to follow, from 1 to 50. The default of 20 is the limit in the Fetch Standard and in Chrome and Firefox. Set it to 10 to see whether a chain fits Googlebot's limit.
- Custom User Agent: empty means desktop Chrome. Presets include Safari on iPhone, Chrome on Android, Googlebot (smartphone and desktop), Bingbot, the Facebook and X link preview bots, and curl.
- Custom Request Headers: extra headers sent on every hop, for example
Accept-Language: fr-FRto trigger a language redirect. - Cookies: enter
name=value; other=valueto reproduce a logged-in, consent or region state. Cookies set along the chain are kept for later hops, as in a browser. - Client-side redirects: follow meta refresh tags and simple JavaScript redirects, or only report them.
- Ignore SSL Errors: Cloudflare's edge always validates certificates, so this cannot skip a broken one. A TLS error is reported on the hop where it happened.
Step 3: Read the result
The result starts with the final URL and its status code. The chain below it has one row per hop, with:
- the URL requested and the HTTP method used;
- the status code and reason phrase (the status code reference explains each one);
- the response time, from sending the request until the headers arrived, including any DNS lookup and connection setup;
- the
Locationit points to; - the response headers and the names of any cookies the hop set.
Each redirect is labeled with how it happened: HTTP status code, meta refresh (with its delay in seconds) or JavaScript. Client-side redirects that were found but not followed are reported too. Just as important is how the check ended:
| Outcome | What it means |
|---|---|
| Final response | The chain reached a response that is not a redirect, such as 200 OK or 404 Not Found. |
| Redirect loop | The next request would repeat an earlier one: same URL, method and cookies. The result shows which hop closes the loop. |
| Max hops reached | The chain was still redirecting at the limit. The next target is shown but not requested. |
| Error | A hop failed: DNS, connection, TLS or timeout, or the redirect target was not a valid or allowed URL. |
Warnings flag a temporary redirect in the chain, a downgrade from HTTPS to HTTP, more than three redirects, a final URL on another domain, client-side redirects, and HEAD requests that could not read a page body.
One warning needs care. Some sites show automated or data-center traffic a bot challenge, such as Cloudflare's "Just a moment..." page. TrueURL marks responses that look like one, because the check reached the site's protection layer, not the destination. A real visitor may end up somewhere else.
How to check redirects from the command line
curl is preinstalled on macOS, Windows 10 and 11 and most Linux distributions, and it shows exactly what the server sends, with no browser cache involved. The examples use a Unix shell; in Windows PowerShell 5.1, type curl.exe, because curl is an alias for Invoke-WebRequest there, and write NUL instead of /dev/null.
Look at one hop
curl -I https://example.com/old-page-I sends a HEAD request and prints the response headers, including the status line and any Location. curl does not follow redirects unless asked. Because some servers treat HEAD differently, repeat the check as a GET when the result looks odd; -o /dev/null discards the body and -D - prints the headers:
curl -sS -o /dev/null -D - https://example.com/old-pageFollow the whole chain
-L follows redirects, and with -I or -D - curl prints the headers of every hop. A grep filter leaves a compact view:
curl -sIL http://example.com/Shoes | grep -iE '^(HTTP/|location:)'HTTP/1.1 301 Moved Permanently
Location: https://example.com/Shoes
HTTP/2 301
location: https://www.example.com/Shoes
HTTP/2 302
location: /shoes/
HTTP/2 200curl follows up to 50 redirects by default; --max-redirs 10 applies Googlebot's limit.
Print only the final URL
The -w (write-out) option prints details after the transfer, turning curl into a compact URL expander:
curl -sSL -o /dev/null -w '%{http_code} %{num_redirects} %{url_effective}\n' https://example.com/go%{url_effective} is the last URL fetched, %{num_redirects} the number of redirects followed and %{http_code} the final status. %{time_redirect} reports the seconds spent on redirects before the final request. Without -L, %{redirect_url} shows where the first redirect would lead.
Test POST requests
-d sends a body and makes the request a POST. When following redirects, curl then acts like a browser: it switches to GET after a 301, 302 or 303, and resends the POST and its body after a 307 or 308.
curl -sSL -o /dev/null -D - -d 'email=test%40example.com' https://example.com/subscribeAvoid combining -X POST with -L. -X forces the method on every request, so curl keeps sending POST after a 301, 302 or 303 where a browser would switch to GET, and you test a chain no real client produces.
Change the User-Agent, headers and cookies
# Smartphone User-Agent
curl -sIL -A 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1' https://example.com/
# Extra request header
curl -sIL -H 'Accept-Language: de-DE,de;q=0.9' https://example.com/
# Send a cookie and keep the cookies set along the chain
curl -sSL -o /dev/null -D - -b 'consent=yes' -c cookies.txt https://example.com/-A sets the User-Agent, -H adds a header and -b sends cookies. -c saves received cookies to a file and switches on curl's cookie engine, so a cookie set by one hop is sent on the next.
curl does not run JavaScript or act on meta refresh tags. If its last response is a 200 OK HTML page but your browser ends up elsewhere, the redirect happens on the client side.
How to check redirects in browser DevTools
DevTools shows the chain as your own browser sees it, with your cookies, extensions and location:
- Open DevTools (F12, or Cmd+Option+I on a Mac) and select the Network tab.
- Turn on Preserve log in Chrome and Edge, or Persist Logs in the Firefox network settings menu. Otherwise the list is cleared on every page load, and client-side redirects vanish from view.
- Turn on Disable cache, so a cached redirect does not hide what the server sends today.
- Enter the URL in the address bar.
Each hop appears as its own row with its 3xx status; select it and open Headers to see the location response header. In Chrome, "(disk cache)" or "(memory cache)" in the Size column means the redirect came from the cache, not the server.
Chrome sometimes lists a 307 Internal Redirect from http:// to https://. The server never sent it: the browser upgraded the request itself, usually because it has stored an HSTS policy for the site. To see what the server does with plain HTTP, use curl or TrueURL.
Common redirect problems and how to fix them
Chains longer than one hop
Chains grow in layers: a rule from an old migration points to a URL that a later migration redirected again. Point every rule straight at the final destination, and update internal links, canonical tags, hreflang annotations and sitemaps so your own site never triggers a redirect. The Bulk Redirect Checker shows which old URLs still need more than one hop.
Redirect loops
Chrome reports a loop as "redirected you too many times" (ERR_TOO_MANY_REDIRECTS); Firefox says "The page isn't redirecting properly". Common causes:
- HTTPS behind a proxy or CDN. The origin redirects HTTP to HTTPS, but the proxy reaches the origin over plain HTTP, so the origin never sees HTTPS and redirects forever. On Cloudflare, this is the classic result of the Flexible SSL/TLS mode; use Full (strict), or have the origin check
X-Forwarded-Proto. - Two layers that disagree, such as a CDN rule that removes
wwwwhile the server adds it, or a framework that adds a trailing slash the CDN strips. - Cookie-dependent redirects. A login or consent page sends visitors back to the original URL, which redirects them to the login page again because the cookie was not stored.
The Redirect Loop Checker shows which hop closes the loop. Then make one layer responsible for each rule.
Mixed 301 and 302 in one chain
A chain of 301, then 302, then 200 is a permanent move with a temporary step in the middle. It often comes from a default: Express's res.redirect() and PHP's header('Location: ...') both send 302 unless told otherwise. Use a permanent code at every hop and confirm it with the 301 Redirect Checker. Our guide to HTTP redirect status codes explains when each code fits.
HTTP to HTTPS to www double hops
A very common chain is http://example.com → https://example.com → https://www.example.com: two hops where one would do. Redirect each non-canonical variant directly to the final HTTPS URL, then test all four with the HTTPS Redirect Checker.
One exception is deliberate. If your canonical host is www and you add the domain to the HSTS preload list, hstspreload.org requires http://example.com to redirect to https://example.com first, so browsers record the HSTS policy for the bare domain.
Trailing slash inconsistencies
/pricing and /pricing/ are different URLs. If both return 200 OK, you have duplicate content; if two layers redirect each to the other, you have a loop. Pick one form, redirect the other to it with a single 301 and link consistently. The Trailing Slash Checker tests both forms at once.
Mobile-only redirects
Separate mobile sites, app-install prompts and device detection sometimes send phones elsewhere, often to the mobile home page instead of the equivalent page. Under mobile-first indexing, Google crawls mainly with its smartphone crawler, so the mobile chain matters most for indexing. Compare both with the Mobile vs Desktop Redirect Checker.
Redirects in sitemaps
A sitemap should list the canonical URLs you want in search results, and those return 200 OK. Redirecting entries waste crawl requests and send conflicting canonical signals. Run the Sitemap Redirect Checker after every migration and replace each redirecting entry with its final URL.
JavaScript and meta refresh redirects
Google treats an instant meta refresh as a permanent redirect and a delayed one as temporary. It only sees JavaScript redirects after rendering the page, a step that comes after crawling and can fail. Many other crawlers, link preview bots and command-line tools do not run JavaScript at all, and some ignore meta refresh too. Use server-side redirects wherever you control the server, and find client-side ones with the Meta Refresh Checker.
Redirect checklist
Run through this list after a migration, a CDN change or before a campaign launch:
- Every old URL reaches its final destination in one hop.
- Permanent moves use 301 or 308 at every hop.
- All four protocol and host variants end on the canonical HTTPS URL.
- No hop goes from HTTPS to HTTP.
- Query strings, including UTM parameters and affiliate IDs, survive the chain.
- Each URL has one trailing slash form, and the other form redirects to it.
- Desktop, smartphone and Googlebot requests end on equivalent pages.
- Server-side redirects replace meta refresh and JavaScript wherever possible.
- Internal links, canonical tags, hreflang and sitemaps point to final URLs.
- Removed pages without a replacement return 404 or 410 instead of redirecting to the home page.
- Redirects from a site move stay in place; Google recommends at least a year.