The HEAD method asks for the response a server would send to GET, without transferring the response content. It is useful for checks that need status, validators, type, or length, but only when the metadata remains aligned with the real GET path.

Compare a normalized header set

Dynamic headers such as Date will differ between requests. Compare the fields that describe the selected representation:

url=https://www.example.test/downloads/manual.pdf

curl -sS -I "$url" > head.headers
curl -sS -D get.headers -o /dev/null "$url"

for file in head.headers get.headers; do
  printf '== %s\n' "$file"
  awk '
    /^HTTP\// ||
    tolower($1) ~ /^(content-type:|content-length:|content-encoding:|cache-control:|etag:|last-modified:|vary:)$/ { print }
  ' "$file"
done

The two requests should select the same status and representation metadata. Compression negotiation also belongs in the comparison: send the same Accept-Encoding value to both requests.

Do not use HEAD as the only release check

A server can synthesize plausible headers while the file is missing, unreadable, or truncated. Keep one small GET in the smoke test and verify its body or checksum. HEAD reduces transfer cost; it does not prove the payload.

Check redirects explicitly

Without --location, curl -I reports the first response. That is useful when testing redirect policy. With --location, it reports the final chain, which is useful when testing the destination. Record which question the command answers:

curl -sS -I --max-redirs 0 https://old.example.test/manual
curl -sS -I --location https://old.example.test/manual

Treat method-specific failures as configuration defects

A static page that returns 200 to GET and 405 or 404 to HEAD usually exposes a proxy or routing inconsistency. Fix the method handling instead of teaching monitors to ignore it, unless the endpoint contract deliberately disallows HEAD.

Sources