Reading an HTTP redirect chain — the underrated debugging skill
When 'is the site down' turns out to be 'the site is fine, but the redirect chain is sending users somewhere unexpected,' the only useful diagnostic is the full hop-by-hop trail. Here's what each step tells you, and the patterns that crop up most often.
A user reports that your site is "broken." You open it, it works fine. They sent a screenshot — they're staring at a generic login page that isn't yours. You ask which URL they typed; they typed yours. So how did they end up somewhere else?
The answer is almost always in the redirect chain — the sequence of 301 / 302 / 307 / 308 responses that quietly bounce a request from one URL to another before the browser shows anything. Browsers show only the final URL in the address bar. The hops in between are invisible unless you go looking.
This post is a field guide to the patterns we see most often, and what each one tells you about where the problem actually is.
A normal redirect chain looks like this
http://example.com/ → 301 → https://example.com/
https://example.com/ → 301 → https://www.example.com/
https://www.example.com/ → 200
Three hops. Two redirects. The first is the universal http → https upgrade. The second is the bare-domain → www canonical. Both are permanent (301), which is what tells the browser, search engines, and any HTTP cache "this redirect is stable, you can remember it."
Our website-down checker renders chains like this as a vertical timeline with status-coded badges. Reading top-to-bottom, you see what the user's request actually did.
The patterns that go wrong
1. Redirect to login the user didn't expect
https://app.example.com/dashboard → 302 → https://app.example.com/login?return_to=...
https://app.example.com/login?return_to=… → 200
The user's session cookie expired (or the cookie domain doesn't match this host, or they're on a different browser profile, or they got logged out by an admin action). Your dashboard correctly redirects unauthenticated requests to login.
When this happens to a real user, it usually feels like "the site is broken" because they didn't expect to be logged out. The chain makes the cause obvious in one screen.
2. Old domain → new domain, with the cookies still on the old one
https://oldname.com/ → 301 → https://newname.com/
https://newname.com/ → 200 (but: SSO cookies on oldname.com are useless here)
You renamed your domain. The redirect at the apex works. Internal links work. But session cookies, OAuth state, CSRF tokens — anything Domain=oldname.com — vanishes the moment the user lands on newname.com.
Common symptom: users say they "have to log in twice" or "kept getting kicked out" even though the site loads. The chain looks healthy but the cookie reset between hops is invisible to it.
3. Loop
https://example.com/a → 302 → /b
https://example.com/b → 302 → /a
https://example.com/a → 302 → /b
…
Browsers eventually give up with ERR_TOO_MANY_REDIRECTS (Chrome) or The page isn't redirecting properly (Firefox). Our checker stops at 5 hops by design and reports "Too many redirects" so you don't end up DDoS-ing yourself diagnosing the bug.
These are usually a misconfigured framework or middleware: the auth gate redirects unauthenticated → /login, but /login itself runs through the same gate, redirecting back to where it came from. Or a www → bare-domain rule paired with a bare-domain → www rule. Or two CDN rules that both want to "fix" the URL in opposite directions.
4. CDN landing → unexpected origin
https://www.example.com/path → 301 → https://example.com/path (Cloudflare normalisation)
https://example.com/path → 302 → https://example.example.workers.dev/path (worker route)
https://example.example.workers.dev/path → 503
Your front door is fine. The user is being routed to an internal worker / origin that's down or misconfigured. Without seeing the chain, this looks like "the whole site is broken" — when actually only the worker handling that one path is.
5. The mobile redirect
https://example.com/ → 200
https://example.com/ (User-Agent: iPhone) → 302 → https://m.example.com/
https://m.example.com/ → 200
Your desktop tests pass; mobile users hit a different host that has its own SSL config, its own deploy pipeline, its own bugs. If m.example.com's certificate is expired but example.com's isn't, mobile users see a security warning that desktop users never do. The redirect chain reveals it because we send a real HTTP request, not a synthetic one.
6. The "I forgot redirects exist" 200
https://example.com/ → 200
No redirect at all. Users typing example.com in their browser get the bare domain working. But your marketing emails, your business cards, your CI link checker — anything that hits https://www.example.com — gets a 404 or, worse, a hostnamemismatch SSL error. You assumed your registrar handled the bare/www split. It didn't.
Catch this one by checking both spellings.
How to actually use a redirect chain
Three quick rules:
-
Status codes mean what they say. 301/308 are permanent and cacheable; 302/307 are temporary; 303 is "the answer is somewhere else, GET it." If a chain has 302s where you expected 301s, browsers and CDNs won't cache them — you're paying for the redirect lookup on every request. If it has 301s where you expected temporary ones, users (and Googlebot) will hold onto the old URL forever, which is the right thing if you really did move and the wrong thing if you didn't.
-
The hop count matters. Each hop is a real round-trip. If your "https://example.com" → "https://www.example.com" → "https://app.example.com/login" chain has three redirects, that's at least three TLS handshakes for cold connections (HTTP/2 reuse helps, but only within a single host). Mobile users on flaky connections feel each one. Aim for one hop maximum to your canonical URL.
The Location header in a redirect can be relative (/path) or absolute (https://other.example.com/path). Both are spec-compliant. Most CDNs prefer absolute. If you're switching origin or scheme during a redirect, an absolute Location avoids a class of subtle browser-quirk bugs.
- Watch for unexpected hosts. If the chain hits a domain that isn't yours — a CDN's intermediate edge, a
*.workers.dev, a tracking service, a raw IP — that's information about your stack you might not have known. Sometimes useful, sometimes alarming.
A small toolbox
Beyond our checker, the commands that help:
# All hops, with status and Location, no body
curl -sI -L -o /dev/null -w '%{http_code} %{url_effective}\n' \
--max-redirs 10 \
https://example.com/
# Same but with full headers per hop
curl -sIL https://example.com/ | grep -E '^(HTTP|Location|Set-Cookie)'
# Watch a single hop without following
curl -sI https://example.com/curl -L is good enough for 90% of debugging. The browser dev tools' Network tab, with "Preserve log" on, is the other 10% — you can see redirects with their cookies and TLS info.
The takeaway
When somebody says a site is broken and the URL bar isn't where they expected, the redirect chain almost always has the answer. Pull it up, read top to bottom, and the cause is usually obvious in one of the hops. The skill is just looking — most people don't think to.