urllib3-future: HTTP/1.1, 2, and 3 Client (Sync & Async)
urllib3.future is a powerful HTTP 1.1, 2, and 3 client with both synchronous and asynchronous interfaces, designed to be forward-looking. It provides a robust alternative to the standard urllib3 library, offering support for modern HTTP protocols and optional memory-safe TLS backends like Rustls. The project is under active and rapid development, with frequent releases.
Warnings
- gotcha Header precedence behavior was subject to confusing changes between versions 2.19.902 and 2.19.903. While the intent is for user-supplied headers to take precedence over extension defaults (e.g., for SSE), the exact behavior during this period was ambiguous due to conflicting release notes.
- gotcha `urllib3-future` is a distinct library, not a drop-in replacement or a fork of the standard `urllib3`. While it shares similar API patterns, it may introduce differences, especially around asynchronous features, HTTP/2/3, and specific connection management. Direct compatibility is not guaranteed for all `urllib3` use cases.
- gotcha The project exhibits a rapid release cadence (daily/weekly) and uses high patch version numbers (e.g., `.905`) within a `2.x` major version. This signifies active and rapid development, where minor behavioral changes or API tweaks could occur even in what appear to be 'patch' releases.
- gotcha Installing the `[rtls]` extra automatically switches the underlying TLS backend to Rustls. While Rustls is lauded for memory safety and security, it is a different implementation than OpenSSL (used by default in CPython and standard `urllib3`). This may lead to subtle behavioral differences, particularly with advanced SSL/TLS configurations or specific certificate authorities.
Install
-
pip install urllib3-future -
pip install urllib3-future[rtls]
Imports
- AsyncConnectionPool
import urllib3.future as urllib3 pool = urllib3.AsyncConnectionPool(...)
- ConnectionPool
import urllib3.future as urllib3 pool = urllib3.ConnectionPool(...)
- PoolManager
import urllib3.future as urllib3 manager = urllib3.PoolManager(...)
Quickstart
import urllib3.future as urllib3
import asyncio
import os
# Asynchronous example
async def async_example():
# No authentication needed for httpbin.org
pool = urllib3.AsyncConnectionPool("https://httpbin.org")
try:
print("\n--- Async Example ---")
resp = await pool.request("GET", "/get")
print(f"Status: {resp.status}")
# Decode data and truncate for cleaner output
print(f"Data: {resp.data.decode('utf-8')[:200]}...")
except Exception as e:
print(f"Async request failed: {e}")
finally:
await pool.close()
# Synchronous example
def sync_example():
pool = urllib3.ConnectionPool("https://httpbin.org")
try:
print("\n--- Sync Example ---")
resp = pool.request("GET", "/get")
print(f"Status: {resp.status}")
print(f"Data: {resp.data.decode('utf-8')[:200]}...")
except Exception as e:
print(f"Sync request failed: {e}")
finally:
pool.close()
# Run the examples
if __name__ == "__main__":
asyncio.run(async_example())
sync_example() # Synchronous call, not within async loop