HTTP 304 Not Modified – Free, Online, Private
304 Not Modified means the client's cached copy is still fresh.
What HTTP 304 means
304 is the answer to a conditional GET. The client sent If-None-Match or If-Modified-Since, and the representation has not changed. The server sends no body. The client keeps the copy it already has. A 304 without a prior cache is useless, because there is nothing to keep. Validators have to have been on the original 200.
304 Not Modified belongs to the 3xx redirection class. Clients that only look at the class will group it with its neighbors. Clients that care about the exact code should use the narrower rule on this page, because the class is only the first digit.
When you see HTTP 304
When you see HTTP 304 Not Modified, stop on that exact status line. 304 Not Modified means the client's cached copy is still fresh. The trace that usually produces it: A browser revalidated a cached stylesheet and the file had not changed. The 3xx redirection class only tells you the first digit. A neighbor in that class is a different fault, and the fix on this page does not transfer to it.
Return 304 when the condition says the client's version matches. Copy the validators you still stand behind, such as ETag, onto the 304. Do not include a body. Do not return 304 to a client that did not send a precondition. That client would have nothing to display.
How to fix HTTP 304
To fix HTTP 304, change the condition that made the server choose Not Modified. On 304, keep the stored representation and update its freshness from the new headers. Do not parse a body. If you have no stored representation, ignore the 304 and GET without the precondition. There is nothing to retry. The resource has not changed. A retry without the validator returns the full 200. If the log line is a different code, leave this page. The mix-up people make with 304 is this one: 204 is an empty success with no stored copy implied. 304 is an empty success that points at a stored copy. 200 is the full new representation.
- ETag comparison failed because the server put quotes on one side only.
- A client treated 304 as an error and cleared the cached copy it should have kept.
- A cache returned 304 to a client that had never stored the 200.
An access log that only stores 304 is not enough to tell these apart. Keep the method, the path, and a request id. Do not keep the Authorization header or a request body that might be a token. The status explains the outcome. It is not a place to echo secrets back to the client either.
Example response
HTTP 304 Not ModifiedHTTP/1.1 304 Not Modified
ETag: "abc"
There is no body. The ETag matches the one the client sent. The client continues to use its stored response, including the stored Content-Type. If you changed the body and forgot to change the ETag, clients will keep the old bytes and you will not understand why the deploy is invisible.
What the client should do
On 304, keep the stored representation and update its freshness from the new headers. Do not parse a body. If you have no stored representation, ignore the 304 and GET without the precondition.
304 is how caches revalidate. The stored object remains the cache entry. A 304 does not replace that object with an empty one.
There is nothing to retry. The resource has not changed. A retry without the validator returns the full 200.
Codes people confuse with HTTP 304
204 is an empty success with no stored copy implied. 304 is an empty success that points at a stored copy. 200 is the full new representation.
Frequently asked questions
Does 304 include the file?
No. The client already has it. The status says it is still valid.
Which request headers cause 304?
If-None-Match with an ETag, or If-Modified-Since with a date. Both compare against the current representation.
What if the ETag changed?
The server returns 200 with the new body and the new ETag.
Can 304 be the first response?
It should not be. A client with no cached copy cannot use it.
What should I do first when I see HTTP 304?
Read the status as 304 Not Modified specifically. 304 Not Modified means the client's cached copy is still fresh. Then check the cause that matches the request you sent, starting with: A browser revalidated a cached stylesheet and the file had not changed.