Every HTTP response starts with a three-digit status code. The first digit tells you the category; the specific code tells you what happened. Knowing the common ones speeds up debugging websites, APIs and server configs.
| Range | Category |
|---|---|
| 1xx | Informational |
| 2xx | Success |
| 3xx | Redirection |
| 4xx | Client error (the request was wrong) |
| 5xx | Server error (the server failed) |
Check a URL’s status:
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/page
curl -sI https://example.com/page | head -1
1xx
- 101 Switching Protocols — WebSocket upgrades. See WebSockets through Nginx.
- 103 Early Hints — preload hints sent before the final response.
2xx: success
- 200 OK — the normal response.
- 201 Created — a resource was created (APIs, after POST).
- 204 No Content — success with no body (DELETE, CORS preflight).
- 206 Partial Content — range requests (video seeking, resumed downloads).
3xx: redirects
- 301 Moved Permanently — the URL changed for good; search engines transfer ranking. Use for domain moves, HTTPS, URL restructuring.
- 302 Found — temporary redirect.
- 304 Not Modified — the cached copy is still valid (ETag/Last-Modified revalidation). Good — saves bandwidth.
- 307 Temporary Redirect / 308 Permanent Redirect — like 302/301 but the method and body are preserved (POST stays POST).
See 301 vs 302 redirects and Nginx redirects. Watch for redirect chains and loops (ERR_TOO_MANY_REDIRECTS) — see WordPress too many redirects.
4xx: client errors
- 400 Bad Request — malformed request, invalid JSON, oversized headers/cookies, or (Django) a host not in
ALLOWED_HOSTS. - 401 Unauthorized — authentication required or failed (basic auth, missing API token).
- 403 Forbidden — authenticated or not, access is refused: file permissions, deny rules, WAF blocks. See Nginx 403.
- 404 Not Found — no resource at that URL: wrong path, missing file, broken permalinks. See WordPress permalinks 404.
- 405 Method Not Allowed — e.g. POST to a static file.
- 408 Request Timeout — the client was too slow sending the request.
- 410 Gone — removed permanently; search engines drop it faster than a 404. Useful when deleting content on purpose.
- 413 Content Too Large — upload exceeds limits. See Nginx 413.
- 414 URI Too Long — enormous query strings.
- 419 (Laravel) — expired CSRF token/session.
- 429 Too Many Requests — rate limited. See Nginx rate limiting.
- 444 (Nginx-specific) — connection closed without a response; used to drop bad requests.
- 499 (Nginx log only) — the client closed the connection before the server responded (impatient user or a proxy timeout upstream).
5xx: server errors
- 500 Internal Server Error — the application crashed or a config error occurred. Check application and PHP error logs.
- 502 Bad Gateway — the proxy got an invalid response from the backend: app down, wrong socket/port. See Nginx 502.
- 503 Service Unavailable — overloaded or in maintenance; should include
Retry-After. Return 503 (not 200 or 404) during planned maintenance so search engines come back later. - 504 Gateway Timeout — the backend was too slow. See Nginx 504.
- 507/508 — storage or resource limits (some shared hosts use 508 “Resource Limit Reached”).
CDNs add their own codes — Cloudflare’s 520–526 indicate problems between Cloudflare and your origin (e.g. 521: origin refused the connection, 522: timeout, 525/526: SSL problems at the origin).
Status codes and SEO
- Use 301 for permanent moves; avoid long chains.
- Return a real 404/410 for missing pages, not a 200 “not found” page (“soft 404”).
- Use 503 for temporary outages.
- Keep 5xx errors rare — repeated server errors make crawlers slow down.
Find problems in your logs
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
awk '$9 ~ /^5/ {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head