ConfigsApr 14, 2026·3 min read

HTTPX — The Next-Generation HTTP Client for Python

HTTPX provides the ergonomics of requests with the power of async, HTTP/2, and strict type safety. The same API works in sync and async code, making it the go-to client for modern Python applications.

TL;DR
HTTPX combines the requests-like API with async support, HTTP/2, and type safety for modern Python.
§01

What it is

HTTPX is a Python HTTP client that provides the familiar API of the requests library with added support for async/await, HTTP/2, and strict type annotations. The same httpx.Client API works in both synchronous and asynchronous contexts, making it the go-to HTTP client for modern Python applications that need to evolve from sync to async.

HTTPX targets Python developers building API clients, web services, scrapers, or microservice integrations who want a requests-compatible API with modern protocol support.

§02

How it saves time or tokens

Migrating from requests to an async HTTP client traditionally meant learning a different API (aiohttp). HTTPX uses the same method names and patterns as requests, so the migration is mechanical. Adding HTTP/2 support is a single flag (http2=True). You get connection pooling, automatic redirect handling, and cookie persistence without extra setup.

§03

How to use

  1. Install HTTPX: pip install httpx (add httpx[http2] for HTTP/2 support).
  2. For sync code, use httpx.get() or create a httpx.Client() for connection pooling.
  3. For async code, use async with httpx.AsyncClient() as client: and await client.get().
§04

Example

import httpx
import asyncio

# Synchronous usage (drop-in requests replacement)
r = httpx.get('https://api.github.com/users/python')
print(r.json()['public_repos'])

# Async usage
async def main():
    async with httpx.AsyncClient(http2=True) as client:
        r = await client.get('https://httpbin.org/get')
        print(r.http_version)  # HTTP/2
        print(r.status_code)

asyncio.run(main())

# Connection pooling with a persistent client
with httpx.Client(base_url='https://api.example.com') as client:
    users = client.get('/users').json()
    posts = client.get('/posts').json()
§05

Related on TokRepo

§06

Common pitfalls

  • Creating a new httpx.Client() per request instead of reusing it. Each client manages its own connection pool and TLS sessions.
  • Forgetting to install httpx[http2] for HTTP/2 support. The base package only includes HTTP/1.1.
  • Using httpx.get() (module-level) in performance-critical code. Module-level functions create a temporary client each call. Use a persistent Client instance instead.

Frequently Asked Questions

How does HTTPX compare to requests?+

HTTPX provides the same API as requests but adds async support, HTTP/2, strict type annotations, and a more modern codebase. For synchronous code, HTTPX is a near-drop-in replacement. The main difference is that HTTPX requires explicit client management for connection pooling, while requests uses a global session.

Does HTTPX support HTTP/2?+

Yes. Install `httpx[http2]` and pass `http2=True` to the client constructor. HTTPX negotiates HTTP/2 via ALPN during the TLS handshake. HTTP/2 multiplexes multiple requests over a single connection, reducing latency for APIs that support it.

Can HTTPX stream responses?+

Yes. Use `client.stream('GET', url)` to get a streaming response. You can iterate over chunks with `async for chunk in response.aiter_bytes()` or `aiter_lines()`. This is essential for downloading large files or processing server-sent events.

Is HTTPX compatible with requests middleware?+

HTTPX has its own middleware system based on transports and event hooks, not requests adapters. You can add custom authentication, logging, or retry logic via event hooks (`event_hooks={'request': [...], 'response': [...]}`). The API differs from requests but is straightforward.

Does HTTPX work with pytest?+

Yes. HTTPX provides `httpx.MockTransport` for testing. You supply a handler function that returns mock responses, and the client uses it instead of making real HTTP calls. This is simpler than mocking at the socket level and integrates cleanly with pytest fixtures.

Citations (3)

Discussion

Sign in to join the discussion.
No comments yet. Be the first to share your thoughts.

Related Assets