Headers and Cookies
20 min · Intermediate
Need help? Ask a tutor on WhatsApp (opens in a new tab)The method and the path are only part of a request. Headers carry the rest: what format the data is in, who is asking, and what the client remembers. Cookies are headers that let a server recognise the same visitor again.
Headers are labelled extra information
Header is a name and value pair sent with a request or response that describes the message, such as its format, its size, who is asking, or how long it may be cached.
A header is a line of the form Name: value. Names are not case sensitive, and the same name may appear twice. Both requests and responses have headers.
import httpx
h = httpx.Headers({"Content-Type": "application/json"})print(h["content-type"])print("CONTENT-TYPE" in h)Example 1 · Header names ignore case
import httpx
h = httpx.Headers([("Accept", "application/json"), ("X-Tag", "a"), ("X-Tag", "b")])print(h["ACCEPT"])print(h.get_list("x-tag"))print(sorted(h.keys()))application/json ['a', 'b'] ['accept', 'x-tag']
What this code does
- Lookups work with any letter case.
- A name may appear twice;
get_listreturns every value.
httpx treats header names without caring about letter case, just like real servers do.
The headers you meet every day
Content-Type says what the body is. Accept says what the client wants back. Authorization carries credentials. User-Agent names the client program. Cache-Control says how long a response may be reused.
from email.message import Message
msg = Message()msg["Content-Type"] = "application/json; charset=utf-8"print(msg.get_content_type())print(msg.get_param("charset"))Example 2 · Content-Type and Authorization
from email.message import Message
msg = Message()msg["Content-Type"] = "application/json; charset=utf-8"print(msg.get_content_type(), msg.get_param("charset"))
auth = "Bearer abc.def.ghi"scheme, token = auth.split(" ", 1)print(scheme)print(token.count("."))application/json utf-8 Bearer 2
What this code does
- The media type and its parameters are separated for you.
- The word before the first space is the scheme; the rest is the token.
A media type such as application/json can have parameters after a semicolon. The standard library can split them for you.
Cookies remember the visitor
Cookie is a small named value that a server asks the client to store with Set-Cookie. The client sends it back in the Cookie header on later requests, so the server can recognise the same visitor.
HTTP forgets every request as soon as it ends. A server fixes this by sending Set-Cookie. The client stores the value and sends it back in a Cookie header on every later request to that site.
from http.cookies import SimpleCookie
jar = SimpleCookie()jar.load("theme=dark; session=abc123")print(jar["theme"].value)print(sorted(jar))Example 3 · Read a Cookie header
from http.cookies import SimpleCookie
jar = SimpleCookie()jar.load("theme=dark; session=abc123; lang=en")for name, morsel in jar.items(): print(name, "=", morsel.value)print("session" in jar)theme = dark session = abc123 lang = en True
What this code does
- Each cookie becomes a
Morselwhose.valueis the text you stored. - Order follows the order in the header.
SimpleCookie parses a Cookie header into named values.
Cookie flags protect the cookie
A session cookie is as good as a password, so flags matter. HttpOnly hides it from page scripts. Secure sends it only over HTTPS. SameSite limits sending from other sites. Max-Age sets its life in seconds.
from http.cookies import SimpleCookie
c = SimpleCookie()c["session"] = "abc123"c["session"]["httponly"] = Truec["session"]["max-age"] = 3600print(c.output())Example 4 · Build a Set-Cookie line
from http.cookies import SimpleCookie
c = SimpleCookie()c["session"] = "abc123"c["session"]["httponly"] = Truec["session"]["secure"] = Truec["session"]["samesite"] = "Lax"c["session"]["max-age"] = 3600print(c.output())Set-Cookie: session=abc123; HttpOnly; Max-Age=3600; SameSite=Lax; Secure
What this code does
- The flags decide how safe the cookie is in a browser.
Max-Ageis in seconds, so 3600 is one hour.
Example 5 · Headers and cookies in a FastAPI app
from fastapi import FastAPI, Cookie, Header, Responsefrom fastapi.testclient import TestClient
app = FastAPI()
@app.get("/visit")def visit(response: Response, visits: int = Cookie(default=0), x_client: str = Header(default="unknown")): visits += 1 response.set_cookie("visits", str(visits), httponly=True) return {"visits": visits, "client": x_client}
client = TestClient(app)print(client.get("/visit").json())print(client.get("/visit").json())r = client.get("/visit", headers={"X-Client": "mobile"})print(r.json())print(r.headers["set-cookie"]){'visits': 1, 'client': 'unknown'}
{'visits': 2, 'client': 'unknown'}
{'visits': 3, 'client': 'mobile'}
visits=3; HttpOnly; Path=/; SameSite=laxWhat this code does
- The test client keeps cookies between calls, like a browser does.
- FastAPI reads a header by its name with dashes turned into underscores.
The printed line is exactly what a server sends in the response. Without Max-Age, the cookie lasts until the browser closes.
Next step
Check your understanding
12 quick questions