2026-04-24
HTTP Status Codes Explained: The Developer's Quick Reference
HTTP status codes are how servers talk to clients. Master these and you'll debug faster, monitor smarter, and build better alerting systems.
HTTP status codes are how servers talk to clients. Master these and you'll debug faster, monitor smarter, and build better alerting systems.
Quick Reference Table
| Code | Status | What It Means | Common Causes |
|---|---|---|---|
| 200 | ✅ OK | Success | Page loaded, API returned data |
| 201 | ✅ Created | Resource made | New record saved, user created |
| 204 | ✅ No Content | Success, empty body | Delete confirmed, action done |
| 301 | 🔀 Permanent | Moved forever | Domain redirect, URL rewrite |
| 302 | 🔀 Temporary | Moved temporarily | A/B testing, maintenance redirect |
| 304 | ⚡ Not Modified | Cached version OK | Browser cache, CDN |
| 400 | ❌ Bad Request | Your request is broken | Bad JSON, missing params, bad encoding |
| 401 | 🔒 Unauthorized | Not logged in | No token, expired session |
| 403 | 🚫 Forbidden | Logged in but not allowed | Wrong role, IP blocked |
| 404 | ❌ Not Found | Resource doesn't exist | Deleted page, typo in URL |
| 429 | ⏳ Too Many Requests | Slow down | Rate limit hit, bot detected |
| 500 | 💥 Server Error | The server broke | Code bug, DB down, OOM |
| 502 | 🔌 Bad Gateway | Upstream is sick | Reverse proxy failed |
| 503 | ⏰ Service Unavailable | Server overloaded | Maintenance, traffic spike |
| 504 | ⏱️ Gateway Timeout | Upstream too slow | Timeout waiting for API/DB |
2xx — Success
200 OK — The standard success. Request worked, here's your data. Every healthy endpoint should return this.
201 Created — Resource successfully made. Use after POST requests that create records. Important for API design: return 201 + the created resource's location header.
204 No Content — Success but nothing to return. Used for DELETE operations or actions that don't need a response body. Important: no content means no body, not even {}.
304 Not Modified — Browser/CDN should use cached version. Server sends this when client sends If-None-Match or If-Modified-Since headers. Huge for performance: means zero bandwidth for unchanged resources.
3xx — Redirects
301 Moved Permanently — Resource lives somewhere else forever. Browsers cache this. SEO transfers ranking. Use for domain migrations, URL restructuring.
302 Found (Temporary) — Resource is somewhere else for now. Browsers don't cache this. Use for A/B tests, seasonal redirects, maintenance pages.
304 Not Modified — Already covered above under 2xx, but it's a redirect. Reduces bandwidth significantly.
307 Temporary Redirect — Same as 302 but guarantees the method won't change. POST requests stay POST.
308 Permanent Redirect — Same as 301 but guarantees the method won't change.
304 vs 301/302: 304 is about caching, not redirecting. It tells the client "your cached version is still valid." 3xx codes tell clients to fetch from a different URL.
4xx — Client Errors
These are your fault (or the caller's).
400 Bad Request — The request is malformed. Bad JSON, missing required fields, invalid encoding. Check your request body and headers.
401 Unauthorized — No valid authentication. Missing or invalid token/session/API key. The server doesn't know who you are.
403 Forbidden — Authenticated but not allowed. You are who you say you are, but you don't have permission. Unlike 401, the server knows your identity — you just can't access this.
404 Not Found — The resource doesn't exist at this URL. Could be deleted, never existed, or a typo. For monitoring tools: a 404 on your /api/health endpoint means something is very wrong.
405 Method Not Allowed — Tried POST on a GET-only endpoint, etc. Check the allowed methods in the Allow header.
409 Conflict — Request conflicts with current server state. Tried to create a duplicate, outdated version, or conflicting operation. Common in distributed systems.
410 Gone — Like 404 but permanent. The resource existed and is deliberately removed. Different from 404: this tells clients it's never coming back.
415 Unsupported Media Type — Sent JSON when server expects XML, or forgot to set Content-Type. Check your request headers.
422 Unprocessable Entity — Syntax is correct but semantics are wrong. "Valid JSON but the email address is invalid." Common in Rails/Spring APIs.
429 Too Many Requests — Rate limited. Check Retry-After header. Back off and retry after the specified seconds.
451 Unavailable For Legal Reasons — Censorship. The resource exists but can't be served in this jurisdiction (DMCA, government order). Named after Ray Bradbury's Fahrenheit 451.
5xx — Server Errors
These are the server's fault. If you're seeing these in your monitoring, something broke and you need to investigate.
500 Internal Server Error — Generic server failure. Something threw an unhandled exception. The worst status code because it tells you nothing about what broke.
501 Not Implemented — Server doesn't support this request method. Rare — usually means incomplete API.
502 Bad Gateway — Your server is acting as a gateway/proxy and the upstream returned an error. Common cause: your API server is down, returning 503, or throwing 500, and your reverse proxy surfaces it as 502.
503 Service Unavailable — Server is temporarily down. Could be overloaded, under maintenance, or restarting. Check the Retry-After header. If you see this frequently, your infrastructure is underprovisioned.
504 Gateway Timeout — Your server is acting as a gateway and the upstream is too slow. Common when a microservice times out. Check the upstream service's health and your timeout settings.
500 vs 502 vs 503:
- 500: Your code broke
- 502: Your dependencies broke
- 503: Your system is overloaded or restarting
How Status Codes Help Your Monitoring
If you run uptime monitoring for clients, here is what you want to see:
| Scenario | Expected Code |
|---|---|
| Health check | 200 on /api/health |
| Authenticated user data | 200 with valid session |
| Deleted resource | 404 (or 410 if permanent) |
| Rate limited | 429 with Retry-After |
| Internal error | 500 → alert immediately |
| Dependency down | 502 or 504 → alert immediately |
| Maintenance mode | 503 with Retry-After |
Configure your monitors to alert on 5xx only (server errors are the real problems). A 404 on a specific URL might be expected. A 500 is always a problem.
Tools for Checking Status Codes
curl -I https://example.com— HEAD request, shows headers onlycurl -s -o /dev/null -w "%{http_code}" https://example.com— status code only- Browser DevTools → Network tab → Status column
- Pinger's HTTP monitor — get alerted the second status codes change
When to Escalate
- 200 → 500: P0. Site is broken. Alert immediately.
- 200 → 502/503: P0. Dependency or infrastructure issue.
- 200 → 429: P1. Rate limiting kicking in. May indicate traffic spike or abuse.
- 200 → 404: P2. Likely a broken link or deleted resource.
- 3xx changes: Worth investigating — a 301 becoming 200 means a redirect was removed.
Common Misconceptions
"404 is always bad" — No. 404 on /blog/old-post-2021 is fine if that post was deleted. 404 on /api/health is a disaster.
"500 is always the server's fault" — Yes, but "the server" includes your dependencies. If your DB returns 500, it's your server returning 500.
"3xx means something broke" — No. 301/302 are normal redirects. 304 is a performance optimization.
"Status code is the whole story" — No. A 200 with 5-second response time means your page is broken even though the status is OK. Monitor latency too.
Stay on top of your status codes. Set up HTTP monitoring at pingerhq.com — try it free.