What are HTTP Status Codes?¶
HTTP status codes are numerical codes returned by the server to the client to indicate the result of a request. For example, “200” means the request was successful, and “404” means the requested resource does not exist. In FastAPI, properly setting status codes helps API clients (such as front-ends or other services) accurately understand request results, which is fundamental for building robust APIs.
How to Set Status Codes in FastAPI?¶
FastAPI provides two common ways to set status codes:
1. Specify directly when returning from the route function: Return a tuple (data, status_code).
2. Use the HTTPException exception: Raise an exception with a status code and error message (recommended for error scenarios).
Example code (comparison of two methods):
from fastapi import FastAPI, HTTPException
app = FastAPI()
# Method 1: Return a tuple directly
@app.get("/hello")
def say_hello():
return {"message": "Hello"}, 200 # Returns 200 OK
# Method 2: Raise HTTPException (for error scenarios)
@app.get("/users/{user_id}")
def get_user(user_id: int):
if user_id != 1:
raise HTTPException(
status_code=404,
detail="User not found"
)
return {"user_id": user_id, "name": "Alice"}
Common Status Codes and Usage Scenarios¶
Here are the most commonly used status codes for beginners, with simple examples for understanding:
1. 200 OK: Request Successful¶
Scenario: Returned when GET/POST/PUT requests are processed successfully, returning specific data or results.
Example: Querying existing user information:
fake_users_db = {1: {"name": "Alice"}, 2: {"name": "Bob"}}
@app.get("/users/{user_id}")
def get_user(user_id: int):
if user_id in fake_users_db:
return fake_users_db[user_id] # Automatically returns 200 OK
raise HTTPException(status_code=404, detail="User not found") # Returns 404 if not found
2. 404 Not Found: Resource Does Not Exist¶
Scenario: Returned when the requested resource (e.g., ID, path) does not exist, common in GET/DELETE requests when the target cannot be found.
Example: Requesting a non-existent user ID:
@app.get("/users/{user_id}")
def get_user(user_id: int):
if user_id not in fake_users_db:
return {"error": "User not found"}, 404 # Returns 404
return fake_users_db[user_id]
3. 500 Internal Server Error: Server Internal Error¶
Scenario: Returned when server-side issues occur (e.g., code errors, database connection failures). Avoid exposing details to users; instead, catch exceptions and return friendly messages.
Bad Example (avoid):
@app.get("/crash")
def crash():
1 / 0 # Intentionally creates an error; FastAPI returns 500 by default (but should be caught!)
Correct Handling: Use try-except to catch errors and return specific codes like 400:
from fastapi import HTTPException
@app.get("/divide")
def divide(a: float, b: float):
try:
return a / b
except ZeroDivisionError:
raise HTTPException(status_code=400, detail="Divisor cannot be zero")
4. 201 Created: Resource Created Successfully¶
Scenario: Returned when a POST request successfully creates a new resource (e.g., adding a user or product), and the new resource’s information should be returned.
Example: Creating a new user:
@app.post("/users")
def create_user(new_user: dict): # Assume receiving new user data
new_id = 3 # New ID in the database
created_user = {"id": new_id, **new_user}
return created_user, 201 # Returns 201 and the created user
5. 204 No Content: No Content to Return¶
Scenario: Returned when a DELETE/PUT request succeeds but no data needs to be returned (e.g., after deleting a resource), only the status code is returned.
Example: Deleting a user:
from fastapi import status
@app.delete("/users/{user_id}")
def delete_user(user_id: int):
if user_id in fake_users_db:
del fake_users_db[user_id]
return {"message": "User deleted"}, status.HTTP_204_NO_CONTENT # 204 No Content
raise HTTPException(status_code=404, detail="User not found")
6. 400 Bad Request: Invalid Request Parameters¶
Scenario: Returned when request parameters are invalid (e.g., missing required fields, incorrect format).
Example: Submitting a negative price (validated by Pydantic model):
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
@app.post("/items")
def create_item(item: Item):
if item.price < 0:
raise HTTPException(status_code=400, detail="Price cannot be negative")
return item, 201
7. 401 Unauthorized / 403 Forbidden¶
- 401: Unauthenticated (user not logged in).
Example: Accessing a login-required interface:
from fastapi import Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
async def get_current_user(token: str = Depends(oauth2_scheme)):
if not token: # Assume no token means unauthenticated
raise HTTPException(status_code=401, detail="Unauthorized")
@app.get("/profile")
def get_profile(user=Depends(get_current_user)):
return {"message": "Logged in"}
- 403: Authenticated but insufficient permissions (e.g., a regular user accessing an admin interface).
Example: A regular user accessing an admin interface:
async def get_admin_role(user: dict = Depends(get_current_user)):
if user.get("role") != "admin":
raise HTTPException(status_code=403, detail="Insufficient permissions")
@app.get("/admin")
def admin_route(user=Depends(get_admin_role)):
return {"message": "Admin data"}
Best Practices: Status Code Conventions for Different HTTP Methods¶
- GET: For querying data; return 200 on success, 404 (resource not found) or 400 (parameter error) on failure.
- POST: For creating resources; return 201 on success, 400 on parameter errors.
- PUT/PATCH: For updating resources; return 200 or 204 on success, 400/404 on failure.
- DELETE: For deleting resources; return 204 on success, 404 on failure.
Summary¶
Status codes are the “language” of APIs. Proper usage ensures clients clearly understand request results. FastAPI simplifies status code setup with the status_code parameter and HTTPException. Beginners should focus on core codes like 200 (success), 404 (resource not found), 500 (server error), 201 (created), and 400 (parameter error) to avoid confusion for front-ends or downstream services.
(Note: FastAPI’s auto-generated Swagger documentation displays route status codes, making it easy to debug by directly viewing defined status codes in the docs.)