HandyTools Hub

← All guides

HTTP Status Codes Troubleshooting Guide: Where to Look When You See 4xx/5xx

2026-08-06

When an API call returns a 500, or an alert fires because 502s are spiking on an endpoint, your first question should be: whose problem is this code pointing at? An HTTP status code is essentially the server’s assignment of blame — 4xx means the client did something wrong, 5xx means the server did. Reading that digit correctly gets you halfway to the fix. This guide covers the five status code classes, walks through the most common codes one by one with causes and debugging directions, and clears up the two most confusing pairs: 301 vs 302 and 502 vs 504.

The Five Classes: Assign Blame First

The first digit of a status code determines its class:

ClassMeaningResponsible party
1xxInformational — request received, keep goingThe protocol itself
2xxSuccess — the request was handledNo problem
3xxRedirection — the client must take further actionDepends on configuration
4xxClient error — the request itself is flawedThe caller
5xxServer error — the server failed to handle itThe service

The most useful field rule: don’t dig through server logs for a 4xx, and don’t doubt your request parameters for a 5xx. That is only a starting point — a few codes (404 and 502 in particular) are less clear-cut than they look, as we’ll see below.

2xx: Success Has Nuances Too

200 OK: the generic success response. Beware the “200 but business failure” trap — many APIs bury application errors inside a 200 body ({"code": 4001, "msg": "insufficient balance"}), so monitoring that only watches status codes misses real failures. Business errors should return an appropriate 4xx.

201 Created: a resource was successfully created — the classic response to a POST that creates an order or a user. A well-behaved implementation includes the new resource’s URL in the Location header. If your POST endpoints always return 200, switching to 201 is semantically more accurate.

204 No Content: success with no response body, typically for DELETE or fire-and-forget submissions. A 204 must not carry a body; some frameworks force content in anyway, which breaks strict HTTP clients.

3xx: Redirects and Caching

301 Moved Permanently: a permanent redirect. Search engines transfer nearly all of the original URL’s ranking signals (link equity, indexation) to the new URL, and browsers cache the jump.

302 Found: a temporary redirect. Search engines treat the original URL as the canonical one, keep indexing it, and transfer no ranking weight.

The SEO difference between these two causes real production incidents: a site migration that mistakenly uses 302 watches its search traffic collapse because the old domain’s ranking never transfers; the reverse mistake — using 301 for a short-lived campaign or A/B test — means browsers and CDNs cache the “permanent” jump and users keep getting redirected after the campaign ends. The one-line rule: permanent moves get 301, temporary jumps get 302.

304 Not Modified: not an error — it is the sign that caching works. The client sends a conditional request with If-Modified-Since or If-None-Match; the server confirms nothing changed and replies 304 so the client uses its local copy. When debugging “my asset won’t update,” first check whether cache headers are too aggressive. Conversely, if static assets return 200 every time instead of 304, your cache policy is misconfigured and you’re burning bandwidth.

4xx: The Problem Is on the Request Side

400 Bad Request: the request payload itself is malformed — broken JSON syntax, a missing required field, a wrong parameter type. Print the raw request body and check it field by field against the API documentation.

401 Unauthorized: not authenticated. Despite the name, it means “I don’t know who you are” — the token is missing, expired, or has a bad signature. Check whether the Authorization header is present and whether the token has expired.

403 Forbidden: authenticated but not permitted — “I know who you are, and you can’t have this.” Distinguishing 401 from 403 is the first step in any permission investigation: for 401, check the login state; for 403, check role configuration, IP allowlists, or resource ownership.

404 Not Found: the resource doesn’t exist. Watch for two special cases: a gateway-level 404, where the domain or route isn’t mapped and the request never reached your application; and deliberate 404s used in place of 403 to hide a resource’s existence — in that case “it exists but returns 404” is actually a permissions issue.

405 Method Not Allowed: wrong HTTP method, such as sending GET to an endpoint that only accepts POST. The response’s Allow header lists the permitted methods. This commonly appears after an API goes RESTful while old client code still calls it the old way.

429 Too Many Requests: you hit a rate limit. The response usually carries a Retry-After header telling you when to try again. The correct client behavior is exponential backoff, not an immediate retry — hammering the endpoint only extends the limit. If you’re the service owner and 429s are surging, your rate limits or quotas need re-evaluation.

5xx: The Server Side Failed

500 Internal Server Error: the server’s generic catch-all. Almost any uncaught exception in application code surfaces as a 500. The debugging path is unambiguous: read the stack trace in the application logs. A 500 carries no further semantics — the logs are the answer.

502 Bad Gateway: a gateway (Nginx, a load balancer, an API gateway) asked an upstream service for a response and got something invalid — the upstream process is down, refused the connection, or returned unparseable data. The essence: the upstream never produced a proper answer.

503 Service Unavailable: the service is temporarily unable to handle requests. Common causes are deliberate rate shedding, circuit breakers, or maintenance mode, and the response often includes Retry-After. Unlike a 502, a 503 is usually intentional self-protection rather than an accidental failure. When 503s appear, first check whether capacity limits or circuit-breaker configuration are doing their job.

504 Gateway Timeout: the gateway waited for the upstream and ran out of time. The upstream is alive but slow — slow queries, deadlocks, or a stalled downstream dependency are all candidates. The 502 vs 504 distinction directly determines your debugging path:

  • 502: the upstream is dead or refusing connections → check the upstream process, its port, and its health checks;
  • 504: the upstream is alive but too slow → check slow-query logs, database queries, and the downstream call chain.

Practical Debugging Tips

Build one habit: when you see any error status code, first confirm which hop returned it — the application server, the gateway, the CDN, or something the browser fabricated. Run curl -v and read the full response headers; CDNs and gateways leave fingerprints in headers like Server and Via, and in custom error pages. This saves you from burning time at the wrong layer of the stack.

When you run into an unfamiliar code, looking it up in the HTTP Status Reference is much faster than digging through RFCs: it lists every standard status code organized from 1xx to 5xx with plain-language descriptions, searchable right in the browser. Pair the debugging approach in this guide with the HTTP Status Reference tool — the status code tells you which side owns the problem, and the debugging path takes you to the root cause.