HTTP headers · Response

ETag

ETag identifies a specific version of a representation so caches and clients can revalidate it cheaply.

Key facts

TypeResponse
Syntax<code>ETag: "abc123"</code>
Weak<code>W/"abc123"</code>
Revalidation<code>If-None-Match</code>
Success304 with no body
GenerationContent hash or build id
StandardRFC 9110 §8.8.3

Validators and the 304

The client stores an ETag with the body. On the next request it sends If-None-Match, and the server compares. If the representation has not changed, the server answers 304 Not Modified with no body, saving bandwidth while refreshing the stored copy's lifetime.

A strong ETag promises byte equality, which matters for range requests and integrity. A weak ETag, prefixed with W/, promises only semantic equivalence: the content means the same thing but may differ in insignificant ways.

Generating a stable value

Any value works as long as it changes when the bytes change and stays stable when they do not. A content hash is reliable but costs CPU; a build identifier plus mtime is cheap but can collide across deploys. ETags must be quoted, and they must differ between representations that vary by encoding or language.

ETag does not replace Cache-Control. It enables revalidation; Cache-Control decides when revalidation is needed. Without a cache lifetime, a client may revalidate on every request.

Frequently asked questions

Can I use ETag instead of Last-Modified?

Yes, and it is more precise. Sending both is allowed; If-None-Match takes precedence when both validators are present.

Is ETag unique across servers?

No. It is only compared with the same resource on the same server, so a hash does not need a global namespace.

New tools, straight to your inbox

One short email when we add tools worth using. No spam, unsubscribe anytime.