REFERENCE

How link shorteners and redirect chains hide where a link goes

How HTTP redirects, meta refresh, JavaScript and shorteners hide a link's destination, with hop counts we measured on 23 public URLs.

Updated 2026-10-108 sources

On this page
Short answer

A redirect chain is the series of responses a link passes through before it reaches a final page, and the address a person sees first says nothing about where the chain ends. In our measurement on 10 October 2026 [8], 14 of 17 well-known sites redirected a plain http:// request at least once, and 6 of them took two redirects; a walker that reads only status codes cannot see redirects a page triggers through HTML or JavaScript.

Key facts#

  • RFC 9110 defines five redirect status codes that carry a Location header: 301, 302, 303, 307 and 308 [1]. #
  • RFC 9110 also says a client “SHOULD detect and intervene in cyclical redirections” and notes that an earlier specification recommended a maximum of five redirections [1]. #
  • A <meta http-equiv="refresh"> tag is a timed redirect defined in the HTML Standard, and location.assign() navigates from JavaScript [2][3]. Neither produces a 3xx status, so a tool that reads only status codes does not see them. #
  • On 10 October 2026, 14 of 17 well-known public sites we requested over http:// redirected at least once; the maximum was 2 redirects. #
  • OWASP names open redirects (an application that redirects to a URL supplied in a parameter) as a phishing risk because the link carries the trusted site’s name [4]. #
  • Abnormal AI reported that 21.6% of the phishing emails it analysed in the second half of 2025 used redirect links, and 10.2% of those used link shorteners [7]. #
  • As of October 2026, StormDoor’s links gate follows HTTP redirects only, up to 10 fetches, and does not parse page bodies. #

How does an HTTP redirect work?#

A server answers a request with a 3xx status and a Location header; the client repeats the request at the new address. RFC 9110 separates permanent redirects (301, 308) from temporary ones (302, 307) and says 307 and 308 were added to preserve the request method, because clients had converged on changing POST to GET for 301 and 302 [1]. A client following a chain applies the same rule at each hop, so the first address shown to a user can be several requests away from the page they land on.

The RFC sets no mandatory hop limit. Real clients choose their own: StormDoor’s gate documentation puts curl’s default at 50 and most browsers at around 20 (we did not re-verify those figures), so the same chain can resolve in one tool and fail in another. StormDoor’s own cap is lower than both (see below).

Why does a plain HTTP client miss some redirects?#

Two redirect mechanisms live in the page, not in the headers:

  • Meta refresh. The HTML Standard describes http-equiv="refresh" as a pragma that “acts as a timed redirect”, with a time in seconds and an optional URL [2].
  • JavaScript. Location.assign() “causes the window to load and display the document at the URL specified” [3]. Any script can call it, including after a delay, a user-agent test or an IP test.

The server’s status for such a page is 200 OK. We checked this on loopback with three local pages served from our own machine: the HTTP 302 page returned status 302 with a redirect URL; the meta-refresh page and the JavaScript page both returned status 200 with no redirect URL.

A tool that only reads status codes therefore reports a one-hop, clean-looking chain for those pages. Only a tool that fetches the body and runs or parses it, usually a headless browser, follows them.

What is an open redirect?#

An open redirect is an application feature that sends users to a URL taken from a request parameter without validating it. OWASP gives the pattern http://example.com/example.php?url=http://malicious.example.com: the link begins on a trusted domain and ends elsewhere, and OWASP lists phishing as the main risk [4]. Its recommended fixes are to avoid redirects, map IDs to destinations on the server, or allowlist parsed scheme, host, port and path [4].

For a screening tool, an open redirect on a reputable domain is a hop that looks harmless. Reputation checks on the first domain pass; only the full chain reveals the destination.

Two illustrative chains, stepped one hop at a time (example domains, not captured traffic):

You clickedshort.example/x7Kp
You landed onwww.shop.example/autumn-sale
Redirects4 across 3 domains
  1. 301https://short.example/x7Kp
    Location: https://track.example/c?id=8812

    The shortener: the only address the reader sees.

  2. 302https://track.example/c?id=8812
    Location: http://shop.example/autumn-sale

    A click tracker logs the visit and passes it on.

  3. 301http://shop.example/autumn-sale
    Location: https://shop.example/autumn-sale

    The shop upgrades plain HTTP to HTTPS.

  4. 308https://shop.example/autumn-sale
    Location: https://www.shop.example/autumn-sale

    The shop moves to its preferred hostname.

  5. 200https://www.shop.example/autumn-sale

    The page that loads. Four redirects, three different domains.

All domains are reserved example domains (.example, RFC 2606). The chains illustrate common patterns; they were not captured from live traffic.

A shortener maps a short code to a long URL and answers with a redirect, so the visible text never shows the destination. Their policies matter because they decide what happens when a short link is bad or old:

  • Bitly says it calls its Abuse API while decoding a link to check whether the destination is malicious. A link in the “warn” category shows an interstitial with the long URL; in the “blocked” category the interstitial hides the long URL [6] (post dated 21 February 2023).
  • Google’s goo.gl stopped accepting new URLs in 2018. Google announced on 18 July 2024 that goo.gl links would stop responding after 25 August 2025, then updated the post on 1 August 2025 to say only links with no recent activity would be deactivated and all others would keep working [5]. A short link is only as durable as its operator.

Chaining two shorteners puts the destination behind two operators, each of which sees only its own hop. StormDoor flags two or more distinct shortener services in one chain (link.shortener_chain).

How often do phishing emails use redirects?#

Abnormal AI, an email-security vendor, analysed nearly 800,000 email attacks across more than 4,600 organizations in the second half of 2025 and reported that 21.6% of phishing attacks used redirect links, with 10.2% of those relying on link shorteners. Abnormal calls redirect chains “a deliberate evasion technique” [7]. This is one vendor’s customer sample, published 29 April 2026, and the page gives no further method.

What do redirect chains look like on ordinary sites?#

We walked 23 public URLs one hop at a time with curl on 10 October 2026, recording the status code at each hop (method in the Method section). The first group is 17 well-known sites and shortener home pages requested over http://.

Start URL Redirects Status sequence Final URL
http://google.com 1 301 > 200 http://www.google.com/
http://www.google.com 0 200 http://www.google.com
http://github.com 1 301 > 200 https://github.com/
http://www.github.com 2 301 > 301 > 200 https://github.com/
http://wikipedia.org 2 301 > 301 > 200 https://www.wikipedia.org/
http://en.wikipedia.org/wiki/Main_Page 1 301 > 200 https://en.wikipedia.org/wiki/Main_Page
http://amazon.com 2 301 > 301 > 200 https://www.amazon.com/
http://www.bbc.com 1 302 > 200 https://www.bbc.com/
http://bbc.co.uk 2 301 > 301 > 200 https://www.bbc.co.uk/
http://youtube.com 2 301 > 301 > 200 https://www.youtube.com/
http://reddit.com 2 301 > 301 > 403 https://www.reddit.com/
http://example.com 0 200 http://example.com
http://www.mozilla.org 1 301 > 200 https://www.mozilla.org/
http://bit.ly 1 302 > 200 https://bitly.com/
http://tinyurl.com 1 301 > 200 https://tinyurl.com/
http://t.co 0 520 http://t.co
http://goo.gl 1 301 > 400 https://goo.gl/

Of these 17, 3 had no redirect, 8 had one and 6 had two. The first hop was 301 in 12 cases and 302 in 2 cases. t.co answered 520 and reddit.com ended in 403 at the last hop, which we believe is bot filtering but did not verify; goo.gl ended in 400 on its root page. We did not create any shortener links.

The second group is httpbin.org’s documented /redirect/N endpoints, which return N redirects:

Start URL Redirects Status sequence Final URL
https://httpbin.org/redirect/1 1 302 > 200 https://httpbin.org/get
https://httpbin.org/redirect/3 3 302 > 302 > 302 > 200 https://httpbin.org/get
https://httpbin.org/redirect/10 10 302 > 302 > 302 > 302 > 302 > 302 > 302 > 302 > 302 > 302 > 200 https://httpbin.org/get
https://httpbin.org/redirect/12 12 302 > 302 > 302 > 302 > 302 > 302 > 302 > 302 > 302 > 302 > 302 > 302 > 200 https://httpbin.org/get
https://httpbin.org/status/301 2 301 > 302 > 200 https://httpbin.org/get
https://httpbin.org/absolute-redirect/3 3 302 > 302 > 302 > 200 http://httpbin.org/get

Two points follow. Ordinary sites chain two hops for http:// plus a www canonicalisation, so “more than one hop” alone is not suspicious. And /redirect/10 and /redirect/12 resolved in our 20-hop walk, yet would exceed a 10-fetch cap.

POST /v1/links follows a URL’s redirect chain, then checks the final domain’s registration age and typosquat signals, and flags known shorteners (gate docs). You can try the same chain walk in the free redirect checker and the link checker. StormDoor makes both tools.

From the gate’s implementation and its documentation:

  • Status codes only. It follows 301, 302, 303, 307 and 308 and never reads a page body. Meta-refresh and JavaScript redirects are not followed, so a chain that continues that way ends at the page that contains it. The gate also does no content scanning of the destination.
  • 10 fetches. The cap is 10 hops. By our reading of the loop, a chain of up to 9 redirects resolves and one with 10 or more is cut off, which emits link.hop_cap_exceeded. We did not run this against a live chain.
  • 8-second budget for the redirect-chain check.
  • HEAD first. Each hop uses HEAD, falling back to GET only on 405 or 501. A server can answer HEAD and GET differently.
  • Unsafe hops are refused. A redirect to a non-HTTP(S) scheme or a non-public host stops the walk and emits link.unsafe_redirect_target. The docs state this per-hop validation does not fully close DNS rebinding.
  • One vantage point. The gate cannot see cloaking that depends on the visitor’s user agent, referrer or IP. Its docs note that long chains are a common cloaking technique.

A browser-based tool will catch JavaScript redirects that this gate misses; a status-code walker is faster and cheaper, and it will not execute attacker-controlled script.

Method#

  • Date and host. All measurements on 10 October 2026 from one server, using curl with --max-redirs 0 per hop, a 15-second timeout and a hop cap of 20. HEAD first, GET on 405 or 501, as the gate does.
  • Sample. 23 URLs: 17 chosen by hand (major sites and shortener home pages), plus 6 httpbin.org endpoints. This is a convenience sample, not representative of the web.
  • Counted. Redirect count is the number of 3xx responses with a Location before a non-redirect response.
  • Not done. No malicious URLs were visited. No browser was used, so JavaScript and meta-refresh behaviour on live sites is not measured. Results depend on location and user agent and can change.
  • Local demo. Three pages served on loopback (an HTTP 302, a meta-refresh page and a JavaScript location.assign page) were requested with curl on 10 October 2026; the status and any redirect URL curl reported were recorded.
  • Limits. One run, one vantage point, no repeats, so a site’s answer on another day or from another network may differ.
  • Not verified. The common claim that appending + to a Bitly link previews its destination: we found it only on third-party pages and not in Bitly’s documentation, so we left it out.

Sources#

  1. IETF, RFC 9110 section 15.4, accessed 2026-10-10.
  2. WHATWG, HTML Standard, refresh pragma, accessed 2026-10-10.
  3. MDN, Location.assign(), accessed 2026-10-10.
  4. OWASP, Unvalidated Redirects and Forwards Cheat Sheet, accessed 2026-10-10.
  5. Google Developers Blog, Google URL Shortener links will no longer be available, accessed 2026-10-10.
  6. Bitly, Trust and Safety: An Overview of Our Abuse System, 21 February 2023, accessed 2026-10-10.
  7. Abnormal AI, 2026 attack landscape report: phishing, 29 April 2026, accessed 2026-10-10.
  8. StormDoor internal measurement, 2026-10-10; method described in this article.
Try it on your own input

Redirect checker

Hear when StormDoor opens

StormDoor is not open for signups yet. Join the waitlist and we will email you when it is.

WHAT WOULD YOU USE IT FOR?