Developer FIELD NOTES · 4 MIN READ
HTTP Status Codes Explained: What 200, 301, 404 and 500 Really Mean
The five HTTP response families, what 200, 301, 404 and 500 really mean, 401 vs 403, redirect choices, and the 200-with-error anti-pattern.
Every HTTP response begins with three digits, and those digits are the fastest summary of what happened: the browser, the API client, the monitoring system, and the search engine all read the status code before anything else. The five families are simple — the nuance is in which code you pick among cousins like 301 and 302, or 401 and 403.
The first digit is the family
1xx informational request received, keep going
2xx success it worked
3xx redirection go look over there
4xx client error the request was the problem
5xx server error the server was the problem
The first digit narrows the blame instantly: 4xx means fix the request, 5xx means fix the server (or wait). A full response line carries the code plus a reason phrase — HTTP/1.1 404 Not Found — but the phrase is decoration; machines act on the number, and well-known codes carry defined side effects like Location or Retry-After headers.
2xx: the success family
200 OK is the default success and covers most GETs and POSTs. 201 Created says "the request made something" and should come with a Location header pointing at the new resource — a well-behaved API returns 201 when your POST creates a record. 204 No Content means success with nothing to say: the body is empty, which fits DELETE operations and PUTs that save without echoing data. Clients must handle it specially — there is no body to parse. 202 Accepted means "received, not finished" — the code behind every queue-based API that starts work now and reports later.
3xx: redirects — permanent, temporary, and cached
HTTP/1.1 301 Moved Permanently
Location: https://example.com/new-path
301 says the resource moved for good. Browsers may cache it aggressively, search engines transfer the old URL's ranking to the new one — which is why site migrations use 301. 302 says "moved for now": engines keep indexing the original, and browsers should not cache long. The subtle pair is 307 and 308: they mirror 302 and 301 but guarantee the method survives the redirect — a POST stays a POST instead of being silently downgraded to GET, which matters whenever a form or API call gets redirected mid-flight. Finally, 304 Not Modified is the caching win: the client asked "is my cached copy still good?" and the server answered "yes" with zero bytes of body.
4xx: the request's fault
400 Bad Request covers malformed input — broken JSON, bad syntax, values that cannot be interpreted. 401 Unauthorized really means "unauthenticated": the server does not know who you are, and it says so with a WWW-Authenticate header telling the client how to authenticate. The classic Basic scheme sends credentials as a Base64 string in an Authorization header — encoding, not encryption, as How Base64 Encoding Works explains; it must ride on HTTPS. 403 Forbidden is the opposite verdict: identity known, access denied — and many servers deliberately return 403 even for things that do not exist, so probing clients cannot distinguish "missing" from "none of your business".
404 Not Found is the web's most famous code: the URL is valid-shaped but nothing lives there. Its lesser cousin 410 Gone means "it existed and was deliberately removed" — useful to tell search engines to stop crawling forever. 429 Too Many Requests is the rate limiter's answer, ideally with a Retry-After header saying when to come back; clients that ignore 429 are the ones that get IPs blocked.
5xx: the server's fault
500 Internal Server Error is the generic "something threw" — an unhandled exception caught by the web server's safety net. It is honest but useless for debugging without server logs, which is why disciplined codebases return more specific codes where they can. 502 Bad Gateway and 504 Gateway Timeout are proxy diagnoses: the server you reached sits in front of another server, and that upstream either returned garbage (502) or did not answer in time (504). 503 Service Unavailable announces deliberate overload or maintenance, often with Retry-After. Reading these as a user: 500 is the site's bug, 502/504 are usually infrastructure between you and the app, 503 is often planned.
The anti-pattern: 200 with an error inside
The worst habit in API design is returning HTTP 200 with an error payload inside — {"success": false, "error": "..."}. It happens when frameworks make exceptions easy and status codes feel like work, and it silently breaks the entire ecosystem built on top of the protocol: monitoring tools alert on 5xx rates, browsers' fetch rejects on 4xx/5xx, CDNs cache and retry by status class, and search engines react to specific codes. A client that must parse a successful response to discover failure now needs custom logic that no generic tool will run. The status line is the contract; the body is details. Spend the three digits.
Try it yourself
Look up any code — the famous ones and the obscure 4xx ranges — in the HTTP Status Code Lookup for meaning, category, and typical causes. Since redirects and status headers are all about URLs, dissect one into scheme, host, path, and query with the URL Parser, and when you build query strings — the part most often mangled by special characters — encode them correctly with the URL Encoder & Decoder.