State of client side HTTP in python

I'm developing a small package for writing typed Web API clients, similar to Uplink, only compatible with OpenAPI (lapidary). I use these clients mostly in Web servers, so I decided to make it async. So far I've settled on HTTPX, but I want to keep tabs on available python packages.

urllib.request

See also The Requests package is recommended for a higher-level HTTP client interface.

It accepts request headers only as a dict, and I've decided that it doesn't count as support for HTTP

❌ HTTP/1.1 ❌ HTTP/2 ❌ HTTP/3 ❌ asyncio

urllib3

Fast and robust, slowly acquiring HTTP/2 support, but only sync.

✅ HTTP/1.1 ❌ HTTP/2 ❌ HTTP/3 ❌ asyncio

requests

This the one every python example tells you to use. It's under a feature freeze since forever – HTTP moves on but requests is as perfect as possible. It also “broke the internet” when it moved to urllib3 2.0.0, which dropped support for older TLS algorithms, in a minor version release. As long as the API doesn't change in an incompatible way, right?

✅ HTTP/1.1 ❌ HTTP/2 ❌ HTTP/3 ❌ asyncio

pycURL

It's super fast, since it's super thin wrapper over libcURL.

Also a great showcase of how not to write python wrappers. Might as well use ctypes.

✅ HTTP/1.1 ✅ HTTP/2 ✅ HTTP/3 (I think it's supported, libcURL says it's experimental) ❌ asyncio but non-blocking, since it's a native code.

HTTPX

The most popular async HTTP client package for python. Supports HTTP/2 but claims it's “not as robust” as 1.1. Both sync and async.

API is mostly compatible with requests (it's not a feature). Depending on usage pattern, it's slightly slower or much slower than aiohttp.

✅ HTTP/1.1 ✅ HTTP/2 (discouraged, opt-in) ❌ HTTP/3 ✅ sync & async

aiohttp

API is close to the protocol, so a bit more complex than alternatives, but I like it. One of the fastest packages in python.

The community seems more focused on the server side (more features and plugins).

✅ HTTP/1.1 ❌ HTTP/2 ❌ HTTP/3 ✅ asyncio-only

Aiosonic

Looks and feels like HTTPX.

Depending on usage pattern, it's either a bit slower or a bit faster than aiohttp. Probably there's something wrong with it, because nobody seems to be using it. Definitely worth a closer look.

✅ HTTP/1.1 ✅ HTTP/2 – beta ❌ HTTP/3 ✅ sync & asyncio

Aioquic

Really low level HTTP/3 & QUIC package. Only for genuine H3 users. Could use better examples – example client has 600+ lines. Or maybe it's that hard to use...

❌ HTTP/1.1 ❌ HTTP/2 ✅ HTTP/3 ✅ asyncio-only

Niquests

Async fork of requests with HTTP/2 and 3. Fast, full featured but not user-friendly.

It uses a forked urllib3 (by the same author) that shadows it, so if you happen to have a transitive dependency on the original, it will mess up your environment. The author is fine with it. I recommend against using it.

✅ HTTP/1.1 ✅ HTTP/2 ✅ HTTP/3 ✅ sync & asyncio

Reqwest wrappers

This makes a lot of sense – Rust is a popular language, reqwest is a popular rust package, keep it DRY. None of the wrappers are widely popular, but some projects are live and definitely worth watching. – gufo-http – I think it's the oldest and still maintained – pyreqwesthttpr

Found a few more, just search reqwest in pypi.

✅ HTTP/1.1 ✅ HTTP/2 ❌ HTTP/3 – maybe, it's still experimental in reqwest ✅ sync and asyncio

Conclusion

Honestly, the clients for the protocol that makes the Web makes me wonder is Python still alive? There isn't a single popular and stable package with HTTP/2 (2015!) or HTTP/3 (2022) either sync or async. Is Python only for Django and LLM? Have everyone else switch to Rust and/or Deno?

CC BY-NC-SA 4.0