How to inspect redirect chains with curl
Links in email campaigns, social posts and QR codes often conceal the final destination behind several redirects. Following them in a browser reveals the page, but it can also trigger analytics, download files or accept cookies. A command-line inspection gives you a clearer record of every server response.
A sparse page containing only a “Click here” link may redirect visitors back to the same domain with a tracking-style query parameter. The pattern alone does not prove malicious activity, yet it is worth examining when the landing page offers no context about its purpose, services or subject matter.
The curl utility sends HTTP requests and displays the headers returned by each server. It can expose intermediate addresses, status codes and tracking parameters without executing JavaScript or loading advertising. That makes it useful for checking redirects in Australian campaigns, affiliate links and shortened URLs.
Build a safe first request
Start by preserving the first response instead of immediately following it. This command retrieves a URL, prints the response headers and discards the body:
curl -sS -D - -o /dev/null --max-time 20 \
--proto '=https' 'https://example.com/start'
The -D - option writes response headers to standard output, while -o /dev/null prevents the page body from filling the terminal. The --proto setting restricts the initial request to HTTPS. Adding a finite timeout prevents an unresponsive server from leaving the command running indefinitely.
Place the complete URL inside single quotes. A query string containing an ampersand can otherwise be interpreted by the shell as the start of another command. For a URL that redirects to HTTP, restrict subsequent requests as well with --proto-redir '=https'.
Keep certificate verification enabled and avoid the tempting -k option. A certificate warning is part of the evidence rather than an inconvenience to suppress. The curl exit status also matters: a timeout, DNS failure or rejected certificate means no complete redirect chain was obtained.
Read each Location header
Without the -L option, curl stops after the first HTTP response. Look for the status line and the Location header within it. A location may be absolute, such as https://other.example.au/path, or relative, such as /campaign/42. Relative locations must be resolved against the URL that returned them.
The common redirect statuses have different meanings. A 301 normally indicates a permanent move, 302 a temporary one and 303 a request to retrieve another resource with GET. A 307 or 308 preserves the original request method. These distinctions can matter when a form submission or authenticated request is involved.
Do not rely exclusively on curl -I. That command sends a HEAD request, and some websites respond differently to HEAD than to GET. Fetching the headers while discarding the GET body usually gives a more representative first hop. Also remember that JavaScript redirects and HTML meta refreshes are not HTTP Location redirects, so they will not appear in this header sequence.
A tracked link might eventually point to a page labelled online casino game shows, for example. Whether it came through a publisher, affiliate network or unknown intermediary can only be established from the intervening responses, not from the destination’s subject matter.
Follow the chain while keeping limits
Once the first hop is understood, use -L to follow location headers while collecting all response headers and a compact summary:
curl -sS -L --max-redirs 10 --max-time 30 \
-D - -o /dev/null \
-w 'final=%{url_effective}\nstatus=%{http_code}\nredirects=%{num_redirects}\ntime=%{time_total}s\n' \
'https://example.com/start'
The --max-redirs setting stops a loop or excessively long sequence, while --max-time limits the entire operation rather than each individual request. In the output, url_effective identifies the final URL, http_code is its status and num_redirects counts the intermediate hops.
Method changes deserve attention. During an automatic redirect, curl commonly changes a POST to GET after a 301, 302 or 303 response. A 307 or 308 is intended to preserve the method and body. An investigation should record both the server’s status code and the request method actually sent on the next hop.
Avoid --location-trusted for ordinary inspection. It can forward credentials to a different host when the chain crosses domains. The safer default is to treat each destination as a separate trust boundary, especially when the chain moves from an Australian business domain to an unfamiliar advertising or payment service.
Track query parameters and cookies
A redirect can change meaning without changing the visible domain. For instance, example.com.au/click?ref=abc123 may return example.com.au/offer?id=456. The path and query string then identify the campaign, while the hostname remains constant.
Use curl’s write-out variables to compare the requested URL with its effective destination. Review every Location value as well, because a parameter might appear only on an intermediate hop. Look for campaign fields such as utm_source, utm_campaign, ref and click_id, as well as encoded URLs stored inside another parameter.
Cookies can also alter the route. A response may set a session cookie that is returned on the next request, causing the server to select a different offer. Use -c cookies.txt to record cookies and -b cookies.txt to resend them when reproducing a session. Begin with a clean cookie jar as well, because stale preferences can hide the public redirect path.
A URL promoted as a campaign landing page may add its own identifier before forwarding visitors elsewhere. Comparing the original query, each intermediate location and the final URL reveals whether identifiers accumulate, disappear or are replaced. That comparison is often more informative than the final page title.
Account for Australian conditions
Redirect timing can differ across Australia even when the destination is identical. Sydney and Melbourne observe daylight saving and shift between UTC+10 and UTC+11, while Brisbane remains on UTC+10 and Perth uses UTC+8. Record timestamps in UTC and include the relevant local time so daylight-saving changes do not distort an apparent delay.
The Australian market also shapes the URLs and commerce involved in a redirect. Australian organisations commonly use .com.au addresses, although .au and global domains are also used. Prices may be displayed in Australian dollars, and GST of 10% is commonly included. A redirect to an overseas checkout can therefore change the displayed currency, tax treatment or consumer information as well as the domain.
Australian legislation provides relevant context, but a technical trace is not a legal determination. The Spam Act 2003, administered by the Australian Communications and Media Authority, sets consent, identification and unsubscribe requirements for commercial electronic messages. Promotional redirect links in email can fall within those rules.
The Privacy Act 1988 and Australian Privacy Principles govern how covered organisations collect, use and disclose personal information. The Australian Consumer Law, administered through state and territory regulators and the Australian Competition and Consumer Commission, also makes deceptive conduct and misleading representations unlawful. Redirects that conceal a material change in destination or commercial terms warrant particular attention in that framework.
Produce a reproducible redirect record
A final investigation should preserve both machine-readable output and the command that produced it. A practical capture can be written to local files:
curl -sS -L --max-redirs 10 --connect-timeout 10 --max-time 30 \
--proto '=https' --proto-redir '=https' \
-D redirect-headers.txt -o /dev/null \
-w 'status=%{http_code}\nfinal=%{url_effective}\nredirects=%{num_redirects}\ntotal=%{time_total}s\n' \
'https://example.com/start' > redirect-report.txt
The header file shows every status and Location header, while the report supplies the final status, effective URL, redirect count and elapsed time. Keep the exact command, retrieval time, DNS result, remote address and relevant user agent with those files so another person can repeat the check under comparable conditions.
A second test with a different user agent or a clean cookie jar can distinguish a stable chain from one that varies by browser or session. Browser developer tools may then be useful for identifying JavaScript behaviour that curl cannot display. Comparing the two records prevents an HTTP-only result from being mistaken for the complete browser journey.
A defensible finding identifies the requested address, every observed hop, each status code, all parameter changes and the final destination. It also states which behaviour was confirmed directly and which remains uncertain, such as server logic that depends on JavaScript, location or a valid session.