Learn · Click tracking · Updated 2026-08-14

How to test a redirect before you trust it

Open the link with your browser's developer tools on the network tab, or run curl -I -L from a terminal, and read the status code and destination of every hop until you reach the final page. Anything other than a clean chain ending in a 200 is worth investigating.

  1. Open the link in a fresh browser tab with developer tools open
    Switch to the network tab before you load the link, not after, so the request is actually captured from the first hop.
  2. Load the link and watch the network tab for every hop
    Each redirect shows up as its own row. A link with one redirect shows two requests total; a link with three shows four.
  3. Read the status code and location header of each hop
    Click into each request in the chain to see whether it returned a 301, 302, 307, or 308, and what URL it pointed to next.
  4. Confirm the final URL loads with a 200 status
    The last row in the chain should be a normal 200 response for the page you actually intended to land on, not another redirect and not an error.
  5. Repeat the check with curl -I -L from a terminal
    This is faster once you know what you are looking for, and it works without a browser, which is useful for scripting a check across many links at once.
  6. Test again inside an in-app browser if the link will be shared on social
    Instagram, TikTok, and Facebook's built-in browsers sometimes handle a redirect chain differently than Safari or Chrome, so a link that passes a desktop test can still misbehave from the app it was actually shared in.
  7. Confirm tracking parameters survived to the final URL
    Check the last URL in the chain for the UTM parameters or click ID you attached at the start. A redirect that does not explicitly forward the query string will silently drop them.

What testing a redirect checks

Testing a redirect means confirming three separate things: that every hop in the chain returns the status code you expect, that the chain ends at the correct final URL, and that nothing gets lost along the way. That last part is the one most people forget to check, and it is usually the one that causes the most damage later. A redirect can look completely fine to a visitor, the page loads, nothing errors, while quietly dropping the tracking parameters that were supposed to travel with the click.

There are three practical ways to do this: your browser's own developer tools, curl from a terminal, and dedicated redirect checker tools. Each one shows you something slightly different, and the browser is generally the one to trust when the other two disagree.

Method 1: browser developer tools

Open the network tab before loading the link, load it, and read the requests that appear. Every hop shows up as its own row with its own status code, and clicking into any one of them reveals the response headers, including the Location header telling the browser where to go next. This is the most reliable method. It runs the exact same rendering engine a real visitor's browser would use, JavaScript redirects and meta refreshes included, rather than simulating one.

Method 2: curl, and the flag that trips people up

From a terminal, curl -I https://your-link sends a HEAD request and shows you the response headers, but only for the first hop. If there is a redirect chain behind it, curl will not follow it on its own, which leads a lot of people to conclude a link only has one redirect when it actually has three. Add the follow flag: curl -I -L https://your-link makes curl follow every hop and print the headers for each one along the way, giving you the full chain from a single command rather than one hop at a time.

Curl is faster than a browser for a quick check, and it is scriptable across a whole list of links at once, which a browser is not. What it will not show you is anything that depends on JavaScript running, so a client-side redirect will not appear in curl's output the way it would in a browser's network tab.

Method 3: an online redirect checker

A redirect checker tool wraps the same request curl makes into a page that lists the chain for you without needing a terminal. This is convenient, but it comes with the same limitation curl has: it is making its own request from its own server, not from a browser, so anything that depends on JavaScript, cookies already set in your browser, or the specific behavior of an in-app browser will not show up in the result.

Method Shows every hop Shows exact status codes Catches JS and meta refresh redirects Needs no install
Browser developer tools Yes Yes Yes Yes
curl -I -L Yes Yes No No, needs a terminal
Online redirect checker Usually Usually No Yes

Why curl -I can show you something a real visitor never sees

Curl's -I flag sends a HEAD request, which asks a server for headers only, no page body. Most redirects behave identically whether the incoming request was a HEAD or a GET, which is why -I is normally a safe shortcut. It is not universal, though. A server that decides its response based on the request method, which is rare but not unheard of on custom redirect logic, can hand a HEAD request a different status code than the GET request a real browser sends when someone clicks the link. If a curl test and a browser test genuinely disagree on the same link, trust the browser, since it is running the same request type a real visitor's click produces.

This is also where the distinction between a 302 and a 307 stops being academic. A 303 always forces the next request to be a GET, regardless of what the original request was. A 307 explicitly preserves the original method and any body sent with it. For a simple tracked link this rarely matters, since almost every click is a GET to begin with, but it matters a great deal for anything redirecting after a form submission, where switching the method silently drops the data that was supposed to travel with it.

Spotting a redirect loop

A redirect loop happens when a chain points back at a URL it already visited, so it never reaches a final page. A browser will usually stop after a fixed number of hops and show an explicit error, something like "too many redirects," rather than hanging indefinitely. In the network tab, this shows up as the same URL appearing more than once in the chain, which is easy to miss if you are only glancing at the row count rather than reading each destination. Curl behaves similarly: without a limit set, curl -L will eventually give up and report that it hit its default redirect limit, which is itself a useful signal that something in the chain is circular rather than simply long.

What each hop tells you

A 301 or 308 means the link is telling you, and any crawler reading it, that the old URL has moved for good. A 302 or 307 means the opposite, that this is temporary and the old URL might still matter later. If a link that is meant to be a permanent redirect is showing up as a 302, or the reverse, that is worth fixing, not just noting. The full breakdown of what each status code means and when to use it is in what is a redirect.

The in-app browser problem most checks miss

A redirect chain that passes a clean test on desktop Chrome does not automatically pass the same test inside Instagram's or TikTok's built-in browser. These in-app browsers are their own rendering environment, with their own cookie handling and their own quirks around multi-hop chains, and they are also the environment most bio link clicks actually happen in. Test only on a desktop browser and you have effectively never tested the link in the environment it will mostly be used. If a link seems to work everywhere except when opened from the app it was posted in, that mismatch, and what to do about it, is covered in why links open in the wrong browser.

Checking whether tracking data survives the chain

Once the chain itself checks out, look at the final URL specifically for whatever you attached at the start, a UTM parameter or a click ID from an ad platform. A redirect only forwards what it is explicitly told to forward. A redirect built to always point at one fixed destination will drop everything after the question mark without any visible error, the page still loads fine, and the only symptom shows up days later as a pile of clicks in your reporting with no source attached. This is also why a custom domain on your own short links is worth setting up properly. It is one less redirect hop between the click and the destination, and one less place for a parameter to disappear.

What a failed test looks like, and how to fix it

A failing test usually shows up as one of a small number of patterns: a chain that loops back on itself and never reaches a final page, a hop that returns a 404 or 500 partway through, a final URL missing the query string it should have kept, or a chain that behaves correctly on desktop but breaks specifically inside an in-app browser. Each points at a different fix: a broken redirect configuration, a dead destination page, a redirect that does not preserve query parameters, or an in-app browser incompatibility. None of that is visible from clicking the link once yourself and watching it load. Reading the actual network requests is the only way to know which one you are dealing with.

Common questions

Does curl -I show the whole redirect chain by itself?
No, plain curl -I only shows the first hop's headers and stops there. Add -L so curl follows every redirect and prints the headers for each hop along the way.

Will testing a link count as a real click in my analytics?
Usually yes, since the request still hits the tracking layer the same way a real visitor's click would. If you are testing a link that logs clicks, expect your own test to add one, and account for that when reading the numbers afterward.

Why does a link work on my phone's browser but not from the app I posted it in?
In-app browsers inside Instagram, TikTok, and Facebook are a separate rendering environment from Safari or Chrome, with their own handling of cookies and multi-hop redirects. A link needs to be tested specifically inside that environment, not just on a normal mobile browser.

What redirect status code should a permanent short link use?
A 301 or 308 signals that the destination is permanent, which is right for most tracked short links. A 302 or 307 signals a temporary destination and is the wrong choice if the link is meant to keep working the same way indefinitely.

Related: What is a redirect? · What is an in-app browser? · Why do links open in the wrong browser? · What is a click ID?