Contact

What is 304 Not Modified?

Definition

304 Not Modified is the HTTP status code a server returns to a conditional GET or HEAD request when the client's stored copy is still valid. The client sends back the earlier ETag in If-None-Match or a date in If-Modified-Since; if nothing has changed, the server replies with a body-less 304 and the client reuses its cached copy.

Also known as: ETag, If-None-Match, conditional request, conditional GET, HTTP 304

Sequence where the browser sends a conditional ETag request, the server answers 304 without a body and the cached copy is reused

A conditional request, step by step

A 304 is the end of a short negotiation. On the first request the server sends the content with 200 and adds validators that identify the current version:

HTTP/1.1 200 OK
ETag: "a3f9c1"
Last-Modified: Tue, 15 Sep 2026 08:12:00 GMT
Cache-Control: no-cache

When the client asks for the same URL again, it sends those values back. The server compares them and, if nothing changed, answers without a body:

GET /products/ HTTP/1.1
If-None-Match: "a3f9c1"
If-Modified-Since: Tue, 15 Sep 2026 08:12:00 GMT

HTTP/1.1 304 Not Modified
ETag: "a3f9c1"
Cache-Control: no-cache

Under RFC 9110 a 304 cannot contain a body and must include the headers a 200 would have carried, such as ETag, Cache-Control, Date and Vary; the client uses them to refresh its cached copy. How Cache-Control decides when to ask again is covered under Cache-Control.

ETag or Last-Modified?

An ETag is an opaque identifier the server assigns to one version of the content, typically a hash or a version number. A weak ETag, prefixed with W/, says the content is semantically the same but may not be byte-identical. Last-Modified is a date with one-second resolution: it cannot tell apart two edits in the same second, and if the date format is wrong, clients cannot parse it.

When both are sent, the ETag wins: RFC 9110 says that if If-None-Match is present, If-Modified-Since is not evaluated at all. Google also recommends ETag for its own crawlers because it has no date-formatting pitfalls, while noting there is no harm in sending both for the benefit of other clients and CMSs.

Googlebot and 304

Google's crawling infrastructure supports both ETag/If-None-Match and Last-Modified/If-Modified-Since. Googlebot uses them when recrawling URLs for Google Search, though not every Google crawler makes use of caching. According to Google, a 304 tells the next system that the content is the same as at the last crawl; the indexing pipeline may recalculate signals for the URL, but otherwise the code has no effect on indexing. The payoff is efficiency: no body is transferred for unchanged pages, server load drops and, on large sites, more crawl budget is left for pages that did change.

Mistakes that stop 304s from ever happening

  • An ETag that changes every time: if each response embeds a fresh CSRF token, nonce or timestamp, the content hash changes on every request and a 304 never occurs.
  • Server-specific ETags: an ETag derived from something machine-specific, such as a file's inode number, differs between the servers behind a load balancer even for the same file.
  • Compression layers: a layer that compresses responses may turn a strong ETag into a weak one (W/). That is expected, but some layers strip the ETag entirely.
  • A false 304: returning the old validator after the content changed is the most dangerous case; browsers and Googlebot stay on the stale copy.

Checking takes two commands: get the ETag with curl -sI URL, then send it back with curl -sI -H 'If-None-Match: "a3f9c1"' URL and confirm the response is 304.

Related terms

← Back to the glossary