DevToolsmith

HTTP 304 Not Modified

HTTP 304 Not Modified tells the client its cached copy is still valid, so no body is sent. The client must take further action, usually following a redirect.

Class
3xx Redirection
Standard
RFC 9110
Cacheable by default
No
Safe to retry
Not applicable: this isn’t an error
Go constant
http.StatusNotModified

What HTTP 304 means

When a client revalidates a cached response with If-None-Match (ETag) or If-Modified-Since, the server returns 304 with no body if nothing changed. The client keeps using its cached copy, saving bandwidth. Seeing many 304s in DevTools is a good sign that caching works.

Using 304 correctly

  • If you always get 200 instead of 304, check that the server sends a stable ETag or Last-Modified. Some load balancers generate different ETags on each server.

Retrying

Not applicable: this isn’t an error.

Example response

HTTP/1.1 304 Not Modified
Date: Wed, 21 Oct 2026 10:30:00 GMT
ETag: "33a64df5"
Cache-Control: max-age=0, must-revalidate

How to return 304

Node.js (Express)
res.status(304).end();
Python (FastAPI)
from fastapi import Response

return Response(status_code=304)
Go (net/http)
w.WriteHeader(http.StatusNotModified)

Related status codes

Other 3xx status codes

300 Multiple Choices · 301 Moved Permanently · 302 Found · 303 See Other · 307 Temporary Redirect · 308 Permanent Redirect

See the full list of HTTP status codes.

Sources

Spotted a mistake? Email hello@devtoolsmith.com and we’ll fix it.

Frequently asked questions

What does HTTP 304 Not Modified mean?

HTTP 304 Not Modified tells the client its cached copy is still valid, so no body is sent. When a client revalidates a cached response with If-None-Match (ETag) or If-Modified-Since, the server returns 304 with no body if nothing changed. The client keeps using its cached copy, saving bandwidth. Seeing many 304s in DevTools is a good sign that caching works.