Also available in: Español · Português · Français · العربية
ETag checker
Compare two entity tags under the weak and strong comparison functions, and see what each conditional request header would do with them.
What an ETag is, and what the W/ means
An ETag is an opaque string a server attaches to a version of a resource. The client stores it, sends it back on the next request, and the server can answer with a 304 instead of the whole body if nothing has changed. The value has a small grammar: an optional W/ prefix, then the tag itself in mandatory double quotes.
The quotes are part of the value rather than decoration, and the permitted characters are narrower than people expect — the set is %x21 and %x23 to %x7E, which excludes both the double quote and, less obviously, the space. A backslash is allowed, though the specification advises against one because older recipients may try to unescape it.
The W/ prefix means the tag is a weak validator. The usual explanation is that a weak tag identifies a semantically equivalent version rather than a byte-identical one, which is true and makes it sound like a minor annotation about precision. It is not. It changes what the tag can be used for.
How to use it
- Put the server's ETag in the first box. Exactly as it appears in the response header, quotes and W/ prefix included. Anything malformed is explained rather than silently ignored.
- Put the tag being compared against it in the second. Usually that is what a client would send in If-None-Match or If-Match.
- Read both comparison results, then the header table. Where the two functions disagree, the answer depends entirely on which header is asking — and the table below spells out what each one would do.
Two comparison functions, and the one nobody mentions
HTTP does not have a comparison function for entity tags. It has two, and it requires different ones in different places. RFC 9110 section 13.1.2 says a recipient must use the weak comparison function for If-None-Match. Section 13.1.1 says an origin server must use the strong comparison function for If-Match.
Weak comparison ignores the W/ prefix entirely and compares the opaque tags. Strong comparison requires the tags to be equal and both to be strong. The consequence is the thing worth carrying away: a weak ETag never satisfies strong comparison, not even against an identical copy of itself. The specification prints this in its own table — W/"1" against W/"1" is a match under weak comparison and no match under strong.
So a weak ETag caches perfectly and cannot be written against. Every conditional PUT or PATCH that uses If-Match for optimistic concurrency fails, permanently, no matter what the client sends. There is no error explaining why; the precondition simply never passes. If your API returns 412 on every update and the ETag starts with W/, that is the reason.
This is not a rare configuration. Sampling the top 250 domains, 173 of which responded, only 20.2% send an ETag at all — and of those, 25.7% are weak, including wikipedia.org, github.com and apache.org. For a page being cached that is a sensible choice, since a weak tag survives compression and other transformations that change the bytes without changing the meaning. For an API endpoint people update, it removes a feature nobody realises they have lost.
If-Range is the third case and works differently again. The restriction there sits on the client: section 13.1.5 says a client must not generate an If-Range header containing a weak entity tag at all, so resuming a partial download needs a strong validator by construction rather than by comparison.
Honest limits, and how this was checked
This compares two tags you paste. It does not fetch anything, so it cannot tell you what your own server sends — a browser cannot read arbitrary response headers from another origin, and any tool that claims otherwise is proxying the request through a server. Your browser's developer tools will show you the header in one click, which is the right way to get it.
One thing this page deliberately does not claim: that servers commonly emit syntactically invalid ETags. That was the second half of the idea, and measuring killed it. Zero of the 35 real ETags sampled were malformed. Frameworks emit this header; almost nobody writes one by hand. The validator still explains malformed input, because a reader who has typed one deserves an answer, but it is not the interesting fact and the page does not pretend it is.
The comparison logic is checked against the specification's own four-row table, re-extracted from the RFC text on every test run rather than transcribed, so a copying error cannot survive. There are 513 assertions and 14 negative controls. Two of my own test fixtures turned out to encode assumptions rather than the grammar — I had a spaced tag down as valid and a backslashed one as invalid, and the grammar says the opposite on both counts.
Why is it free?
This is string comparison. It runs in your browser, there is no server to pay for, and there is nothing to sign up to.
Nothing you type is uploaded, stored or logged. ETags are opaque by design and sometimes encode more about a resource than their author intended, so it is worth stating that they stay in the tab.