HTTP Status Codes

Numbers that tell you if your request worked, failed, or went somewhere else.

6 min read

What are HTTP Status Codes?

Every HTTP response includes a three-digit status code. The first digit tells you the category, the other two get specific.

javascript
const response = await fetch("/api/users/123");
console.log(response.status); // 200
console.log(response.ok);     // true (status 200-299)

If you've ever seen a 404 page, you've seen a status code in the wild.

The Five Categories

RangeCategoryMeaning
1xxInformationalHold on, still processing
2xxSuccessIt worked
3xxRedirectionGo somewhere else
4xxClient ErrorYou messed up
5xxServer ErrorWe messed up

Success Codes (2xx)

The happy path. Your request worked.

CodeNameWhen to Use
200OKStandard success (GET, PUT, PATCH)
201CreatedResource created (POST)
202AcceptedRequest received, processing later
204No ContentSuccess but nothing to return (DELETE)
javascript
// Handling success codes
async function createUser(data) {
  const res = await fetch("/api/users", {
    method: "POST",
    body: JSON.stringify(data)
  });

  if (res.status === 201) {
    const user = await res.json();
    console.log("Created:", user.id);
  }
}

Redirection Codes (3xx)

The resource moved. Follow the Location header.

CodeNameWhen to Use
301Moved PermanentlyURL changed forever, update bookmarks
302FoundTemporary redirect
304Not ModifiedUse your cached version
307Temporary RedirectSame as 302 but keep the method
308Permanent RedirectSame as 301 but keep the method
ℹ️301 vs 308

With 301/302, browsers may change POST to GET on redirect. Use 307/308 when you need to preserve the original HTTP method.

Client Error Codes (4xx)

Something's wrong with the request. Fix it on your end.

CodeNameMeaning
400Bad RequestMalformed syntax, invalid JSON
401UnauthorizedNo auth or bad credentials
403ForbiddenValid auth but not allowed
404Not FoundResource doesn't exist
405Method Not AllowedWrong HTTP verb
409ConflictRequest conflicts with current state
410GoneResource existed but was deleted
422Unprocessable EntityValidation failed
429Too Many RequestsRate limited, slow down
javascript
// Handling client errors
async function getUser(id) {
  const res = await fetch(`/api/users/${id}`);

  switch (res.status) {
    case 200:
      return res.json();
    case 401:
      throw new Error("Please log in");
    case 403:
      throw new Error("You don't have permission");
    case 404:
      return null; // User doesn't exist
    case 429:
      throw new Error("Too many requests, try again later");
    default:
      throw new Error(`Request failed: ${res.status}`);
  }
}

401 vs 403

CodeAuth Present?Permission?Example
401No/InvalidN/AMissing or expired token
403Yes, validNoUser trying to access admin panel

Server Error Codes (5xx)

The server broke. Not your fault (usually).

CodeNameMeaning
500Internal Server ErrorGeneric "something broke"
502Bad GatewayUpstream server sent bad response
503Service UnavailableServer is overloaded or down
504Gateway TimeoutUpstream server didn't respond in time
javascript
// Handling server errors with retry
async function fetchWithRetry(url, retries = 3) {
  for (let i = 0; i < retries; i++) {
    const res = await fetch(url);

    if (res.status >= 500) {
      // Server error - wait and retry
      await new Promise(r => setTimeout(r, 1000 * (i + 1)));
      continue;
    }

    return res;
  }
  throw new Error("Server unavailable after retries");
}

Quick Reference Table

CodeNameRemember It As
200OK"Here's your stuff"
201Created"Made it for you"
204No Content"Done, nothing to say"
301Moved Permanently"We moved, update your links"
304Not Modified"Use your cache"
400Bad Request"I can't understand you"
401Unauthorized"Who are you?"
403Forbidden"I know you, but no"
404Not Found"Doesn't exist"
409Conflict"Can't do that right now"
422Unprocessable"I understand but won't do it"
429Too Many Requests"Calm down"
500Internal Server Error"We broke"
502Bad Gateway"Upstream broke"
503Service Unavailable"Try again later"

Common Gotchas

⚠️200 with Error Body

Some APIs return 200 with an error in the JSON body. Always check both the status code AND the response body. { "status": 200, "error": "Not found" } is poor API design, but it exists.

⚠️Empty 404 vs 204

A 404 means "this resource doesn't exist." A 204 means "success, but nothing to return." Don't use 404 for successful DELETE operations.

  • response.ok only checks 2xx - In JavaScript fetch, response.ok is true for 200-299 only. A 304 redirect returns ok: false.
  • Browsers hide 401/403 details - For security, browsers may not expose the full error. Check network tab for details.
  • Rate limit headers - When you get 429, check Retry-After header to know how long to wait.
  • Don't use 200 for errors - If validation fails, use 400 or 422, not 200 with an error message.
  • 503 means "come back later" - If you see 503, the server is overwhelmed. Implementing exponential backoff is polite.

Try It

Format API Error Responses

"HTTP status codes: where 200 means success, 404 means missing, and 418 means someone at the IETF had a sense of humor."