Learn what each HTTP status code range means, which codes to use in your REST API, and how to avoid the most common status code mistakes.
The Five Ranges
- 1xx Informational: Request received, continuing process (rarely used directly)
- 2xx Success: Request was received, understood, and accepted
- 3xx Redirection: Client must take additional action to complete the request
- 4xx Client Error: The request is wrong — the client is at fault
- 5xx Server Error: The server failed to fulfill a valid request — the server is at fault
Essential 2xx Codes
200 OK — Standard success. Use for GET, PUT, PATCH responses that return a body.
201 Created — Resource was created. Return after successful POST. Include a Location header with the new resource URL.
204 No Content — Success with no response body. Use for DELETE operations.
Essential 4xx Codes
400 Bad Request — Malformed request, invalid JSON, or failed validation. Include error details in the body.
401 Unauthorized — Authentication required or failed. Means "unauthenticated" despite the name.
403 Forbidden — Authenticated but not authorized. User is logged in but lacks permission.
404 Not Found — Resource does not exist. Also use to hide existence of a resource from unauthorized users.
409 Conflict — State conflict — e.g., duplicate email on signup.
422 Unprocessable Entity — Request is well-formed but semantically wrong. Preferred for validation errors.
429 Too Many Requests — Rate limit exceeded. Include Retry-After header.
Common Mistakes
// Never return 200 for errors
❌ HTTP 200: { "status": "error", "message": "User not found" }
✓ HTTP 404: { "error": "User not found" }
// 401 vs 403:
// 401 = "who are you?" (not logged in, or wrong credentials)
// 403 = "I know who you are, but no" (not authorized)
// Always return JSON from APIs — not HTML error pages
REST API Status Code Cheatsheet
GET /users/1 → 200 or 404
POST /users → 201 or 400/422 (invalid input)
PUT /users/1 → 200 or 404
DELETE /users/1 → 204 or 404
POST /auth/login → 200 or 401 (wrong credentials)
GET /admin/data → 200 or 403 (not admin)