🚦

HTTP Status Codes

HTTP status codes are three-digit numbers that the server sends in the response to each HTTP request. They indicate whether the request was successful, requires additional action, failed due to client error, or encountered a server problem.

Every time your browser or app makes an HTTP request (GET, POST, PUT, DELETE), the server responds with a 3-digit numeric code. This code communicates the operation's result before processing the response body. Codes are grouped into five classes by first digit: 1xx (informational), 2xx (success), 3xx (redirection), 4xx (client error), 5xx (server error).

Example: when you load a page and see content, the server probably responded 200 OK. If the URL changed, maybe it was 301 Moved Permanently. If you try to access without permission, 403 Forbidden. If the server is down, 503 Service Unavailable. These codes are HTTP standards defined in RFC 7231 and later extensions.

HTTP codes are fundamental for debugging, SEO, monitoring, and UX. A well-handled 404 with custom page improves experience. A 500 without logging makes finding bugs difficult. Google penalizes sites with many 5xx errors. REST APIs use specific codes (201 Created, 204 No Content, 409 Conflict) to communicate results unambiguously.

2xx: Success. 200 OK: successful request, response with content. 201 Created: resource created (typical in POST). 204 No Content: success but no body (useful in DELETE). 206 Partial Content: partial response, used in streaming and resumable downloads.

3xx: Redirection. 301 Moved Permanently: URL changed forever, update bookmarks (important for SEO). 302 Found: temporary redirect, original URL still valid. 304 Not Modified: resource unchanged since last time, use cache (key optimization). 307 Temporary Redirect: like 302 but guarantees HTTP method doesn't change (POST stays POST).

4xx: Client error. 400 Bad Request: malformed request (invalid JSON, missing parameters). 401 Unauthorized: authentication required or failed. 403 Forbidden: authenticated but no permissions. 404 Not Found: resource doesn't exist. 405 Method Not Allowed: GET on endpoint that only accepts POST. 409 Conflict: state conflict (create resource that already exists). 429 Too Many Requests: rate limiting, retry later.

5xx: Server error. 500 Internal Server Error: generic server error. 502 Bad Gateway: intermediate server (proxy, load balancer) received invalid response. 503 Service Unavailable: server temporarily overloaded or in maintenance. 504 Gateway Timeout: intermediate server didn't receive response in time.

In frontend, always check the code before processing response. Don't assume successful fetch() means valid data: a 404 technically doesn't throw error in fetch, you need if (!response.ok) throw new Error(). Show specific messages: 401 → "Please log in", 403 → "You don't have permissions", 404 → "Page not found", 500 → "Server error, try again".

In backend/APIs, use semantic codes. POST creating resource should return 201 with Location header pointing to new resource. Successful DELETE can be 204 (no content) or 200 with message. Failed validation is 400 with error details, not 500. Failed authentication is 401, failed authorization is 403. For rate limiting, return 429 with Retry-After header.

In SEO, correct codes are critical. Deleted pages should return 410 Gone or 404, not 200 with "not found" message (Google indexes it as real content). Permanent redirects (domain change, deprecated URLs) should be 301 to transfer SEO juice. 302/307 only for truly temporary redirects. Frequent 5xx errors damage ranking: monitor and fix quickly.

Developer tools in browsers show all codes in Network tab. Filter by ranges: viewing only 4xx reveals client problems, 5xx server problems. Status column gives you the code, Time column response time. A 200 taking 10 seconds is a problem even though code is correct.

In production, configure alerts on error rates. If >5% of requests are 5xx, something's broken. If you see 429 spikes, your rate limiting is working or you have anomalous traffic (scrapers, attacks). Tools like Datadog, New Relic or Sentry track HTTP codes and correlate with performance and logs.

API testing: write tests validating expected codes. POST /users with valid data should return 201, with duplicate email should be 409, without auth should be 401. This prevents regressions where code changes alter API contracts unknowingly.

A common mistake is only logging 5xx errors. Also log relevant 4xx: many 404s on same URL suggest broken links, many 401s may indicate integration problem. Analyze patterns: if 80% of 400s come from same form field, frontend validation isn't working.

Examples

  • GET /api/users/123 → 200 OK (user found and returned)
  • POST /api/users → 201 Created (user created successfully)
  • GET /api/users/999 → 404 Not Found (user doesn't exist)
  • DELETE /api/users/123 without auth → 401 Unauthorized (missing token)
  • PUT /api/users/123 with invalid data → 400 Bad Request
  • GET /api/products when server down → 503 Service Unavailable

FAQ

What's the difference between 401 and 403?

401 Unauthorized means you're not authenticated: missing token, expired session, incorrect credentials. The server doesn't know who you are. 403 Forbidden means you're authenticated but not authorized: the server knows who you are but you don't have permissions for that resource. Example: regular user trying to access admin panel is 403, user without login is 401.

Why does my API return 200 with error in body instead of 4xx/5xx?

This is a common anti-pattern called "envelope response". Some old APIs always return 200 with <code>{"status":"error"}</code> in JSON. This breaks HTTP caching, complicates error handling in client, and isn't RESTful. HTTP code should reflect the result: validation error is 400, resource not found is 404, server error is 500. Use body for additional details.

What code to use when a resource no longer exists and never will?

410 Gone is most appropriate: indicates resource existed but was permanently deleted. This is useful for SEO (tells Google to stop indexing) and APIs (client can clean references). 404 Not Found is also acceptable and more common, but doesn't communicate permanence. For intentionally deleted pages (discontinued products, deleted posts), 410 is semantically better.