# HTTP 304 Not Modified — Status Code Meaning & Examples

> The cached copy is still valid; use it instead of downloading the resource again.

304 is the payoff of conditional requests. When a browser holds a cached response with an `ETag` or `Last-Modified`, it revalidates with `If-None-Match` or `If-Modified-Since`. If nothing changed, the server answers 304 with no body and the browser reuses its copy — a few hundred bytes instead of the full file.

- Class: 3xx Redirection
- Retry: Not applicable
- Cacheable by default: no
- Defined in: [RFC 9110 §15.4.5 — 304 Not Modified](https://www.rfc-editor.org/rfc/rfc9110.html#section-15.4.5)

## Example response

```http
HTTP/1.1 304 Not Modified
```

## When you'll see it

- Revalidation of a cached page, image or API response.
- Reloading a page, which makes the browser revalidate its cache.

## How to use it well

1. Send `ETag` or `Last-Modified` on cacheable responses so clients can revalidate.
2. Never include a body in a 304.
3. Stale content after a deploy means the server is wrongly answering 304, usually because the ETag doesn't change with the content. Fingerprint asset URLs (`app.3f2a1c.js`) and cache them as immutable instead.

## FAQ

### Is a 304 an error?

No — it's the best case for a cached resource. In DevTools it shows up as a request that transferred only headers.

### Why does fetch() show 200 when the server sent 304?

The browser handles revalidation itself and hands your code the cached 200 response. You only see a 304 if you send the conditional headers yourself.

## Related status codes

- [200 OK](https://www.devkult.com/http/200.md)
- [412 Precondition Failed](https://www.devkult.com/http/412.md)
- [206 Partial Content](https://www.devkult.com/http/206.md)

Open the interactive page: https://www.devkult.com/http/304