Débutant20 min de lecture

HTTP Status Codes

Master HTTP status codes, understand the 1xx-5xx families, learn when to use which code, and avoid common mistakes in API responses.

Understanding Status Codes

Every HTTP response includes a status code — a three-digit number that tells the client what happened. Did the request succeed? Was there an error? Should the client retry?

Status codes are organized into five families, each with a specific meaning:

1xx — Informational The request was received and is being processed. Rarely used in REST APIs.

  • 100 Continue — Server received headers, client should send body
  • 101 Switching Protocols — Server is switching to WebSocket, for example

2xx — Success The request succeeded. The most common and desirable outcome.

  • 200 OK — Request succeeded, response body contains the result
  • 201 Created — New resource was created (POST)
  • 204 No Content — Request succeeded but no content to return (DELETE)

3xx — Redirection The client needs to take additional action. The resource has moved.

  • 301 Moved Permanently — Resource has permanently moved to a new URL
  • 302 Found — Resource temporarily at a different URL
  • 304 Not Modified — Resource hasn't changed since last request (caching)

4xx — Client Error The client made a mistake. Bad request, unauthorized, not found.

  • 400 Bad Request — Malformed request syntax
  • 401 Unauthorized — Authentication required or failed
  • 403 Forbidden — Authenticated but not authorized
  • 404 Not Found — Resource doesn't exist

5xx — Server Error The server failed to fulfill a valid request. Something went wrong on the backend.

  • 500 Internal Server Error — Generic server error
  • 503 Service Unavailable — Server is temporarily down or overloaded

The first digit tells you the category. If you see a 4xx code, you know it is a client error. If you see a 5xx code, you know it is a server error. This structure makes status codes predictable and easy to handle programmatically.

The Most Important Status Codes for APIs

While there are dozens of status codes, only a handful are essential for building REST APIs. Here are the ones you will use most:

200 OK — General Success Use for successful GET, PUT, or PATCH requests when returning data.

html
GET /users/123 → 200 OK + user data
PUT /users/123 → 200 OK + updated user data

201 Created — Resource Created Use for successful POST requests that create a new resource. Include a Location header with the URL of the new resource.

html
POST /users → 201 Created + new user data
Location: /users/456

204 No Content — Success with No Response Body Use for successful DELETE requests or updates that don't return data.

DELETE /users/123 → 204 No Content

400 Bad Request — Malformed or Invalid Request Use when the request is syntactically incorrect or missing required fields.

POST /users with invalid JSON → 400 Bad Request

401 Unauthorized — Authentication Required Use when the request lacks valid authentication credentials. The name is misleading — it really means "unauthenticated".

GET /users without auth token → 401 Unauthorized

403 Forbidden — Authenticated but Not Authorized Use when the user is logged in but doesn't have permission for this action.

DELETE /users/123 as a non-admin → 403 Forbidden

404 Not Found — Resource Doesn't Exist Use when the requested resource doesn't exist.

GET /users/999999 → 404 Not Found

409 Conflict — Request Conflicts with Current State Use when the request would create a conflict, like a duplicate resource.

POST /users with existing email → 409 Conflict

422 Unprocessable Entity — Validation Failed Use when the request is well-formed but fails business logic validation.

POST /users with email missing @ symbol → 422 Unprocessable Entity

429 Too Many Requests — Rate Limit Exceeded Use when the client has sent too many requests in a given time period.

html
100th request in 1 minute → 429 Too Many Requests
Retry-After: 60

500 Internal Server Error — Something Broke Use when an unexpected error occurs on the server.

GET /users causes database crash → 500 Internal Server Error

503 Service Unavailable — Server Temporarily Down Use when the server is under maintenance or overloaded.

html
Any request during deployment → 503 Service Unavailable
Retry-After: 300

Status Code Decision Flow

html
<div style="font-family:sans-serif; padding:20px; line-height:1.8;">
  <h3>Choosing the Right Status Code</h3>
  <div style="background:#f3f4f6; padding:16px; border-radius:8px; border-left:4px solid #3b82f6;">
    <strong>1. Did the request succeed?</strong><br>
    ✅ Yes → Use 2xx<br>
    ❌ No → Continue to step 2
  </div>
  <div style="background:#fef3c7; padding:16px; border-radius:8px; border-left:4px solid #f59e0b; margin-top:12px;">
    <strong>2. Who caused the problem?</strong><br>
    👤 Client error (bad input, auth failure) → Use 4xx<br>
    🖥️ Server error (crash, timeout) → Use 5xx
  </div>
  <div style="background:#dbeafe; padding:16px; border-radius:8px; border-left:4px solid #3b82f6; margin-top:12px;">
    <strong>3. What specifically happened?</strong><br>
    <table style="width:100%; margin-top:8px; font-size:14px;">
      <tr><td>Created new resource?</td><td><strong>201 Created</strong></td></tr>
      <tr><td>Deleted successfully?</td><td><strong>204 No Content</strong></td></tr>
      <tr><td>Missing auth token?</td><td><strong>401 Unauthorized</strong></td></tr>
      <tr><td>Not allowed to access?</td><td><strong>403 Forbidden</strong></td></tr>
      <tr><td>Resource not found?</td><td><strong>404 Not Found</strong></td></tr>
      <tr><td>Validation failed?</td><td><strong>422 Unprocessable Entity</strong></td></tr>
      <tr><td>Server crashed?</td><td><strong>500 Internal Server Error</strong></td></tr>
    </table>
  </div>
</div>

Common Status Code Mistakes

Many APIs misuse status codes, leading to confusion and poor client experience. Here are the most common mistakes and how to avoid them:

Mistake 1: Returning 200 OK for Errors Some APIs return 200 OK for every response and put the error in the response body:

json
200 OK
{ "success": false, "error": "User not found" }

This is wrong. Status codes exist to communicate success or failure. Use 404 Not Found instead. Clients should be able to check the status code without parsing the body.

Mistake 2: Using 404 for Validation Errors

POST /users with invalid email → 404 Not Found ❌

404 means the resource doesn't exist. Validation failures should return 400 Bad Request or 422 Unprocessable Entity.

Mistake 3: Confusing 401 and 403

  • 401 Unauthorized — You are not logged in. Send credentials.
  • 403 Forbidden — You are logged in, but you don't have permission.

If a user without an auth token tries to delete a resource, return 401. If a regular user tries to delete an admin resource, return 403.

Mistake 4: Using 500 for Expected Errors

GET /users/invalid-id → 500 Internal Server Error ❌

If the client sends an invalid ID, that is a client error (400 Bad Request). Reserve 500 for unexpected server crashes and exceptions.

Mistake 5: Not Including Retry Information When returning 429 Too Many Requests or 503 Service Unavailable, always include a Retry-After header telling the client when to try again:

html
429 Too Many Requests
Retry-After: 60

Best Practice: Be Specific Don't just use 400 Bad Request for everything. If it is a validation error, use 422. If it is a conflict, use 409. If it is a not found, use 404. Specific status codes help clients handle errors intelligently.

A user tries to update another user's profile. They are logged in, but they don't have permission. What status code should the API return?

Prêt à pratiquer ?

Crée ton compte gratuit pour accéder à l'éditeur de code interactif, lancer les défis et suivre ta progression.