devkult_
tools29converters34
home/headers/if-none-match

If-None-Match

request headercaching

Makes a request conditional: send the resource only if its current ETag isn't one of those listed.

If-None-Match carries the ETag or ETags a client already has. For GET and HEAD, the server answers 304 Not Modified if the current ETag matches, so the client can reuse its copy. With the value *, it means 'only if no version exists yet' — a way to create something without overwriting what's there.

Syntax

If-None-Match: "<etag>", "<etag>"…   or   If-None-Match: *

Defined in RFC 9110 §13.1.2 — If-None-Match.

Examples

If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

revalidate a cached copy

If-None-Match: *

on a PUT: create the resource only if it doesn't exist

Good to know

  • Browsers send it automatically when revalidating; you only set it by hand in API clients.
  • When a request carries both, If-None-Match takes precedence over If-Modified-Since.
  • With * on a write, an existing resource produces 412 Precondition Failed.

Who sets If-None-Match

Browsers send If-None-Match on their own when they revalidate a cached response that had an ETag. To test revalidation, copy the ETag from a response and send it back: curl -sI -H 'If-None-Match: "33a64df5"' https://example.com/app.css — a matching ETag returns 304.

Check it

In the browser, open DevTools → Network, pick a request and look under Request Headers. From the command line, curl's verbose mode prints every header it sends, prefixed with >:

curl -sv https://example.com/ -o /dev/null 2>&1 | grep '^>'

Frequently asked questions

Why does fetch() never show me a 304?

The browser revalidates its own cache and hands your code the cached 200. You only see the 304 if you add If-None-Match yourself.

Status codes it appears with
Related headers