4 comments

[ 3.1 ms ] story [ 23.5 ms ] thread
Author here. I forked Requests in mid-2023 because it's effectively frozen, and Python's HTTP capabilities have fallen far behind what the protocols and the ecosystem allow today. The Requests API is great; I didn't want to replace it, I wanted to catch it up.

Three years later, here's where things stand:

HTTP/2 by default, HTTP/3 over QUIC when the server advertises it via Alt-Svc or via DNS HTTPS record. No configuration needed, the client negotiates automatically. This alone accounts for most of the performance difference in practice. A quick benchmark (1000 requests to httpbingo.org/get, reproduction steps in the README)

niquests 0.551s (HTTP/2) aiohttp 1.351s (HTTP/1.1) httpx 2.087s (HTTP/2)

Security defaults that should have been there years ago. OS trust store instead of bundled certifi. Certificate revocation checks via OCSP or CRL. Encrypted Client Hello. Post-quantum key exchange. None of this is exotic anymore - browsers have shipped most of it - but Python clients still don't do it.

DNS. DNS-over-HTTPS, DNS-over-TLS, DNS-over-QUIC, DNSSEC validation. Per-session resolver configuration.

Other things that accumulated over three years: Happy Eyeballs, WebSocket and SSE over all three HTTP versions, in-memory certificates for mTLS, connection-level telemetry (DNS/TCP/TLS timings via response.conn_info), native Unix socket support, and as of 3.18, experimental Pyodide/WASM support.

Migration is boring by design: import niquests as requests. Existing auth flows, cookie jars, .netrc, adapters - they all work. We also maintain compatibility shims for requests-mock, responses, and betamax.

Happy to discuss anything related to the project or HTTP in general.

Three years is a serious commitment for a fork. The drop-in compatibility story is what makes this viable — the biggest adoption barrier for any requests replacement is the migration cost across existing codebases. Curious how you're handling the cases where people rely on requests internals directly — things like custom HTTPAdapter subclasses or session-level hooks. Those are usually where drop-in replacements start breaking in the real world.
That feature comparison table is brutal for httpx and aiohttp. HTTP/3 over QUIC, DNSSEC, post-quantum, and still 4x faster than httpx? How stable has QUIC negotiation been with the big CDNs in practice?