An ETag is a version label the server attaches to a response. Clients send it back with If-None-Match to get a cheap 304 Not Modified when nothing changed, and with If-Match on writes so the server can reject an update made against a stale copy with 412 Precondition Failed.
What an ETag looks like
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
ETag: W/"0815"
The value is a quoted ASCII string. According to MDN, the method for generating it is not specified. Common choices are a content hash, a hash of the last modified time or a revision number. The optional W/ prefix, which is case sensitive, marks a weak validator.
Strong vs weak
- Strong validators are ideal for comparisons, but can be hard to generate efficiently.
- Weak validators are easy to generate but far less useful for comparisons. Two weak representations may be semantically equal without being byte for byte identical.
- Weak ETags prevent caching of byte range requests, while strong ETags allow them.
If your data model has a version counter, a strong ETag derived from it is cheap and precise.
Use 1: cache revalidation
When a cached response goes stale, the client asks whether its copy is still good:
GET /report.json
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
If the current ETag matches, the server answers 304 Not Modified with no body, and the client keeps using its stored copy. You save bandwidth and server work. Pair this with sensible freshness settings from the Cache-Control cheat sheet.
Use 2: avoiding mid-air collisions
Two people open the same record, both edit, and the second save silently wipes the first. ETags fix that:
PUT /pages/42
If-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
If the hash no longer matches, someone else changed the document and the server returns 412 Precondition Failed. The client can then fetch the new version and merge. This is optimistic concurrency without locks.
Implementation tips
- Generate the ETag from content or a version, not from a timestamp with coarse resolution that can repeat.
- Make the ETag consistent across all servers behind a load balancer, or revalidation will fail randomly.
- Return a clear error body on 412 so clients know to refetch.
- Require If-Match on write endpoints where lost updates would hurt, and return an error when it is missing.
- Do not put secrets or internal paths in ETag values. Treat them as visible to clients.
Security notes
ETags also reach shared caches, so the same privacy rules apply as for any cached response. A private page that is revalidated through a shared cache still needs the right directives. An attacker who can read ETags learns whether content changed, which is usually harmless but worth knowing for sensitive resources.
Where Safeguard fits
Safeguard does not run your DNS, certificates or network routes. It covers the code around them: dependency and SBOM scanning, reachability analysis and policy gates for the libraries your applications use. You can try a free scan at gold.safeguard.sh/scan.
Quick check
What does 412 mean?
Precondition Failed. The If-Match value did not match the current version, so the write was refused.
When should I use a weak ETag?
When byte identical output is not guaranteed and semantic equality is enough. Remember weak ETags prevent caching of byte range requests.
Sources
Last reviewed: 19 October 2026.