The Complete Guide to HTTP Status Codes: From Protocol to Troubleshooting
The Complete Guide to HTTP Status Codes: From Protocol to Troubleshooting#
When debugging APIs, you’ve surely encountered various HTTP status codes. 200 OK is straightforward, but what about 401, 403, or 500? What’s the difference between 502 and 504? This article covers HTTP status codes from protocol principles to practical troubleshooting.
The Classification Logic#
HTTP status codes are three-digit numbers where the first digit indicates the category:
| Range | Category | Meaning |
|---|---|---|
| 1xx | Informational | Request received, continuing process |
| 2xx | Success | Request successfully received, understood, accepted |
| 3xx | Redirection | Further action needed to complete request |
| 4xx | Client Error | Request contains bad syntax or cannot be fulfilled |
| 5xx | Server Error | Server failed to fulfill valid request |
Remember this classification - it helps you quickly identify who’s responsible when problems arise.
Common Status Codes Explained#
2xx Success Codes#
200 OK is the most common success response, but be aware:
- GET request: Response body contains the requested resource
- POST request: Response body contains the operation result
- HEAD request: Only headers, no response body
201 Created indicates resource creation success, typically used after POST requests to return the new resource URI:
HTTP/1.1 201 Created
Location: /api/users/123
Content-Type: application/json
{"id": 123, "name": "John Doe"}
204 No Content means success without response body, commonly used for DELETE or PUT updates:
// Return 204 after deleting user
app.delete('/users/:id', async (req, res) => {
await User.delete(req.params.id)
res.status(204).send()
})
3xx Redirection Codes#
301 vs 302 - Many developers confuse these:
- 301 Moved Permanently: Permanent redirect, browser caches new address, SEO value transfers
- 302 Found: Temporary redirect, browser requests original address each time, SEO value doesn’t transfer
// Permanent migration to new domain
app.get('/old-page', (req, res) => {
res.redirect(301, 'https://new-domain.com/new-page')
})
// Temporary maintenance page
app.get('/dashboard', (req, res) => {
if (isMaintenance) {
res.redirect(302, '/maintenance')
}
})
304 Not Modified indicates cache hit, working with If-Modified-Since and ETag:
GET /style.css HTTP/1.1
If-Modified-Since: Wed, 01 May 2026 00:00:00 GMT
HTTP/1.1 304 Not Modified
// No response body, use browser cache directly
4xx Client Errors#
400 Bad Request means malformed request syntax. Common causes:
- Invalid JSON format
- Missing required parameters
- Parameter type mismatch
// Backend parameter validation example
app.post('/api/users', (req, res) => {
const { name, email } = req.body
if (!name || !email) {
return res.status(400).json({
error: 'Missing required fields',
required: ['name', 'email']
})
}
// ...
})
401 Unauthorized vs 403 Forbidden - Key difference:
- 401: Not logged in or invalid token, needs re-authentication
- 403: Logged in but insufficient permissions
// 401: Invalid token
if (!verifyToken(req.headers.authorization)) {
return res.status(401).json({ error: 'Invalid token' })
}
// 403: Insufficient permissions
if (user.role !== 'admin') {
return res.status(403).json({ error: 'Admin access required' })
}
404 Not Found means resource doesn’t exist, but distinguish two cases:
- URL path error:
GET /api/usres/123(typo) - Resource actually missing:
GET /api/users/999(user ID doesn’t exist)
5xx Server Errors#
500 Internal Server Error is the most common error code but also the least helpful. Possible causes:
- Code logic errors (uncaught exceptions)
- Database connection failure
- Third-party service timeout
// Error handling middleware
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).json({
error: 'Internal server error',
message: process.env.NODE_ENV === 'development' ? err.message : undefined
})
})
502 Bad Gateway means reverse proxy (like Nginx) cannot get response from upstream server:
- Backend service not started
- Backend service crashed
- Backend service response timeout
504 Gateway Timeout means reverse proxy timed out waiting for upstream server:
- Backend processing too long
- Slow database query
- External API call timeout
# Nginx timeout configuration
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
Practical Troubleshooting#
1. Quick Diagnosis with curl#
# View complete response headers
curl -I https://api.example.com/users/123
# Follow redirects
curl -L https://old-domain.com/page
# Simulate browser request
curl -A "Mozilla/5.0" https://example.com
2. Browser DevTools Analysis#
Open Network panel, click any request:
- Status column shows status code and text description
- Headers tab shows complete response headers
- Preview tab shows response body (if error message exists)
3. Backend Log Investigation#
For 500 errors, always check backend logs - the status code is just the symptom:
# Node.js
pm2 logs app
# Nginx
tail -f /var/log/nginx/error.log
# System logs
journalctl -u myapp -f
Common Questions#
Q: Why do some APIs return 200 with error info in body?
A: This is RPC-style error handling, not RESTful compliant. The correct approach:
// Wrong approach
res.status(200).json({ code: 400, message: 'Bad request' })
// Correct approach
res.status(400).json({ error: 'Bad request' })
Q: How to handle 429 Too Many Requests?
A: This is rate limiting protection, response headers usually contain retry time:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
Q: What’s the difference between 503 and 500?
A: 503 means temporarily unavailable (usually with Retry-After header), 500 means internal server error. 503 is common for planned maintenance or overload protection.
Summary#
HTTP status codes are the language for frontend-backend communication. Understanding each code helps you quickly identify problems:
- 2xx success, 3xx redirection, 4xx client issues, 5xx server issues
- 401 unauthenticated, 403 no permission
- 502 upstream unreachable, 504 upstream timeout
Next time you encounter a status code issue, first determine the category, then the specific number, finally check relevant logs.
Related Tools:
- HTTP Status Code Lookup - Quick lookup of all status code meanings
- HTTP Header Analyzer - Analyze HTTP response header security
- API Tester - Test API endpoints online