HTTP headers carry metadata (auth tokens, content negotiation, tracing IDs) and cookies carry small client-side state. FastAPI reads them with Header and Cookie, and writes them through the Response object.
from fastapi import FastAPI, Header
from typing import Optional
app = FastAPI()
@app.get("/items/")
def read_items(
user_agent: Optional[str] = Header(default=None),
x_token: Optional[str] = Header(default=None),
):
return {"User-Agent": user_agent, "X-Token": x_token}
Underscores convert to hyphens automatically: the parameter user_agent reads the User-Agent header. To keep underscores literal, use Header(convert_underscores=False).
from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/download/")
def download(response: Response):
response.headers["X-Process-Time"] = "0.42"
response.headers["Content-Disposition"] = 'attachment; filename="report.csv"'
return {"status": "ok"}
Or return a JSONResponse directly when you need full control (note: then the return value of your function is ignored and the response is built manually).
from fastapi import FastAPI, Cookie, Response
app = FastAPI()
@app.get("/preferences/")
def get_preferences(session_id: Optional[str] = Cookie(default=None)):
return {"session_id": session_id}
@app.post("/set-cookie/")
def set_cookie(response: Response):
response.set_cookie(
key="session_id",
value="abc123",
httponly=True, # JavaScript cannot read it (XSS protection)
secure=True, # only sent over HTTPS
samesite="lax", # CSRF mitigation
max_age=3600,
)
return {"message": "cookie set"}
@app.delete("/unset-cookie/")
def unset_cookie(response: Response):
response.delete_cookie("session_id")
return {"message": "cookie removed"}
A: No. Header lookup is case-insensitive; declaring x_token matches X-Token, x-token, etc. The underscore-to-hyphen conversion is the only transformation applied.
A: Common causes: calling set_cookie on a locally-created JSONResponse instead of the injected Response; CORS — the frontend must use credentials: "include" and the server must set Access-Control-Allow-Credentials: true with an exact origin (wildcard * blocks cookies); or secure=True while testing over plain HTTP.
A: Authorization headers are the standard for APIs (stateless, no CSRF cookie issues). HttpOnly cookies protect against XSS but need CSRF protection. localStorage is readable by any injected script — generally avoid for tokens.
Declare Header/Cookie parameters to read metadata, and use the injected Response to set headers and cookies with secure flags. Authentication and tracing dependencies (coming in Intermediate) build exactly on these primitives.