If you’ve used Requests, then you’ve probably felt its limits the moment you needed to fire off a batch of API calls at once or keep one stalled server from freezing your script. HTTPX2, the Pydantic-maintained fork of Python HTTPX, keeps the Requests-style API you know while adding asynchronous requests, sensible default timeouts, and HTTP/2. In this tutorial, you’ll learn how to move from Requests to HTTPX2.
By the end of this tutorial, you’ll understand that:
- A reusable
Clientpools connections instead of opening a new one per request. AsyncClienthandles concurrent requests withasyncio.- Granular timeouts and a clear exception hierarchy make failures predictable.
- Streaming processes large responses without ever loading them fully into memory.
- HTTP/2 costs one extra dependency and one argument.
To get the most out of this tutorial, you should be comfortable making basic requests with Requests and working with dictionaries, with statements, and exceptions. You don’t need prior experience with asyncio, since you’ll learn what you need along the way.
To follow along, you’ll want a working Python 3.10 or newer environment. Start by creating and activating a virtual environment, so that the packages you install stay isolated from the rest of your system:
The (.venv) prefix in the prompt confirms that the environment is active, and installing both libraries into it lets you compare them side by side.
If you want to explore the code examples from this tutorial, then you can download them here:
Get Your Code: Click here to download the free HTTPX2 sample code that shows you how to make HTTP requests in Python with HTTPX2.
Take the Quiz: Test your knowledge with our interactive “Python HTTPX: Making HTTP Requests With HTTPX2” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
Python HTTPX: Making HTTP Requests With HTTPX2Test your knowledge of Python HTTPX2 by reusing clients, sending async requests, setting timeouts, streaming responses, and enabling HTTP/2.
Before you write your first request, it’s worth taking a quick look at where HTTPX2 comes from, since that explains a few names you’ll run into later.
Meet HTTPX2, the Fork of Python HTTPX
The Python ecosystem has evolved considerably since Requests was designed in 2011. The original HTTPX project was kicked off in 2019 to bridge the gaps that Requests left behind. In 2026, Pydantic forked it as HTTPX2, picking up stewardship so that the library has a reliably maintained path forward.
HTTPX and HTTPX2 are separate packages rather than one renamed project: they install under different names, import differently, and can sit side by side in the same environment without conflicting.
HTTPX2 keeps the same public API, so most code moves across unchanged. A few things did shift in the fork: the command-line tool and the underlying httpcore package were renamed, Python 3.9 support was dropped, and TLS verification now uses your operating system’s trust store instead of a bundled certificate list.
That last change helps if you work behind a corporate proxy that inspects TLS traffic: as long as your company’s root certificate is installed in your operating system, HTTPX2 trusts it without any extra configuration. This tutorial refers to HTTPX2 throughout, but almost everything you’ll learn applies equally well to code you’ve already written with HTTPX.
The appeal of HTTPX2 is a developer-friendly API backed by powerful infrastructure. By standardizing on HTTPX2, you get a single tool that can handle both lightweight synchronous scripts and demanding, high-concurrency async workloads.
Replace One-Off Requests With a Reusable Client
In this section, you’ll start with a familiar one-off request, then move to a reusable client that shares connections and settings across calls, and finish by sending data to a server. Along the way, you’ll see how each step maps onto code you may already have written with Requests.
Make Your First Request
The quickest way to get started with HTTPX2 is to make a basic GET request:
first_request.py
import httpx2
response = httpx2.get("https://api.github.com/events")
print(response.status_code)
print(response.json())
The output from this code is shown below:
$ python first_request.py
200
[{'id': '19412078592', 'type': 'PushEvent', 'actor': {...}, ...}, ...]