Skip to content

304 Not Modified

The cached copy the client already holds is still current, so the server sends no body.

Status

HTTP/1.1 304 Not Modified

Details

  • Category: 3xx
  • Status: Standard. Registered with IANA and defined by a current standards-track RFC.
  • Specification: RFC 9110 §15.4.5, RFC 9111 §4.3.4: Caching behaviour on revalidation
  • Cacheable: Cacheable by default
  • Response body: Must not be sent
  • Retry: Not applicable

304 answers a conditional request. The client sends If-None-Match with an ETag or If-Modified-Since with a date, and if nothing changed the server replies 304 with headers only. The client then serves its stored copy. This is the single largest bandwidth saving mechanism in everyday HTTP.

The response must not include a body, and it must carry the validators and cache headers that would have accompanied a 200 so the client can update its freshness bookkeeping.

Note: A 304 carries no body. The client is expected to serve the copy it already holds, so the response must repeat the validators and cache headers that came with the original 200.

Headers

  • ETag: Should match the validator that made the request conditional.
  • Cache-Control: Refreshes the stored freshness lifetime of the cached representation.
  • Vary: Must be consistent with the original 200 or caches may serve the wrong variant.

Common causes

  • A browser revalidated an expired cache entry and nothing had changed.
  • A crawler sent If-Modified-Since and the page was untouched since the last visit.

Usage notes

For clients

  • Serve the stored copy. Do not try to parse the empty body.
  • If you want the full payload for a scrape, omit If-None-Match and If-Modified-Since, or send Cache-Control: no-cache.

For servers

  • Emit stable ETags. Regenerating a different ETag for identical content defeats revalidation entirely.
  • Include the same Vary header as on the 200, or shared caches will mismatch variants.

Examples

Revalidating a cached asset

A revalidation request carrying the ETag the client already holds:

HTTP request

GET /assets/app.css HTTP/1.1
Host: www.example.com
If-None-Match: "9f2c31"

Nothing changed, so the server sends headers only and the client serves its stored copy:

HTTP response

HTTP/1.1 304 Not Modified
ETag: "9f2c31"
Cache-Control: public, max-age=86400

Notes for proxy users

Crawlers that store validators and send conditional requests get 304s instead of full pages, which cuts bandwidth and lowers the request footprint on the target site. That is worth doing even on unmetered proxy plans because it reduces the load pattern that triggers rate limiting.

Specifications

See also