Back to HTTP Methods

HEAD

Identical to GET but the server returns only headers, no response body.

Safe Idempotent Cacheable Has Request Body

What it does

HEAD is GET's quieter sibling: same request, same response headers, same status code — but the server never sends a response body. You get all the metadata about a resource (size, type, last-modified date, whether it exists at all) without downloading the actual content.

The spec requires servers to respond to HEAD exactly as they would to GET, minus the body. If a header would say Content-Length: 50000 on a GET, it says the same thing on a HEAD — even though nothing is actually transferred.

Semantics

Property Value Why it matters
Safe Yes Read-only, same as GET
Idempotent Yes Repeating it changes nothing
Cacheable Yes Same caching rules as GET
Request body No Never sends one
Response body No This is the entire point of HEAD

Syntax & example request

HEAD /files/report.pdf HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Length: 4582931
Last-Modified: Tue, 03 Jun 2026 10:15:00 GMT

No body follows — the response ends after the headers.

curl example

curl -I https://example.com/files/report.pdf

-I tells curl to send a HEAD request and print just the response headers.

Common status codes returned

  • 200 OK — resource exists, here are its headers → see 200
  • 304 Not Modified — conditional HEAD, still valid → see 304
  • 404 Not Found — resource doesn't exist → see 404

HEAD vs GET vs OPTIONS

HEAD GET OPTIONS
Returns a body No Yes Sometimes (small)
Purpose Metadata about a resource Fetch the resource Discover allowed methods/capabilities
Same headers as GET Yes, identical No

HEAD tells you about this specific resource. OPTIONS tells you what you're allowed to do with a resource (or the server in general).

Real-world usage

  • Checking if a file exists before downloading it (avoids wasting bandwidth on a 404)
  • Getting Content-Length to show a download-size estimate or progress bar before starting the actual GET
  • Link checkers and uptime monitors verifying a URL resolves without pulling the full page
  • Cache validation — checking Last-Modified/ETag without re-fetching the body

Security considerations

HEAD leaks the same information a GET would (headers, existence of a resource, size) just without the body — so anything you'd protect on a GET (auth-gated resources, rate limiting) needs the same protection on HEAD. A common misconfiguration is guarding GET routes with auth middleware but forgetting the framework auto-generates a HEAD route that bypasses it.

FAQ

Do servers have to implement HEAD separately from GET?

Not really — most frameworks generate the HEAD response automatically from the GET handler, just stripping the body before sending. You rarely write HEAD logic by hand.

Why use HEAD instead of GET with a small Range request?

They solve different problems. Range still initiates a real (partial) content transfer. HEAD transfers zero bytes of body — it's the cheapest possible way to ask "does this exist, and what would I get if I asked for it?"

Can HEAD have a different Content-Length than the matching GET would?

It shouldn't. RFC 9110 requires the headers to match what a GET would return, precisely so clients can trust HEAD metadata without a follow-up GET.

Fun fact

HEAD predates most of the web's caching infrastructure — it was one of the three original methods in HTTP/1.0 (1996), alongside GET and POST, specifically so early clients could check "has this changed?" before the concept of conditional GET (If-Modified-Since) was fully worked out.

Related Methods