304 Not Modified
This is an educational reference page about HTTP 304 Not Modified. The page itself is served as 200 OK so it can be indexed as HTTP documentation.
Indicates that the resource has not been modified since the version specified by the request headers If-Modified-Since or If-None-Match. In such case, there is no need to retransmit the resource since the client still has a previously-downloaded copy.
Specification
Registered in the IANA HTTP Status Code Registry as Not Modified. Defined in RFC 9110, Section 15.4.5.
What it means
HTTP 304 Not Modified means the cached copy is still valid, so the server does not need to send the response body again.
Common causes
- A browser or CDN sends If-None-Match with an ETag from a previous response.
- A client sends If-Modified-Since with a Last-Modified timestamp.
- Static assets, API responses, or pages are being revalidated instead of downloaded again.
How to fix it
- Return 304 only when the cached representation still matches the current resource.
- Send strong or weak ETag values consistently for cacheable responses.
- Use Last-Modified when timestamp-based validation is accurate enough.
- Keep Cache-Control, ETag, Vary, and Last-Modified behavior consistent across the CDN and origin.
- Return 200 with a full body when the resource changed or validators do not match.
Example response
GET /app.css HTTP/1.1
If-None-Match: "abc123"
HTTP/1.1 304 Not Modified
ETag: "abc123"
Cache-Control: public, max-age=3600
Developer notes
304 is a successful cache validation response. It saves bandwidth and speeds up repeat visits, but incorrect validators can make clients keep stale content.
Questions
What does HTTP 304 mean?
HTTP 304 means the client can reuse its cached copy because the resource has not changed.
Is 304 an error?
No. 304 Not Modified is not an error. It is a normal cache validation response.
What headers cause a 304 response?
If-None-Match and If-Modified-Since commonly trigger 304 when they match the server's current ETag or Last-Modified value.
Should a 304 response include a body?
No. A 304 response does not include the full response body; the client uses its cached body instead.
Header and content rules
What RFC 9110 says about a 304 response, quoted from the RFC.
- MUST (server; Content-Location, Date, ETag, Vary, Cache-Control, Expires): Send those fields. When: Each field that a 200 response to the same request would have sent. Table row
The server generating a 304 response MUST generate any of the following header fields that would have been sent in a 200 (OK) response to the same request: * Content-Location, Date, ETag, and Vary * Cache-Control and Expires (see [CACHING]) RFC 9110 §15.4.5
- SHOULD NOT (sender; representation metadata): Do not send other representation metadata. When: Unless the metadata guides cache updates, such as Last-Modified when there is no ETag. Table row
Since the goal of a 304 response is to minimize information transfer when the recipient already has one or more cached representations, a sender SHOULD NOT generate representation metadata other than the above listed fields unless said metadata exists for the purpose of guiding cache updates (e.g., Last-Modified might be useful if the response does not have an ETag field). RFC 9110 §15.4.5
- No keyword (sender; content): A 304 response ends at its header section. It has no content and no trailers. Table row
A 304 response is terminated by the end of the header section; it cannot contain content or trailers. RFC 9110 §15.4.5
- SHOULD (proxy; forwarding): Forward the 304 to that client. When: The conditional request came from an outbound client, such as a user agent with its own cache. Table row
If the conditional request originated with an outbound client, such as a user agent with its own cache sending a conditional GET to a shared proxy, then the proxy SHOULD forward the 304 response to that client. RFC 9110 §15.4.5
The same rules are in the response obligations table and its JSON.