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.

See also

Last updated: August 2, 2023