State and authentication

Follow redirects with boundaries

Follow redirect chains, inspect every hop, and understand why credentials need special care across hosts.

A redirect tells the client to go request another URL. The server answers with a 3xx status and a Location header pointing somewhere else.

Browsers follow that pointer automatically. curl doesn’t. It shows you the 3xx response and stops, unless you pass --location (short form -L).

That default is a feature. curl never visits a URL you didn’t ask about unless you opt in.

Inspect a chain

Follow a two-hop chain with verbose output on:

curl --location --verbose https://httpbin.org/redirect/2 -o /dev/null

The pattern repeats twice. A request, a < HTTP/2 302 response, a < location: header, then a * Issue another request line as curl moves to the next URL. Read every status and every Location value. Notice the final URL, and whether the hostname changes along the way.

When you want the summary without the noise, two write-out variables do it:

curl --location --silent --output /dev/null \
  --write-out 'hops=%{num_redirects} final=%{url_effective}\n' \
  https://httpbin.org/redirect/2

The output is hops=2 final=https://httpbin.org/get. If num_redirects surprises you, something in the chain is doing more than you thought. I run this one-liner on any URL before I trust it in a script.

Put a ceiling on it

Two pages redirecting to each other create a loop. curl gives up after 50 hops by default. That’s a lot of requests for a diagnostic command, so set a tighter bound:

curl --location --max-redirs 3 https://httpbin.org/redirect/5

This exits with code 47, “maximum redirects followed”, after the third hop. In a script, a low --max-redirs turns a misconfigured redirect loop into a fast, clear failure instead of a slow crawl through 50 requests.

The credential boundary

This is where redirects get dangerous. A chain can hop from the host you trust to one you never intended. Any credentials attached to the request could travel with it.

curl protects you here. When a redirect changes the hostname, it stops sending --user credentials and the Authorization header. The next hop gets an anonymous request.

--location-trusted disables that protection. Every hop receives your credentials, whatever host it lands on.

Do not turn that on unless you’ve inspected the complete chain and every host in it is yours. Run the verbose command first, read every location: line, then decide.

Try it: chain --location --verbose against a short URL from a link shortener you use, and count the hops. Then look at the hostnames. That’s the boundary your credentials would have crossed.

Lesson completed

Take this course offline

Get every free book, course edition, and software download.

Get the download library →