DevLab
Text

HTTP Status Codes: A Practical Developer Guide

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)

Frequently Asked Questions

What is the difference between 401 and 403?

401 Unauthorized means the client is not authenticated — either no credentials were provided or they are invalid. Despite the name, it really means "unauthenticated." 403 Forbidden means the client is authenticated (the server knows who they are) but does not have permission to access the resource. Use 401 for login failures and missing tokens; use 403 for insufficient role or permission.

Should I return 200 with an error message or a 4xx status code?

Always use the correct HTTP status code. Returning 200 with an error in the body (e.g., {"status": "error"}) breaks HTTP semantics. Clients, proxies, CDNs, and monitoring tools all use the status code to determine success or failure. A 200 response with an error body will be cached by CDNs, counted as a success in metrics, and confuse every tool in the chain.

When should I use 400 vs 422?

400 Bad Request means the request is malformed — invalid JSON syntax, missing required headers, or wrong content type. The server cannot even parse the request. 422 Unprocessable Entity means the request is well-formed (valid JSON, correct structure) but semantically invalid — like an email field containing "not-an-email" or a date in the past for a future booking. Many APIs use 400 for both; 422 is more precise.

What does the 429 Too Many Requests status code mean?

The 429 status code means the client has sent too many requests in a given time window and has been rate-limited. The server should include a Retry-After header indicating how many seconds the client should wait before retrying. This code is essential for API rate limiting and protects your server from abuse or accidental request storms from buggy clients.

Should I return 404 or 403 for resources the user cannot access?

It depends on your security model. Returning 403 confirms the resource exists but the user lacks access, which may leak information. Returning 404 hides the resource's existence entirely, which is more secure. Use 404 when you do not want to reveal whether a resource exists (e.g., other users' private data). Use 403 when the resource is known to exist and the user should understand they need different permissions.

More Learning Topics

RegexRegex Basics: A Complete Beginner's GuideRegexRegex Special Characters: Complete ReferenceRegexRegex Groups and Captures ExplainedRegexRegex Quantifiers: Complete GuideCSSCSS Selectors: The Complete GuideCSSCSS Specificity: Why Your Styles Aren't ApplyingJSONJSONPath Syntax: Query JSON Like XPathTimeUnix Timestamps ExplainedEncodingBase64 Encoding ExplainedEncodingJWT Structure and How It WorksEncodingJWT vs Session Tokens: Which Should You Use?EncodingJWT Refresh Tokens ExplainedCryptoHash Functions Explained: MD5, SHA-256, and When to Use EachEncodingURL Encoding Explained: What %20 Actually MeansJSONJSON Schema Explained: Validate Your JSON DataJSONJSON vs YAML: Which Should You Use?JSONJSON.stringify and JSON.parse: Edge Cases You Should KnowRegexRegex Lookahead and Lookbehind: Match Without ConsumingRegexRegex for Email Validation: The Right ApproachCSSThe CSS Box Model: margin, padding, border, and contentCSSFlexbox vs CSS Grid: When to Use EachCSSCSS Custom Properties (Variables) ExplainedTimeISO 8601 Explained: The Right Way to Format DatesTimeUnix Timestamps vs ISO 8601: Which to Use in Your API?EncodingUTF-8 Explained: How Computers Store TextTextCORS Explained: Why Your API Call is BlockedRegexNamed Capture Groups in Regex: Clean ExtractionsColorsColor Spaces Explained: RGB, HSL, HEX, and BeyondColorsColor Contrast for Developers: WCAG Rules and How to CheckNumbersNumber Bases Explained: Binary, Octal, Decimal, and HexNumbersBitwise Operations for Web DevelopersHTMLHTML Semantic Elements: A Complete ReferenceTextText Encoding for Developers: ASCII, UTF-8, and UnicodeRegexWhat is Regex? Complete Guide for DevelopersJSONJSON Format Explained: Structure, Syntax, and Common ErrorsEncodingHow JWT Works: Header, Payload, Signature DecodedHTMLHow to Convert Any Website to Markdown (for LLMs, RAG & Docs)TextPreparing Website Content for RAG: Clean Markdown Pipelines