HTTP client comparison
Generated 2026-09-08 by workflow run against the latest release of every library.
400 requests per cell against a local uvicorn server with gzip responses; wall-clock seconds, lower is better.
Absolute numbers depend on the GitHub runner, so compare rows, not weeks.
See also the httpr performance trend and the
benchmark source.

Sync, one client reused
| name |
wall 200k |
wall 50k |
wall 5k |
cpu 200k |
cpu 50k |
cpu 5k |
| httpr 4c601a5 |
0.48 |
0.22 |
0.13 |
0.37 |
0.11 |
0.03 |
| pycurl 7.47.0 |
0.65 |
0.27 |
0.13 |
0.52 |
0.15 |
0.03 |
| curl_cffi 0.16.3 |
0.72 |
0.34 |
0.22 |
0.61 |
0.22 |
0.10 |
| httpx2 2.12.0 |
0.78 |
0.38 |
0.24 |
0.64 |
0.26 |
0.13 |
| httpx 0.28.1 |
0.82 |
0.37 |
0.28 |
0.69 |
0.27 |
0.17 |
| requests 2.34.2 |
0.93 |
0.52 |
0.37 |
0.81 |
0.39 |
0.25 |
| tls_client 1.0.1 |
1.30 |
0.52 |
0.28 |
1.41 |
0.47 |
0.19 |
Sync, new client per request
| name |
wall 200k |
wall 50k |
wall 5k |
cpu 200k |
cpu 50k |
cpu 5k |
| httpr 4c601a5 |
0.57 |
0.30 |
0.20 |
0.42 |
0.16 |
0.07 |
| pycurl 7.47.0 |
0.73 |
0.34 |
0.19 |
0.57 |
0.19 |
0.06 |
| curl_cffi 0.16.3 |
0.83 |
0.43 |
0.30 |
0.67 |
0.28 |
0.15 |
| httpx2 2.12.0 |
0.96 |
0.58 |
0.55 |
0.84 |
0.46 |
0.42 |
| requests 2.34.2 |
1.02 |
0.61 |
0.45 |
0.88 |
0.45 |
0.31 |
| tls_client 1.0.1 |
1.40 |
0.64 |
0.39 |
1.54 |
0.60 |
0.31 |
| httpx 0.28.1 |
5.90 |
5.49 |
5.39 |
5.77 |
5.36 |
5.27 |
Async, one client reused
| name |
wall 200k |
wall 50k |
wall 5k |
wall json/10?gzip=false |
wall json/10?gzip=true |
wall json/1?gzip=false |
wall json/1?gzip=true |
cpu 200k |
cpu 50k |
cpu 5k |
cpu json/10?gzip=false |
cpu json/10?gzip=true |
cpu json/1?gzip=false |
cpu json/1?gzip=true |
| httpr 4c601a5 |
0.24 |
0.13 |
0.14 |
0.30 |
0.36 |
0.12 |
0.12 |
0.61 |
0.21 |
0.13 |
0.38 |
0.70 |
0.12 |
0.15 |
| aiohttp 3.14.3 |
0.55 |
0.23 |
0.17 |
0.21 |
0.43 |
0.43 |
0.19 |
0.54 |
0.22 |
0.11 |
0.16 |
0.42 |
0.12 |
0.14 |
| curl_cffi 0.16.3 |
0.63 |
0.24 |
0.13 |
0.85 |
1.14 |
0.19 |
0.22 |
0.63 |
0.24 |
0.12 |
0.82 |
1.12 |
0.19 |
0.22 |
| httpx2 2.12.0 |
0.77 |
0.36 |
0.23 |
1.02 |
1.28 |
0.28 |
0.31 |
0.77 |
0.34 |
0.22 |
1.02 |
1.28 |
0.28 |
0.31 |
| httpx 0.28.1 |
2.55 |
2.07 |
1.96 |
2.82 |
3.03 |
2.02 |
2.06 |
2.55 |
2.07 |
1.96 |
2.82 |
3.03 |
2.00 |
2.06 |
32 threads, one client reused
| name |
wall 200k |
wall 50k |
wall 5k |
cpu 200k |
cpu 50k |
cpu 5k |
| httpr 4c601a5 |
0.23 |
0.12 |
0.11 |
0.58 |
0.15 |
0.06 |
| httpx2 2.12.0 |
0.44 |
0.24 |
0.21 |
0.89 |
0.37 |
0.25 |
| pycurl 7.47.0 |
0.46 |
0.13 |
0.09 |
1.15 |
0.21 |
0.04 |
| tls_client 1.0.1 |
0.61 |
0.26 |
0.13 |
1.69 |
0.60 |
0.19 |
| curl_cffi 0.16.3 |
0.62 |
0.31 |
0.21 |
1.33 |
0.56 |
0.33 |
| requests 2.34.2 |
0.85 |
0.42 |
0.31 |
1.38 |
0.56 |
0.34 |
| httpx 0.28.1 |
1.11 |
0.89 |
0.82 |
3.51 |
2.98 |
2.79 |
Raw data:
session=True.csv,
session=False.csv,
session='Async'.csv,
threads.csv,
comparison.md.