Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
For most Python applications that need to make HTTP/2 requests, start with HTTPX. Install its optional HTTP/2 dependency and enable the feature on a synchronous or asynchronous client. Use h2 instead when you need to build or control the protocol layer yourself; consider curl_cffi when you want libcurl-backed HTTP/2 and HTTP/3 or a requests-like interface.
One important distinction: enabling HTTP/2 in a client does not guarantee that a particular request uses it. The server must support the protocol, and the negotiated version should be checked on the response.
Which Python HTTP/2 library should you choose?
The right choice depends on how much of the networking stack you want the library to handle. HTTPX is a high-level HTTP client: it gives you familiar request and response objects, sync and async APIs, and an option to enable HTTP/2. By contrast, h2 is a protocol implementation without its own I/O layer. It is a foundation for building a client, server, proxy, or test harness—not a direct replacement for HTTPX when you simply need to call an API.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemscurl_cffi is another high-level option, backed by libcurl-impersonate. Its documented capabilities include HTTP/2 and HTTP/3, synchronous and asynchronous interfaces, a requests-like API, and optional browser TLS-fingerprint impersonation. The python-hyper project offers lower-level components that can be assembled into custom stacks.
#1 Best Overall
| Library | Abstraction | Sync and async | Transport and protocol control | HTTP/3 | Good fit |
|---|---|---|---|---|---|
| HTTPX | High-level HTTP client | Both | Client configuration; less protocol-level control than a protocol stack | Not stated in the cited HTTPX documentation | Ordinary application API calls |
h2 (hyper-h2) |
HTTP/2 protocol stack; no I/O layer | Not applicable as a ready-made client API | High; the wrapper supplies I/O and event-loop integration | Not stated | Custom transports, servers, proxies, or protocol tests |
| python-hyper components | Composable protocol and networking building blocks | Depends on the components and wrapper | High; select and integrate components for your stack | Not stated | Custom stacks built around an existing transport or framework |
curl_cffi |
High-level libcurl-backed client | Both | Uses libcurl behavior and provides a requests-like API | Yes, according to its documentation | libcurl, HTTP/3, or requests-style compatibility needs |
These are differences in purpose, not a performance ranking. The authoritative documentation summarized here does not establish comparative benchmark results, so choose based on API ergonomics, protocol needs, and the transport model your application requires.
Enable HTTP/2 in HTTPX
HTTPX supports HTTP/1.1 and HTTP/2, but HTTP/2 support is not enabled by default. Install the optional extra so the HTTP/2 dependency is available, then set http2=True on the client instance. The same option is available on both the synchronous and asynchronous client classes.
Install the optional dependency
python -m pip install 'httpx[http2]'
The quoted extra works in shells that treat square brackets specially. If your environment uses a different Python interpreter or virtual environment, run the command with that environment’s Python so the package is installed where your application runs.
Free tools Windows power users keep installed
One-click scans. No signup required.
Synchronous client
import httpx
url = "https://example.com/"
with httpx.Client(http2=True) as client:
response = client.get(url)
response.raise_for_status()
print("Negotiated protocol:", response.http_version)
print(response.text[:500])
The context manager closes the client when the block ends. For an API, replace the example URL with the endpoint you need and process the response according to that API’s expected content type and status codes.
Rank #2
Asynchronous client
import asyncio
import httpx
async def main():
url = "https://example.com/"
async with httpx.AsyncClient(http2=True) as client:
response = await client.get(url)
response.raise_for_status()
print("Negotiated protocol:", response.http_version)
print(response.text[:500])
asyncio.run(main())
Use the async client in an asynchronous application and await its request methods. It is not necessary to switch to h2 merely because your application uses asyncio: HTTPX provides an async high-level client.
Confirm whether a request actually used HTTP/2
http2=True allows HTTPX to negotiate HTTP/2; it is not a command to force every server to use it. The server must support HTTP/2 for the connection to use that protocol. If it does not, HTTPX can use HTTP/1.1 instead. Inspect response.http_version for the protocol used by the response. The documented values include HTTP/2 and HTTP/1.1; another supported version may also be reported.
For troubleshooting, log the value for the response you are investigating rather than assuming that a client-wide setting proves what happened on the wire:
print(response.http_version)
That check answers a narrower and more useful question than “does this Python library support HTTP/2?”: it tells you the negotiated version for this response. A fallback to HTTP/1.1 is not, by itself, evidence that the client configuration failed.
When to use h2 instead of HTTPX
The package commonly called h2 is hyper-h2, a pure-Python HTTP/2 protocol stack. Its key architectural difference is that it performs no I/O. Your application or a wrapper must provide the transport, move bytes over that transport, and integrate the protocol state machine with the event loop or concurrency model you use.
That separation can be valuable if you are writing a specialized client or server, a proxy, a protocol-focused test harness, or software that must fit an unusual transport or concurrency design. It also means you take responsibility for substantially more networking work than when using HTTPX. If your need is simply to send a request and read a response, the low-level protocol interface is usually the wrong starting point.
The project documentation describes h2 as “a HTTP/2 protocol stack, written entirely in Python” and notes that it does no I/O. Treat that distinction literally: a protocol stack is not automatically a complete network client. You need a suitable wrapper or your own transport integration before it can communicate with a remote server.
What the python-hyper project provides
python-hyper is a toolbox of components, not one batteries-included HTTP client. Its listed pieces cover different layers and related protocol needs:
- hyper-h2 (
h2): the HTTP/2 protocol state machine. - hyperframe: HTTP/2 framing.
- hpack: HPACK header compression.
- brotlipy: Brotli support.
- priority: HTTP/2 priority trees.
- wsproto: WebSockets.
Choose a component when you know which layer you need to supply or extend, especially when composing around an existing transport or framework. These parts do not collectively turn into a one-line substitute for a high-level HTTP client; the integration remains part of your application’s design.
When curl_cffi may be a better fit
curl_cffi binds Python to libcurl-impersonate and documents HTTP/2 and HTTP/3 support, sync and async interfaces, and a requests-like API. That combination makes it worth evaluating if your project needs libcurl’s behavior, wants HTTP/3 as well as HTTP/2, or already uses a requests-style calling pattern.
It is a different trade-off from HTTPX: curl_cffi is backed by a native library rather than being the same kind of high-level Python client. If native-library and deployment requirements matter in your environment, check that your chosen installation and runtime setup support them before committing. The cited facts establish the library’s libcurl basis and features, but do not establish a universal winner for compatibility or speed.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchChoose by application need, not by protocol label
- Calling web APIs in ordinary application code: start with HTTPX. Use the sync or async client that matches the rest of the application.
- Implementing or testing HTTP/2 protocol behavior: use
h2when you need the protocol state machine and are prepared to provide I/O integration. - Assembling a specialized stack: inspect the python-hyper components and include only the pieces your transport or framework needs.
- Needing libcurl, HTTP/3, or requests-like ergonomics: evaluate
curl_cffi.
There is no performance figure here that can responsibly settle the choice. Application behavior depends on the service, connection reuse, workload, and deployment; use measurements from your own representative workload if throughput or latency is a deciding factor.
Best Value
Troubleshoot common HTTP/2 setup problems
HTTPX reports HTTP/1.1
Cause: the remote server did not negotiate HTTP/2 for that request, or the request used a client without HTTP/2 enabled. Fix: confirm the request was made through a client created with http2=True, verify the optional dependency was installed in the active environment, and inspect response.http_version again. If configuration is correct, HTTP/1.1 may simply be the protocol available from that server.
Import or dependency errors after installation
Cause: the HTTP/2 extra may not have been installed, or pip may have installed HTTPX into a different environment from the one running the program. Fix: use python -m pip install 'httpx[http2]' with the interpreter for the project, then run the program in that same virtual environment.
Expecting h2 to make a network request by itself
Cause: h2 implements protocol behavior but does not perform I/O. Fix: use a wrapper that provides transport integration, or select a high-level client such as HTTPX if you do not need to own the protocol and transport layers.
Trying to force HTTP/2 against an unsupported endpoint
Cause: a client option cannot make a server speak a protocol it does not support. Fix: check the negotiated response version and use the protocol the endpoint offers; when the server supports HTTP/2, make sure the client is configured to enable it.
ScreenshotNeo for a different task: capturing web pages
ScreenshotNeo is not an HTTP/2 Python library or a replacement for HTTPX, h2, python-hyper, or curl_cffi. If your actual goal is to capture a website as an image or PDF rather than build an HTTP client, it is a separate option: a website screenshot API and MCP server for developers. Its documented features include accepting cookie or consent banners and removing more than 60 known consent platforms, newsletter popups, and chat widgets before capture; those steps can be turned off. Only clean shots are billed: bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and responses identify the page verdict and billing status in headers. It also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for AI agents.
The API supports a GET request with a URL to return a PNG, JPEG, WebP, or PDF. For available parameters and usage details, see ScreenshotNeo’s API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Plans include 1,000 shots per month free with no card, then paid options starting at $5 for 3,000 shots; the stated plans include all features. See ScreenshotNeo for the service and sign up for 1,000 free screenshots a month with no card.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

