Requests vs. HTTPX: Choosing a Python HTTP Client
requests earned its reputation honestly. For a long time, if you needed to call an API, download a file, or glue two services together in Python, requests was usually the obvious answer.
Async web frameworks, high-concurrency services, and I/O-heavy workloads changed what many teams need from an HTTP client. That's where httpx starts to matter.
This post compares requests and httpx from the point of view of a Python developer who already knows requests, wants a clear explanation of what httpx adds, and doesn't want hand-wavy "modernization" advice.
The Champion: requests
requests became the standard because it removed friction. Small API. Sensible defaults. Session when you need reuse.
- The API is small and easy to learn.
- The defaults are simple enough for scripts and internal tools.
Sessiongives you connection reuse and shared configuration without much ceremony.- The ecosystem around it is huge: tutorials, examples, blog posts, Stack Overflow answers, and third-party integrations all assume you know
requests.
For synchronous Python code, it's still a good library. A lot of production code doesn't need async support, doesn't need HTTP/2, and doesn't need a broader transport model. In those cases, requests remains a sensible choice.
That's why this comparison isn't really about replacing a bad tool. It's about recognizing where the older tool stops fitting as cleanly.
The Challenger: httpx
httpx looks familiar on purpose. The synchronous API feels close enough to requests that most Python developers can read it immediately. That compatibility is one of its best features, because it lowers the cost of trying it.
Its two biggest advantages are:
- Native
asyncandawaitsupport throughhttpx.AsyncClient - Optional HTTP/2 support on both sync and async clients
Those aren't cosmetic differences.
Async support means httpx fits naturally into frameworks like FastAPI, Starlette, and any other async application that shouldn't block the event loop on outbound network calls. HTTP/2 support means one client connection can handle multiplexed requests when the remote server supports it, which can matter for high-concurrency workloads.
You opt in with httpx.Client(http2=True) or httpx.AsyncClient(http2=True), and the server still has to support HTTP/2 for you to get it.
httpx also pushes users toward safer networking defaults. The biggest example is timeouts: requests doesn't time out unless you ask it to, while httpx enforces timeouts by default.
