Any program that makes more than a few requests should use a client for speed and consistent configuration.
httpx.Client is the equivalent of requests.Session, but it is the primary interface in HTTPX rather than an optional extra. A client:
- keeps a connection pool, so repeated requests to a host reuse TCP and TLS connections,
- holds shared configuration:
base_url,headers,params,cookies,auth,timeout,follow_redirects,event_hooks,limits,verify,proxy,transport, - persists cookies across requests.
base_url is a big convenience for API clients: client.get("/users/1") resolves against it. Relative paths are merged onto the base URL's path, so with base_url="https://api.example.com/v2" a request to /users goes to /v2/users.
Configuration is merged: per-request headers and params are added to the client's, with request values winning. Unlike Requests, a client-level timeout is a real setting.
Always close clients. The idiom is a with block:
with httpx.Client(base_url=..., timeout=10) as client:
...or call client.close() explicitly. In long-running applications, create one client at start-up and share it (for example, in a FastAPI lifespan handler or as an attribute of your service class), rather than creating one per request, which defeats pooling.
Client headers and other settings can also be modified after creation, e.g. client.headers["Authorization"] = ... after logging in.
Example
import httpx
with httpx.Client(
base_url="https://httpbin.org",
headers={"User-Agent": "inventory-client/2.0"},
params={"api_key": "k1"},
timeout=10.0,
follow_redirects=True,
) as client:
r = client.get("/get", params={"page": 2})
print(r.url) # https://httpbin.org/get?api_key=k1&page=2
print(r.json()["headers"]["User-Agent"]) # inventory-client/2.0
client.get("/cookies/set", params={"session": "abc"})
print(client.cookies["session"]) # abc
r = client.get("/redirect/1")
print(r.status_code, r.url.path) # 200 /get
print(client.is_closed) # TrueRemember
- Client = connection pool + shared configuration
- base_url lets you write client.get('/path')
- Create one long-lived client and close it with a with block
Watch out for
- Creating a new Client inside every function call, losing connection reuse.