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
- 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.
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.
How to fix it
As the client
- 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.
As the server
- 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
GET /assets/app.css HTTP/1.1 Host: www.example.com If-None-Match: "9f2c31" 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.