Quick answer
HTTP 404 Not Found means the server received the request but could not find the requested resource. The endpoint, URL, or resource ID does not exist.
What HTTP 404 means
404 Not Found is the most familiar HTTP error. The server is reachable and understood the request, but there is nothing at the requested URL. In APIs this usually means a wrong endpoint path, a resource ID that does not exist, or an unregistered route.
Common causes
- A typo or wrong path in the request URL
- The resource ID does not exist (or was deleted)
- Wrong API version in the path (e.g.
/v1/vs/v2/) - The route is not registered on the server
- A reverse proxy or gateway is misrouting the request
Example JSON error response
{
"error": "Not Found",
"message": "User with id 999 was not found",
"status": 404
}
Raw HTTP response
HTTP/1.1 404 Not Found
Content-Type: application/json
How to troubleshoot HTTP 404
- ✓ Verify the endpoint URL is spelled correctly
- ✓ Check you are using the right API version in the path
- ✓ Confirm the resource ID actually exists
- ✓ Verify the route is registered on the server
- ✓ Check the reverse proxy / gateway configuration is routing correctly
How to handle a 404 in client code
A 404 is not a network failure — the request succeeded and the server answered. So fetch() does not throw on a 404; you must check the status yourself. This is the single most common 404-handling bug in JavaScript:
// fetch does NOT reject on 404 — check response.ok
const res = await fetch(`/api/users/${id}`);
if (res.status === 404) {
// handle "not found" specifically
return null;
}
if (!res.ok) throw new Error(`Request failed: ${res.status}`);
const user = await res.json();
With axios it is the opposite — axios does reject on 4xx/5xx, so catch the error and inspect error.response.status:
try {
const { data } = await axios.get(`/api/users/${id}`);
return data;
} catch (err) {
if (err.response && err.response.status === 404) return null;
throw err;
}
Returning a 404 in different frameworks
If you are building the API, here is how to return a proper 404 with a JSON body in common frameworks:
| Framework | How to return 404 |
|---|---|
| Express (Node.js) | res.status(404).json({ error: "Not Found" }) |
| Flask (Python) | return jsonify(error="Not Found"), 404 |
| FastAPI (Python) | raise HTTPException(status_code=404, detail="Not Found") |
| Spring Boot (Java) | ResponseEntity.status(HttpStatus.NOT_FOUND).body(...) |
| ASP.NET Core | return NotFound(new { error = "Not Found" }); |
When should an API return 404?
404 is the right status when a specific resource does not exist — for example GET /users/999 where user 999 was never created or was deleted. But two common cases are not 404s:
- An empty collection is not a 404.
GET /users?role=adminwith no matching users should return200 OKwith an empty array[]— the collection endpoint exists and succeeded; it simply has no items. - A deleted-on-purpose resource can be 410. If a resource was intentionally and permanently removed and you want to signal that explicitly,
410 Goneis more precise than 404.
Returning a clear JSON error body with the 404 (rather than an empty response or an HTML error page) makes the failure far easier for API clients to handle — see why an API returns HTML instead of JSON.
Frequently Asked Questions
What causes a 404 in an API?
A 404 means the requested resource does not exist at that URL. Common causes are a wrong or misspelled endpoint path, a resource ID that does not exist, the wrong API version, or a route that is not registered on the server.
How do I fix a 404 Not Found?
Verify the URL is correct, check the API version, confirm the resource ID exists, ensure the route is registered, and check any reverse proxy or gateway configuration. Working through these in order resolves almost all 404s.
What is the difference between 404 and 410?
404 Not Found means the resource is not there (it may never have existed, or its status is unknown). 410 Gone means the resource existed but was intentionally and permanently removed. Use 410 when you want to signal a deliberate, permanent deletion.
Should an empty list return 404 or 200?
Return 200 OK with an empty array. A collection endpoint like /users?role=admin that matches no records still succeeded — the collection exists, it just has no items. Reserve 404 for a specific resource that does not exist, like /users/999.
Why doesn't fetch() throw an error on a 404?
The JavaScript fetch() API only rejects on network failures, not on HTTP error statuses. A 404 is a successful HTTP exchange — the server responded — so fetch resolves normally. You must check response.ok or response.status yourself. (axios is different: it rejects on 4xx/5xx, so you check error.response.status in a catch block.)
Working with a JSON API response?
Format and inspect any response in your browser — nothing is uploaded.