What Is an ETag? A Plain-English Q&A
Common questions about HTTP ETags answered in plain language — fingerprints for cached content, If-None-Match, 304 Not Modified, strong vs weak validators, and how they fit with Cache-Control.

ETags show up in browser DevTools and CDN docs — but what *are* they? Here are common questions about HTTP ETags, answered in plain language. Literacy only: how caching validators work, not how to attack anything.
What is an ETag?
An ETag (entity tag) is a short fingerprint the server attaches to a specific version of a resource — a page, a JSON payload, an image, a stylesheet.
Think of it as a version sticker on a box. If the sticker is the same next time you check, the contents haven't changed. If the sticker is different, something inside is new.
Example response header:
HTTP/1.1 200 OK
ETag: "a1b2c3d4"
Cache-Control: max-age=3600
That "a1b2c3d4" value is opaque to the browser. You don't decode it. You just send it back later so the server can say "same" or "different."
What does ETag stand for?
ETag is short for entity tag.
It's defined in the HTTP caching model alongside other validators like Last-Modified. The important idea: validators let caches *check* freshness without always re-downloading the whole response.
Related: What Is Caching? — temporary copies and why they matter.
How do ETags help with caching?
Browsers and CDNs often keep a local copy of a response. Later, before using that copy (or when Cache-Control says they must revalidate), they ask the origin: "Is my copy still current?"
With an ETag, that question becomes:
You save bandwidth and latency when nothing changed. When something did change, you get a fresh copy.
What is If-None-Match?
If-None-Match is the request header that carries the ETag(s) the client already has.
GET /styles.css HTTP/1.1
Host: example.com
If-None-Match: "a1b2c3d4"
Reading it in plain English: "Give me this resource unless none of these tags still match — in which case just confirm it's unchanged."
If the server's current ETag is still "a1b2c3d4", it answers:
HTTP/1.1 304 Not Modified
ETag: "a1b2c3d4"
No response body. The cache keeps using what it already stored.
If the resource changed:
HTTP/1.1 200 OK
ETag: "e5f6g7h8"
Cache-Control: max-age=3600
/* new CSS bytes here */
Status codes like 304 sit alongside the everyday ones covered in HTTP Status Codes Decoded.
Strong vs weak ETags — what's the difference?
HTTP distinguishes two kinds of validators:
Strong ETag (default look):
ETag: "abc123"
A strong match means the byte-for-byte representation is identical. Safe for partial-content / range-style use cases where exact bytes matter.
Weak ETag (prefixed with W/):
ETag: W/"abc123"
A weak match means "semantically the same" — good enough for many caches even if the exact bytes differ slightly (for example, different compression or trivial formatting). Weak validators are for freshness checks, not for proving identical bytes.
Rule of thumb for literacy:
Most of the time you'll just see quoted strings in DevTools and treat them as opaque fingerprints.
How is an ETag different from Last-Modified?
Both are validators. They answer "has this changed?" in different ways.
| Validator | Based on | Example |
|-----------|----------|---------|
| ETag | Fingerprint of the representation | ETag: "v42.9f3a" |
| Last-Modified | Timestamp | Last-Modified: Mon, 28 Sep 2026 00:00:00 GMT |
Clients use:
ETags are often more precise: two edits in the same second can share a timestamp but get different ETags. Timestamps are simple and widely supported. Many servers send both.
How does ETag fit with Cache-Control?
They solve different jobs:
Important literacy traps (also covered in our Cache-Control posts):
Deep dives:
What happens when content changes?
When the origin updates the resource, it should issue a new ETag. Caches that still hold the old fingerprint will fail the match on the next conditional request and download the new representation.
Until that revalidation happens, a cache might still serve the old copy if max-age (or similar) says it's fresh. Validators don't magically push updates to every browser; they make *checks* efficient when a check is due.
CDNs add another layer of copies at the edge — see What Is a CDN Edge Cache? and Checklist: Do You Need a CDN?.
Do I need ETags if I already set max-age?
Not always. If a file is immutable and fingerprinted in the URL (like app.a1b2c3.js with a long max-age), browsers may never need to revalidate until the URL itself changes.
ETags help most when:
If every request must skip stored copies entirely, that's a Cache-Control / no-store decision — not something an ETag alone solves.
Quick reference
| Term | What it means |
|------|---------------|
| ETag | Fingerprint (entity tag) for a response version |
| If-None-Match | Request header sending stored ETag(s) for a check |
| 304 Not Modified | "Your copy is still good; no body attached" |
| Strong ETag | Byte-identical match ("abc") |
| Weak ETag | Semantic match (W/"abc") |
| Last-Modified | Time-based validator alternative |
| Cache-Control | Rules for storing and revalidating — ETag helps the revalidate step |
Want to go deeper?
What Is Caching? — browser, CDN, and application caches
Browser Cache: Hard Refresh Explained — when you intentionally bypass stored copies
no-cache vs no-store: What's the Difference? — revalidate vs don't store
5 Cache-Control Directives Worth Knowing — max-age, s-maxage, and friends
HTTP Status Codes Decoded — where 304 fits
*This post is part of Hacking Bits, where we explain how everyday technology works — one bit at a time.*
Related Posts
What Is an API in Plain English?
Common questions about APIs answered in plain language — what they do, how they work, why they matter, and how they power every app you use.
What Is DNS? A Plain-English Q&A
Common questions about DNS answered in plain language — recursive vs authoritative servers, TTL and caching, how nameservers work, and why they matter when you visit a URL.
5 Cache-Control Directives Worth Knowing
Understanding max-age, s-maxage, no-cache, no-store, and stale-while-revalidate — how HTTP caching headers control browser and CDN behavior.