skip to content

questions

4

What does the HTTP HEAD method do, how must its response relate to the response a GET on the same URL would produce, and what should the Content-Length header say in a HEAD response?

level: juniorimportance: must knowfreq 55%

answer

  1. HEAD = GET minus body
  2. Same status, same headers as GET
  3. Content-Length = would-be body size
  4. Message ends at blank line — read nothing
  5. Saves bandwidth, not server CPU

basics

~20 s

HEAD asks for exactly what GET would return, minus the response body. The status line and headers must match the GET response, so Content-Length states the size of the body that GET would have sent, even though HEAD sends zero bytes.

solid answer

~50 s

**HEAD is a body-less GET.** The server runs the same logic it would for GET, returns the same status code and the same header fields, but omits the message body. It is safe and idempotent. The useful part is the metadata: `Content-Type`, `Content-Length`, `ETag`, `Last-Modified`, `Cache-Control`, `Accept-Ranges`. Clients use HEAD to check whether a resource exists, how big a download is, or whether a cached copy is stale, without paying for the transfer. **Content-Length is the classic trap.** In a HEAD response it describes the body GET *would* have sent, not the bytes on the wire (which are none). A client must therefore never try to read that many bytes after the headers — in HTTP/1.1 the message ends at the blank line. Getting that wrong desynchronises a keep-alive connection. A server may legitimately omit `Content-Length` if computing it would mean generating the whole body.

code

http · 9 lines
http
HEAD /downloads/app.iso HTTP/1.1
Host: example.com

HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Length: 734003200
Accept-Ranges: bytes
ETag: "9f1c-5e2"
Last-Modified: Tue, 05 Aug 2026 09:14:00 GMT

go deeper

for a junior

Know that HEAD returns headers only, that the headers mirror GET, and name one real use such as checking a file's size or existence before downloading.

for a middle

Explain the Content-Length rule precisely — it describes the body GET would send — and that the message body ends immediately after the headers regardless.

for a senior

Talk about framework implementations deriving HEAD from GET, header divergence bugs, cache interaction (GET can answer HEAD, never the reverse), and connection desync when a parser mishandles the framing.

for a principal

Frame HEAD as a metadata contract: monitoring, link checking, and range-download planning all depend on HEAD headers being byte-accurate, so treat divergence between HEAD and GET headers as a correctness defect with smuggling and cache-poisoning consequences.

## What HEAD is HTTP defines a small set of request methods. `HEAD` is defined as being identical to `GET` for the same target resource, with one difference: the server **must not** send a message body in the response. Everything else — the status code, the reason phrase, and the header fields — should be exactly what the equivalent `GET` would have produced. HEAD is *safe* (it is not expected to change server state) and *idempotent* (issuing it many times has the same effect as issuing it once). Those properties are why crawlers, monitoring probes, and link checkers reach for it freely. ## Why the headers must match GET The entire point of HEAD is to learn about a representation without transferring it. That only works if the metadata is truthful. A conforming server returns the same `Content-Type`, `Content-Length`, `Content-Encoding`, `ETag`, `Last-Modified`, `Cache-Control`, `Vary`, and `Accept-Ranges` that a GET would carry. If those diverge, every client decision built on the HEAD response — "is this a 400 MB file?", "has this changed since I cached it?", "can I request byte ranges?" — is built on a lie. ## The Content-Length rule This is what interviewers actually probe. In a HEAD response, `Content-Length` does **not** describe the number of bytes that follow the headers; it describes the size of the body the server *would* have sent for a GET. RFC 9110 puts it plainly: a server may send `Content-Length` in a HEAD response, and if it does, the value must be the one GET would produce. Equally, the server is allowed to leave it out when producing the number would mean generating the body anyway (a dynamically rendered page, for instance). The corollary is a client/parser rule: after the header block of a HEAD response, the message is over. Do not read `Content-Length` bytes. Do not wait for a terminating chunk if `Transfer-Encoding: chunked` is present. In HTTP/1.1 with persistent connections, a parser that ignores this consumes the *next* response as if it were this one's body — a connection desync, and one of the shapes that request-smuggling bugs take. In HTTP/2 and HTTP/3 framing is explicit (the stream ends with END_STREAM), so the header is purely informational, but the "describes the would-be body" semantics are unchanged. The same reasoning applies to a `304 Not Modified` response, which is likewise body-less while carrying the entity headers of the would-be body. ## What HEAD is used for - **Cheap existence and size checks** — `curl -I https://example.com/big.iso` before committing to a download. - **Freshness probes** — read `ETag`/`Last-Modified` and decide. (A conditional GET with `If-None-Match` is usually better: one round trip instead of two, and it returns the body when it *has* changed.) - **Link checkers and uptime probes** — verify a URL resolves to 200 without pulling megabytes. - **Capability discovery for ranged downloads** — check `Accept-Ranges: bytes` and `Content-Length` before parallelising a fetch. ## Implementation pitfalls Most web frameworks auto-derive HEAD from the GET handler: they run the handler and discard the body on the way out. That is the correct behaviour, and it costs the same server work as GET — HEAD saves *bandwidth*, not CPU. The bug appears when an application short-circuits, returning early for HEAD without running the handler: now the response is missing `ETag`, has no `Content-Length`, or reports a different `Content-Type` than GET, and clients that trusted it misbehave. On the caching side: a stored GET response can be used to answer a later HEAD, but a HEAD response can never be used to satisfy a later GET, because there is no body to serve. Some CDNs and proxies normalise HEAD into an upstream GET and drop the body themselves; that is legal and invisible to the client. Finally, because HEAD is safe, an endpoint that mutates state when a HEAD arrives is a defect — monitoring systems fire HEAD requests constantly and expect nothing to happen. ## Common confusions HEAD is not "a lightweight request for the server". It is not a substitute for a conditional GET. And a `Content-Length: 51200` on a HEAD response does not mean 51200 bytes are coming.

  • If you want to know whether your cached copy of a resource is still valid, why is a conditional GET usually better than a HEAD?
    A HEAD tells you the current ETag or Last-Modified, but if the resource changed you still need a second request to fetch it — two round trips. A conditional GET with If-None-Match or If-Modified-Since resolves both cases in one: 304 with no body if unchanged, 200 with the new body if changed. HEAD is better only when you genuinely never want the body, such as a size or existence check.
  • A framework returns HEAD responses with no Content-Length while its GET responses have one. Is that a bug?
    Not strictly a spec violation — a server is permitted to omit Content-Length from a HEAD response, typically because producing it would mean rendering the whole body. It is still a quality problem, because the main reason clients send HEAD is to learn the size. The usual fix is to run the normal GET pipeline and discard the body at the end so all entity headers stay identical.

HEAD is asking a librarian for the catalogue card — title, page count, edition, last revision date — without checking the book out. The card must describe the real book, or the card is useless.

saying these in an interview costs you the question

  • Saying a HEAD response must have Content-Length: 0
  • Reading Content-Length bytes of body after a HEAD response, desyncing a keep-alive connection
  • Claiming HEAD is cheaper for the server — it usually does the same work and only saves the transfer
  • Thinking a cached HEAD response can be replayed to satisfy a later GET
  • Implementing HEAD as a short-circuit that skips the GET handler, so ETag/Content-Type diverge from GET

context

open as a page

What is the HTTP OPTIONS method for, what does the Allow response header contain, and what does the request line `OPTIONS * HTTP/1.1` mean?

level: middleimportance: should knowfreq 45%

basics

~20 s

OPTIONS asks what communication options are available for a target. The server answers with an Allow header listing the HTTP methods that target supports, such as Allow: GET, HEAD, OPTIONS. The asterisk form OPTIONS * targets the server or proxy itself, not any resource.

open as a page

Explain what the HTTP CONNECT method does, how a browser uses it to reach an HTTPS site through a forward proxy, and what the proxy can and cannot observe once the tunnel is established.

level: seniorimportance: should knowfreq 35%

basics

~20 s

CONNECT asks a proxy to open a raw TCP connection to a host:port and then relay bytes blindly. The browser sends CONNECT example.com:443, gets 200, then performs TLS end-to-end through the tunnel. The proxy sees host, port, timing and byte counts — not URLs, headers, or bodies.

open as a page

The HTTP TRACE method makes a server echo the received request back to the client. What is it meant to be used for, and why do most production servers and proxies disable it?

level: seniorimportance: nice to knowfreq 25%

basics

~20 s

TRACE is a loop-back diagnostic: the final server echoes the request it received back as the response body, revealing how proxies rewrote it. It is disabled because the echo reflects cookies, Authorization headers, and internal proxy headers back to the caller — information disclosure, historically exploited as Cross-Site Tracing.

open as a page