
Python
HTTP status codes are three-digit numbers that tell you the result of your request. They're essential for understanding what went right or wrong when communicating with servers. Learning to read and handle status codes is crucial for building robust applications.
Every HTTP response includes a status code that indicates the outcome of the request. These codes are grouped into five categories based on their first digit.
import requests
response = requests.get('https://api.github.com/users/octocat')
# The status code
print(response.status_code) # 200
# Check if successful (status 200-299)
if response.ok:
print("Request succeeded!")
else:
print("Request failed!")
# Get status code with reason phrase
print(f"{response.status_code} {response.reason}") # 200 OKThese codes indicate the request succeeded.
The request succeeded and the server returned the requested data.
import requests
response = requests.get('https://jsonplaceholder.typicode.com/posts/1')
print(response.status_code) # 200
if response.status_code == 200:
data = response.json()
print(f"Post: {data['title']}")The request succeeded and a new resource was created.
import requests
new_post = {
'title': 'New Post',
'body': 'Post content',
'userId': 1
}
response = requests.post(
'https://jsonplaceholder.typicode.com/posts',
json=new_post
)
if response.status_code == 201:
created = response.json()
print(f"Created resource with ID: {created['id']}")The request succeeded but there's no content to return (common for DELETE).
import requests
response = requests.delete('https://api.example.com/users/5')
if response.status_code == 204:
print("Resource deleted successfully")
# No response body to parseThese codes indicate the request needs further action to complete.
The resource has been permanently moved to a new URL.
import requests
# By default, requests follows redirects automatically
response = requests.get('https://example.com') # Automatically follows redirects
# See final URL after redirects
print(response.url)
# Disable redirect following
response = requests.get('https://example.com', allow_redirects=False)
if response.status_code == 301:
new_location = response.headers['Location']
print(f"Moved to: {new_location}")The resource hasn't changed since your last request.
import requests
headers = {
'If-None-Match': 'abc123def456' # Validation token from previous response
}
response = requests.get(
'https://api.example.com/data',
headers=headers
)
if response.status_code == 304:
print("Data hasn't changed since last request")
# Use cached data from previous responseThese codes indicate something wrong with the client's request.
The request format is invalid.
import requests
# Missing required field
invalid_data = {'title': 'No body!'} # Missing 'body' field
response = requests.post(
'https://api.example.com/posts',
json=invalid_data
)
if response.status_code == 400:
error = response.json()
print(f"Bad request: {error}")Authentication is required or invalid.
import requests
# Missing authentication token
response = requests.get('https://api.example.com/private-data')
if response.status_code == 401:
print("Authentication required!")
print("Add your API key or token to the headers")
# Correct way with authentication
headers = {'Authorization': 'Bearer your-token-here'}
response = requests.get(
'https://api.example.com/private-data',
headers=headers
)You're authenticated but don't have permission to access this resource.
import requests
# You have a token but lack necessary permissions
response = requests.delete('https://api.example.com/admin/users')
if response.status_code == 403:
print("You don't have permission to delete users")The requested resource doesn't exist.
import requests
response = requests.get('https://api.example.com/users/99999')
if response.status_code == 404:
print("User not found!")
# Check before assuming data exists
if response.ok:
user = response.json()
else:
print(f"Error: {response.status_code}")The request conflicts with the current state of the resource.
import requests
# Trying to create duplicate resource
data = {'username': 'existing_user'}
response = requests.post('https://api.example.com/users', json=data)
if response.status_code == 409:
print("Username already exists!")You've sent too many requests too quickly (rate limiting).
import requests
import time
for i in range(100):
response = requests.get('https://api.example.com/data')
if response.status_code == 429:
# Rate limited - wait before retrying
retry_after = int(response.headers.get('Retry-After', 60))
print(f"Rate limited. Waiting {retry_after} seconds...")
time.sleep(retry_after)
# Retry the request
response = requests.get('https://api.example.com/data')These codes indicate something wrong with the server.
The server encountered an unexpected error.
import requests
response = requests.get('https://api.example.com/data')
if response.status_code == 500:
print("Server error! Try again later.")Invalid response from upstream server.
import requests
import time
response = requests.get('https://api.example.com/data')
if response.status_code == 502:
print("Bad gateway error. Retrying in 5 seconds...")
time.sleep(5)
response = requests.get('https://api.example.com/data')The server is temporarily down for maintenance.
import requests
response = requests.get('https://api.example.com/data')
if response.status_code == 503:
print("Service temporarily unavailable")
print("Check response headers for maintenance information")
print(response.headers.get('Retry-After'))import requests
from requests.exceptions import RequestException
import time
def make_request_with_retry(url, max_retries=3):
"""Make request with proper error handling and retries"""
for attempt in range(max_retries):
try:
response = requests.get(url, timeout=5)
# Check for specific status codes
if response.status_code == 200:
return response.json()
elif response.status_code == 401:
print("Authentication failed")
return None
elif response.status_code == 404:
print("Resource not found")
return None
elif response.status_code in [500, 502, 503]:
# Server error - retry
if attempt < max_retries - 1:
wait_time = 2 ** attempt # Exponential backoff
print(f"Server error. Retrying in {wait_time}s...")
time.sleep(wait_time)
continue
else:
print("Server error persists after retries")
return None
elif response.status_code == 429:
# Rate limited
retry_after = int(response.headers.get('Retry-After', 60))
print(f"Rate limited. Waiting {retry_after}s...")
time.sleep(retry_after)
continue
else:
# Unexpected status
print(f"Unexpected status: {response.status_code}")
return None
except requests.exceptions.Timeout:
print("Request timed out")
if attempt < max_retries - 1:
print("Retrying...")
time.sleep(1)
continue
except RequestException as e:
print(f"Request error: {e}")
return None
return None
# Using the function
data = make_request_with_retry('https://api.example.com/data')
if data:
print(f"Got data: {data}")# Quick reference
STATUS_CODES = {
# 2xx Success
200: 'OK - Request succeeded',
201: 'Created - New resource created',
204: 'No Content - Success with no body',
# 3xx Redirection
301: 'Moved Permanently',
304: 'Not Modified - Use cached version',
# 4xx Client Error
400: 'Bad Request - Invalid format',
401: 'Unauthorized - Auth required',
403: 'Forbidden - No permission',
404: 'Not Found - Resource missing',
409: 'Conflict - Duplicate or state conflict',
429: 'Too Many Requests - Rate limited',
# 5xx Server Error
500: 'Internal Server Error',
502: 'Bad Gateway',
503: 'Service Unavailable'
}
# Use in your code
def explain_status(code):
return STATUS_CODES.get(code, f'Unknown status {code}')
print(explain_status(404)) # Not Found - Resource missing| Code Range | Meaning | Action |
|---|---|---|
| 2xx | Success | Use the data, continue |
| 3xx | Redirection | Follow the new URL |
| 4xx | Client Error | Fix the request |
| 5xx | Server Error | Retry later |
| 200 | OK | Request succeeded perfectly |
| 201 | Created | New resource successfully made |
| 204 | No Content | Success, no body to parse |
| 400 | Bad Request | Check your data format |
| 401 | Unauthorized | Add authentication |
| 403 | Forbidden | You lack permission |
| 404 | Not Found | Resource doesn't exist |
| 429 | Rate Limited | Wait before retrying |
| 500 | Server Error | Server problem, not yours |
Learn how to serialize and work with JSON data in your Python applications.
Ready to practice? Try challenges or explore resources
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep • Build Real • Verify Skills • Launch Forward