304 Not Modified
HTTP response status code 304 Not Modified is returned by the server to indicate a successful HTTP request, yet there is no need to send the data associated with the relevant resource. Essentially, it is the same as a 200 OK status code with a specific header included. There is no message body for this response code.
Usage
The 304 Not Modified status code is sent by the server in a limited number of cases. It implies that the HTTP request is safe, such as a GET or HEAD HTTP request, and the server concludes that the resource has not been changed since it was last stored in the client’s cache. This is intended as a bandwidth-conserving function, as the server does not have to retransmit data that the client already has.
The server must generate one of the following HTTP headers in response to what was sent by the client:
Because the goal of the 304 Not Modified HTTP response is to minimize bandwidth, the server will not generate redundant or unused HTTP headers. Therefore, none of the above fields will be returned that were not included in the HTTP request, unless it is otherwise helpful for the cache-update process.
If the HTTP request was conditional, such as a conditional GET, and it included an appropriate directive, then the server may return 304 Not Modified status code. The relevant directives are If-None-Match and If-Modified-Since, and rely on a header such as ETag to evaluate the necessity to transmit the resource.
Example
In the example, the client requests a resource that is stored in the cache after it is received. The ETag transmitted by the server uniquely identifies the version sent by the server. Sometime later, a second HTTP request is made by the client to see if anything has changed. The client transmits the ETag that it had originally received, and the server recognizes that nothing has changed since the last transmission. Consequently, it returns the 304 Not Modified status code. Finally, the client makes a third HTTP request and by that time, a new version of the document is available. As such, a new copy is transmitted by the server with the newest ETag.
Note
Each time the server updates a resource, it generates a new ETag and maintains a history of the previous ones. This server-side version history, in conjunction with the client’s local cache, together are what make this bandwidth-conserving option possible. Alternatively, the server might return a Last-Modified date, and the client can use that instead of the ETag in If-Modified-Since, negating the need for the server to maintain a history of ETag values.
Initial request
GET /news.html HTTP/1.1
Host: www.example.re
Initial response
HTTP/1.1 200 OK
Etag: “1234 … 000"
Content-Type: text/html
Content-Length: 1250
<message body contains requested resource>
Second request
GET /news.html HTTP/1.1
Host: www.example.re
If-None-Match: “1234 … 000"
Second response
HTTP/1.1 304 Not Modified
Etag: “1234 … 000"
Third request
GET /news.html HTTP/1.1
Host: www.example.re
If-None-Match: “1234 … 000"
Third response
HTTP/1.1 200 OK
Etag: “1234 … 001"
Content-Type: text/html
Content-Length: 1600
<message body contains requested resource>
Code references
.NET
HttpStatusCode.NotModified
Rust
http::StatusCode::NOT_MODIFIED
Rails
:not_modified
Go
http.StatusNotModified
Symfony
Response::HTTP_NOT_MODIFIED
Python3.5+
http.HTTPStatus.NOT_MODIFIED
Java
java.net.HttpURLConnection.HTTP_NOT_MODIFIED
Apache HttpComponents Core
org.apache.hc.core5.http.HttpStatus.SC_NOT_MODIFIED
Angular
@angular/common/http/HttpStatusCode.NotModified
Takeaway
The 304 Not Modified status code indicates that the HTTP request was successful but because the client has the most recent version already cached locally, the server opts to conserve bandwidth and respond to say that there is no reason to retransmit the requested resource.