Introduction
HTTPX is the spiritual successor to requests. Tom Christie (creator of Django REST Framework and Starlette) built it to fix requests' long-standing gaps: no async, no HTTP/2, no connection pooling control, and no type hints. The API is instantly familiar to requests users — just replace requests with httpx.
With over 13,000 GitHub stars, HTTPX is used by OpenAI's Python SDK, FastAPI TestClient, Starlette, and almost every modern async Python app.
What HTTPX Does
HTTPX offers httpx.get() style calls, Client/AsyncClient objects with connection pooling, full HTTP/1.1 and HTTP/2 support, streaming requests and responses, file uploads with progress, proxies, retries (via transports), and MockTransport for tests — all with consistent sync/async APIs.
Architecture Overview
httpx.get(url) | async with AsyncClient() as c: await c.get(url)
\ /
\ /
[Client / AsyncClient]
connection pool
auth, cookies, base_url
|
[Transport]
HTTPTransport / MockTransport
|
httpcore (HTTP/1.1 + HTTP/2)
|
NetworkSelf-Hosting & Configuration
import httpx
client = httpx.Client(
base_url="https://api.example.com",
headers={"User-Agent": "myapp/1.0"},
timeout=httpx.Timeout(connect=5.0, read=30.0, write=30.0, pool=5.0),
limits=httpx.Limits(max_connections=100, max_keepalive_connections=20),
http2=True,
)
res = client.get("/users/me", params={"expand": "orgs"})
res.raise_for_status()
with client.stream("GET", "/large.zip") as r:
with open("large.zip", "wb") as f:
for chunk in r.iter_bytes():
f.write(chunk)
def handler(request: httpx.Request) -> httpx.Response:
return httpx.Response(200, json={"ok": True})
mock = httpx.Client(transport=httpx.MockTransport(handler))
assert mock.get("https://x").json() == {"ok": True}Key Features
- Sync and async APIs — identical shape, write either style
- HTTP/2 support — opt-in via
http2=Trueon the client - Connection pooling — reuse connections across requests
- Streaming —
.stream()iterator for large up/downloads - Strict typing — full type hints for IDE support
- Timeouts — per-phase timeouts (connect, read, write, pool)
- Transport layer — custom retries, caching, mocks via pluggable transports
- OAuth and auth flows — built-in + easy custom auth classes
Comparison with Similar Tools
| Feature | HTTPX | requests | aiohttp | urllib3 | niquests |
|---|---|---|---|---|---|
| Sync | Yes | Yes | No | Yes (low-level) | Yes |
| Async | Yes | No | Yes | No | No |
| HTTP/2 | Yes | No | Partial | No | Yes |
| Streaming | Yes | Partial | Yes | Yes | Yes |
| Type hints | Full | Partial | Full | Partial | Full |
| Learning Curve | Very Low | Very Low | Moderate | Higher | Very Low |
| Best For | Modern Python apps | Quick sync scripts | Pure async servers | Custom low-level | Requests-compatible + HTTP/3 |
FAQ
Q: Should I migrate from requests to HTTPX? A: If you need async, HTTP/2, or better type hints — yes. For one-off scripts, requests is perfectly fine.
Q: Can I reuse requests Session-style behavior?
A: Yes. httpx.Client() is the equivalent. It holds connection pool, cookies, base URL, and default headers.
Q: How do I add retries?
A: HTTPX has no built-in retries by design — use the HTTPTransport(retries=3) option or a custom transport.
Q: Does HTTPX support HTTP/3?
A: Not yet in the mainline. niquests is a drop-in fork with HTTP/3 if you need it today.
Sources
- GitHub: https://github.com/encode/httpx
- Docs: https://www.python-httpx.org
- Author: Tom Christie (Encode)
- License: BSD-3-Clause