Quick Answer

HTTP status codes are grouped by their first digit: 2xx means success, 3xx means redirection, 4xx means the client sent something wrong, and 5xx means the server failed. The distinction that matters most is 4xx versus 5xx — a 4xx says fix your request, a 5xx says the request was fine but the server broke. The most-confused pairs are 401 (not authenticated) versus 403 (authenticated but not allowed), and 301 (permanent, cached aggressively) versus 302 (temporary).

The Five Families

You do not need to memorise the full list. The first digit carries most of the meaning.

  • 1xx — informational. Rare in application code. 101 Switching Protocols appears when a connection upgrades to WebSockets.
  • 2xx — success. The request was received, understood and accepted.
  • 3xx — redirection. The resource is somewhere else; follow the Location header.
  • 4xx — client error. Something about the request was wrong. Retrying it unchanged will fail again.
  • 5xx — server error. The request was reasonable but the server could not fulfil it. Retrying may well succeed.

That 4xx versus 5xx split is the one to internalise. It answers "whose fault is this?", which decides whether you debug your client or your server — and it also decides whether a retry is sensible. Retrying a 400 is pointless; retrying a 503 with backoff is exactly right.

It matters for SEO too. Google treats a 404 as "this is gone, drop it" and a 503 as "come back later, keep the page". Returning the wrong one during maintenance can quietly remove pages from the index.

Success Codes Worth Distinguishing

200 OK — the general success. The response body carries the result.

201 Created — a new resource was created. Correct for a POST that adds a record, and it should include a Location header pointing to the new thing. Returning a bare 200 works but tells the client less.

204 No Content — succeeded, and there is deliberately nothing to send back. The right answer for a DELETE, or a PUT where the client already knows the result. A 204 must not have a body; some clients will error if you send one anyway.

202 Accepted — the request is valid and queued, but not finished. The honest code for asynchronous work such as "generate this report", where pretending it completed with a 200 would be a lie.

A common API mistake is returning 200 OK with {"error": "not found"} in the body. Monitoring, caches and client libraries all read the status code, so an error dressed as a success is invisible to every one of them.

Redirects: 301 vs 302 Matters More Than You Think

301 Moved Permanently tells clients and search engines the resource has moved for good. Browsers cache it aggressively — often indefinitely — and search engines transfer ranking signals to the new URL.

That caching is the danger. If you issue a 301 by mistake, visitors who received it may keep being redirected even after you fix the server, because their browser never asks again. Clearing that requires the user to clear their cache. Test redirects with a 302 first, and promote to 301 once you are certain.

302 Found is temporary. Nothing is cached long-term and search engines keep the original URL indexed. Correct for "log in first, we will send you back" flows.

307 and 308 are the strict versions. The older codes allowed clients to change a POST into a GET when following the redirect, which surprised people; 307 (temporary) and 308 (permanent) guarantee the method and body are preserved. Prefer these for APIs.

304 Not Modified is the caching workhorse. The client asks "has this changed since the version I hold?" and the server replies 304 with no body. It looks like an error in the network tab but is the fastest possible successful response.

Client Errors, Including the Pair Everyone Confuses

400 Bad Request — the request itself is malformed: broken JSON, a missing required field, a wrong data type. The server could not even interpret it.

401 Unauthorizedyou are not authenticated. No credentials, or invalid ones. The name is historically wrong; read it as "unauthenticated". The correct response to "who are you?"

403 Forbiddenyou are authenticated, and you still may not do this. The server knows who you are and is refusing anyway. The correct response to "you are not allowed".

The rule: 401 means log in; 403 means logging in will not help. A normal user hitting an admin endpoint should get 403, not 401 — sending 401 tells them to authenticate, which they already have.

404 Not Found — no such resource. Sometimes used deliberately in place of 403 to avoid revealing that something exists at all.

405 Method Not Allowed — the URL exists but not for that verb, such as POSTing to a read-only endpoint.

409 Conflict — the request clashes with current state, like registering an email that already exists.

422 Unprocessable Entity — the syntax is valid but the content fails validation. Well-formed JSON with an email field containing "banana". Many APIs use 400 for both; splitting them makes error handling clearer.

429 Too Many Requests — rate limited. Should include a Retry-After header, and a well-behaved client honours it rather than hammering.

Server Errors and What They Point To

500 Internal Server Error — the catch-all. Something threw an exception and nothing handled it. This means "look at your server logs", and it should never leak a stack trace to the client, since that hands an attacker your framework versions and file paths.

502 Bad Gateway — a proxy or load balancer got an invalid response from the server behind it. Usually your application crashed or was never listening; nginx returns 502 when it cannot get a sensible answer from the app.

503 Service Unavailable — temporarily unable to handle the request, through overload or maintenance. This is the correct code for planned downtime, and it should include Retry-After. Search engines treat it as "try again later" and keep the page indexed, which a 404 would not.

504 Gateway Timeout — a proxy waited for the upstream server and gave up. The application is alive but too slow, so look for slow queries or a blocked event loop rather than a crash.

The 502 versus 504 distinction saves real debugging time: 502 usually means dead, 504 usually means slow.

Frequently Asked Questions

What is the difference between 401 and 403? 401 means you have not proved who you are — no credentials or invalid ones — so authenticating could fix it. 403 means the server knows who you are and is refusing anyway, so logging in again will not help. A logged-in user hitting an admin route should receive 403.
Should I use 301 or 302 for a redirect? Use 302 while testing, because browsers cache 301 responses aggressively and a mistaken 301 can persist in a user's browser even after you fix it. Use 301 once the move is permanent, since it also passes ranking signals to the new URL.
What does a 502 error mean? A proxy or load balancer received an invalid response from the server behind it — commonly the application crashed or is not listening on the expected port. Distinct from 504, which means the upstream was reachable but too slow to answer in time.
Is it okay to return 200 with an error in the body? No. Status codes are read by caches, monitoring, retry logic and client libraries, none of which inspect your body. An error returned as 200 is invisible to all of them, so failures go unnoticed and misbehaving requests get cached as successful.
Which status code should I use for validation errors? 422 Unprocessable Entity when the request is syntactically valid but fails business validation, and 400 Bad Request when the request itself is malformed, such as broken JSON. Using 400 for both is common and acceptable, but separating them makes client handling simpler.