# 204 No Content

> The request succeeded with no response body. Learn when to use 204 No Content for successful operations that don't return data.

Source: https://howhttpworks.com/status-codes/204
Last reviewed: 2026-10-04

> **TL;DR:** 204 No Content means the request succeeded and there is deliberately no body. It is the usual answer to DELETE, to PUT/PATCH when you do not echo the resource, and to CORS preflights. It cannot carry content, so a 204 with a body is a bug.

## What it means

```http
DELETE /api/items/42 HTTP/1.1
Host: api.example.com

HTTP/1.1 204 No Content
Date: Sun, 04 Oct 2026 12:00:00 GMT
```

RFC 9110 section 15.3.5: a 204 ends after the header section. Servers must not send `Content-Length` or `Transfer-Encoding` on a 204 (RFC 9110 section 8.6 and RFC 9112 section 6.3). Clients with a page open stay on it; a browser form submission that returns 204 leaves the user on the current page without navigating, which can be a useful way to handle "save" actions that do not need a new view.

## When to use it

- DELETE that succeeded.
- PUT or PATCH when the client already has the new state (add an `ETag` so it can track the new version).
- CORS preflight (OPTIONS) responses; most CORS middleware sends 204, and browsers accept any 2xx.
- Beacons and analytics endpoints (`navigator.sendBeacon` ignores the response, so 204 saves bytes).
- Not for GET of an existing resource that happens to be empty; return 200 with `[]` or `{}`, since clients treat a missing body as a parsing case.

## Common bugs

- **`response.json()` throws on 204.** `fetch(...).then(r => r.json())` fails with `SyntaxError: Unexpected end of JSON input`. Check `r.status === 204` before parsing. Axios returns `data: ''`.
- **Body written anyway.** Node's `http` module and Express drop the body on a 204, so the client never sees it. On a raw socket, a stray body would be parsed as the start of the next response.
- **204 in place of 404.** A 204 on a GET for a missing item hides the error. Use 404.

## Implementation

### Express

```javascript
app.delete('/api/items/:id', async (req, res) => {
  await db.items.delete(req.params.id)
  res.sendStatus(204)
})
```

### Flask

```python
@app.delete("/api/items/<int:item_id>")
def delete_item(item_id):
    db.delete(item_id)
    return "", 204
```

### Go

```go
w.WriteHeader(http.StatusNoContent)
```

### nginx

```nginx
location = /beacon {
    return 204;
}
```

## Reproduce with curl

```bash
curl -si -X DELETE https://api.example.com/api/items/42
# HTTP/2 204
# (no body, no content-length)
```

## 204 vs 200 vs 201 vs 205

| Code | Body | Meaning                                         |
| ---- | ---- | ----------------------------------------------- |
| 200  | Yes  | Success with a result                           |
| 201  | Usual | New resource created                           |
| 204  | Never | Success, nothing to show                       |
| 205  | Never | Success, tell the UI to reset the form or view |

## Related

- [200 OK](https://howhttpworks.com/status-codes/200)
- [201 Created](https://howhttpworks.com/status-codes/201)
- [DELETE method](https://howhttpworks.com/methods/delete)
- [OPTIONS method](https://howhttpworks.com/methods/options)

See also the comparison [200 vs 201 vs 204](https://howhttpworks.com/compare/200-vs-201-vs-204): choosing the right success code for create, read, update and delete.
