urllib3-future 2.25.900


pip install urllib3-future

  Latest version

Released: Sep 22, 2026


Meta
Author: Andrey Petrov
Maintainer: Ahmed R. TAHRI
Requires Python: >=3.7

Classifiers

Environment
  • Web Environment
  • WebAssembly
  • WebAssembly :: WASI

Intended Audience
  • Developers

License
  • OSI Approved :: MIT License

Operating System
  • OS Independent

Programming Language
  • Python
  • Python :: 3
  • Python :: 3 :: Only
  • Python :: 3.7
  • Python :: 3.8
  • Python :: 3.9
  • Python :: 3.10
  • Python :: 3.11
  • Python :: 3.12
  • Python :: 3.13
  • Python :: 3.14
  • Python :: 3.15
  • Python :: Free Threading :: 4 - Resilient
  • Python :: Implementation :: CPython
  • Python :: Implementation :: PyPy

Topic
  • Internet :: WWW/HTTP
  • Software Development :: Libraries

urllib3.future logo

Modern HTTP. Familiar urllib3 API. Broad deployment choice.

PyPI Version Python Versions CI Downstream compatibility

urllib3.future is an independently maintained, compatibility-first fork of urllib3. It provides HTTP/1.1, HTTP/2, HTTP/3, synchronous and asynchronous APIs, multiplexing, advanced DNS resolution, and multiple TLS backends while preserving the established urllib3 programming model.

Existing urllib3 applications can adopt a modern transport stack without migrating to a different HTTP client API:

import urllib3

with urllib3.PoolManager() as pool:
    response = pool.request("GET", "https://httpbin.org/robots.txt")

print(response.status)   # 200
print(response.version)  # 11, 20, or 30
print(response.data)

Native asyncio APIs are available through the same package:

import asyncio
import urllib3


async def main() -> None:
    async with urllib3.AsyncPoolManager() as pool:
        response = await pool.request(
            "GET",
            "https://httpbin.org/robots.txt",
        )

        print(response.status)
        print(response.version)
        print(await response.data)


asyncio.run(main())

Why urllib3.future?

Upgrade the transport, not the application

urllib3 sits beneath a large part of the Python HTTP ecosystem: directly, beneath Requests, and inside cloud SDKs, database clients, automation tools, and other libraries. Migrating every integration to a different client API can be expensive and can fragment otherwise stable application code.

urllib3.future keeps the familiar API while replacing the transport with a protocol-neutral implementation capable of HTTP/1.1, HTTP/2, and HTTP/3.

Choice without fragmentation

The project does not require one HTTP generation, TLS implementation, resolver, concurrency model, or runtime. Secure defaults are provided without turning those defaults into artificial deployment limits.

  • Async.
  • Task safety.
  • Thread safety.
  • Happy Eyeballs.
  • Connection pooling.
  • Unopinionated about OpenSSL.
  • Client-side SSL/TLS verification.
  • Highly customizable DNS resolution.
  • File uploads with multipart encoding.
  • DNS over UDP, TLS, QUIC, or HTTPS. DNSSEC protected.
  • Helpers for retrying requests and dealing with HTTP redirects.
  • Automatic Keep-Alive for HTTP/1.1, HTTP/2, and HTTP/3.
  • Support for gzip, deflate, brotli, and zstd encoding.
  • Support for Python/PyPy 3.7+, no compromise.
  • Automatic Connection Upgrade / Downgrade.
  • Early (Informational) Responses / Hints.
  • HTTP/1.1, HTTP/2 and HTTP/3 support.
  • WebSocket over HTTP/2+ (RFC8441).
  • Proxy support for HTTP and SOCKS.
  • Detailed connection inspection.
  • Post-Quantum Security & ECH.
  • HTTP/2 with prior knowledge.
  • Support for free-threaded.
  • Server Side Event (SSE).
  • Multiplexed connection.
  • Mirrored Sync & Async.
  • Trailer Headers.
  • WebSocket.
  • WASI.

The documentation describes the requirements and limitations of each feature.

This philosophy is inspired by curl: broad protocol and platform capability, stable interfaces, secure defaults, and user choice where deployment requirements differ.

Compatibility is a release requirement

Compatibility is continuously measured against inherited urllib3 behavior, protocol integration tests, and the actual test suites of major downstream projects.

When a reasonable downstream pattern breaks, we investigate it as a compatibility defect rather than dismissing it solely because it touches an internal API.

Tested beyond the happy path

The CI matrix is intentionally broad because compatibility and deployment choice are core features of the project.

Dimension Continuous coverage
Python CPython, PyPy, supported historical versions, current versions, free-threaded builds
TLS Modern OpenSSL, older OpenSSL, LibreSSL, stdlib TLS, Rustls with the AWS-LC provider, BoringSSL
Protocols HTTP/1.1, HTTP/2, HTTP/3, prior knowledge, upgrade, downgrade, multiplexing
APIs Synchronous and asynchronous implementations
Networking IPv4, IPv6, Happy Eyeballs, HTTP proxies, HTTPS proxies, SOCKS, TLS-in-TLS
Resolvers System, DoH, DoT, DoQ, DoU, in-memory, resolver composition
Runtime Linux, Windows, macOS, containers, WASI Preview 1, Preview 2, and Preview 3

Protocol integration tests use Traefik and go-httpbin so the client is exercised against independent, non-Python server implementations.

Downstream CI runs the downstream projects' own test orchestration. Current coverage includes:

Project Why it matters
Requests The most widely used urllib3 consumer and a major public API compatibility surface
Niquests Primary consumer of urllib3.future's extended sync and async capabilities
botocore Deep integration with urllib3 internals and the foundation of the AWS Python SDK
boto3 High-level AWS SDK behavior layered over botocore
Sphinx Widely used documentation tooling and HTTP link checking
docker-py Streaming, connection pooling, and Docker transport behavior
clickhouse-connect Database transport, streaming, and chunked-transfer behavior

These checks provide measurable coverage of the tested behavior. No finite test matrix can prove compatibility with every application or undocumented integration, so applications should still run their own representative tests.

Installation modes

Choose how urllib3.future fits into your environment. Use drop-in mode to select it for existing urllib3 imports, or cohabitation mode to keep upstream urllib3 and use both projects side by side.

In-place replacement is the default because we want existing integrations to work out of the box. Niquests extends Requests, whose ecosystem includes plugins that import urllib3 directly and exchange its objects and exceptions. Sharing one implementation preserves that compatibility without requiring users to adapt each integration.

Other applications prefer to keep the two transports separate—for example, when Niquests is an indirect dependency and existing Requests integrations should continue using upstream urllib3. Cohabitation supports that choice explicitly. It retains urllib3.future's features, while extensions that exchange transport objects between the two implementations may need adaptation.

Mode Import Effect Appropriate when
Drop-in import urllib3 urllib3.future becomes the environment-wide urllib3 implementation Applications, managed runtimes, and libraries intentionally standardizing on urllib3.future
Cohabitation import urllib3_future Upstream urllib3 retains the urllib3 namespace Applications requiring strict namespace separation

Drop-in mode

Install the published wheel with your package manager:

Package manager Command
pip python -m pip install urllib3-future
uv uv add urllib3-future
Poetry poetry add urllib3-future
PDM pdm add urllib3-future

Then use the established import:

import urllib3

This is an environment-wide transport selection. Packages in the same Python environment that import urllib3 will use urllib3.future too.

Cohabitation mode

You can use urllib3.future while keeping upstream urllib3 in place. Cohabitation is a supported installation mode, available through two routes:

Route How you choose it What it installs
Source distribution from PyPI Select a source build and set URLLIB3_NO_OVERRIDE=1 Only urllib3_future, without a .pth startup hook
Prebuilt alternative wheel Select a +isolation release from the project's isolation index The same separate package, already built, with a verifiable attestation

Both routes keep import urllib3 pointing to upstream urllib3 when it is installed. Niquests uses urllib3_future; Requests and other libraries that import urllib3 continue using upstream. The fork's HTTP/2, HTTP/3 and async APIs remain available through its own namespace.

Start with a fresh environment, expand your package manager, and choose one route. For prebuilt wheels, select a release listed in the isolation index; the pip example below uses 2.25.900+isolation once that version is available.

pip

Build from the PyPI source distribution:

URLLIB3_NO_OVERRIDE=1 \
python -m pip install --no-cache-dir --no-binary=urllib3-future urllib3-future urllib3

Or install a prebuilt +isolation wheel:

Save this in requirements-isolation.txt:

--extra-index-url https://jawah.github.io/urllib3.future/isolation/simple/
urllib3-future==2.25.900+isolation
urllib3

Then install it:

python -m pip install -r requirements-isolation.txt

Retain the complete +isolation pin when updating dependencies. If that wheel is unavailable, pip fails to resolve it instead of selecting the drop-in build.

uv

Build from the PyPI source distribution:

Add this to your project's pyproject.toml:

[tool.uv]
no-binary-package = ["urllib3-future"]
extra-build-variables = { "urllib3-future" = { URLLIB3_NO_OVERRIDE = "1" } }

Then install:

uv add urllib3-future urllib3

uv records both choices in the project configuration and applies the build flag automatically during installs, syncs, and upgrades, including on Windows.

Or install a prebuilt +isolation wheel:

Bind the package to the isolation index in pyproject.toml:

[tool.uv.sources]
urllib3-future = { index = "urllib3-future-isolation" }

[[tool.uv.index]]
name = "urllib3-future-isolation"
url = "https://jawah.github.io/urllib3.future/isolation/simple/"
explicit = true

Then install:

uv add urllib3-future urllib3

Keep pyproject.toml and uv.lock with your project. The source binding also applies when Niquests depends on urllib3.future.

Poetry

Build from the PyPI source distribution:

poetry config --local installer.no-binary urllib3-future
URLLIB3_NO_OVERRIDE=1 poetry add urllib3-future urllib3

Keep the generated poetry.toml setting with your project so subsequent installations also select source builds.

Or install a prebuilt +isolation wheel:

poetry source add --priority=explicit urllib3-future-isolation https://jawah.github.io/urllib3.future/isolation/simple/
poetry add --source urllib3-future-isolation urllib3-future
poetry add urllib3

Poetry records the fork's source in pyproject.toml. Only urllib3.future is bound to the isolation index; upstream urllib3 uses the usual source. Keep this configuration and poetry.lock with your project.

PDM

Build from the PyPI source distribution:

Add this to your project's pyproject.toml:

[tool.pdm.resolution]
no-binary = "urllib3-future"

Then install with the build flag:

URLLIB3_NO_OVERRIDE=1 pdm add urllib3-future urllib3

Or install a prebuilt +isolation wheel:

Bind the package to the isolation index in pyproject.toml:

[[tool.pdm.source]]
name = "urllib3-future-isolation"
url = "https://jawah.github.io/urllib3.future/isolation/simple/"
include_packages = ["urllib3-future"]

Then install:

pdm add urllib3-future urllib3

Keep pyproject.toml and pdm.lock with your project. The package binding restricts urllib3.future to the isolation index, including when it is a dependency of Niquests.

The pip, Poetry, and PDM source-build commands above use Linux/macOS shell syntax. In PowerShell, set $env:URLLIB3_NO_OVERRIDE = "1" before running the package-manager command. Supply this flag during future installs, syncs, and upgrades too; uv supplies it through extra-build-variables. The wheel route records your choice in the pin or package-source binding.

Then each import selects its own implementation:

import urllib3         # upstream urllib3
import urllib3_future  # urllib3.future

Follow the complete cohabitation guide for Windows commands, persistent requirements, upgrade instructions, and checks you can run to verify the installation. The Niquests cohabitation FAQ also covers source builds with pip, Poetry, PDM, and uv.

The environment variable is a build-time choice; it does not change an already-installed wheel. Keep your chosen recipe in your project and CI so future installations preserve the same namespace separation.

Depending on urllib3.future from a library

A PyPI library can depend on urllib3.future when its supported transport baseline requires capabilities provided by this implementation.

Because the default wheel selects the urllib3 implementation for the Python environment, treat the dependency as an intentional platform decision rather than an invisible optimization.

We recommend:

  • Declaring the compatible major-version range: urllib3-future>2,<3.
  • Running the library's full test suite with common urllib3 consumers present.
  • Mentioning the transport selection in release notes.
  • Reporting compatibility regressions to this project; they are treated as release blockers.

Libraries that require only the standard urllib3 API may leave implementation selection to the application. Libraries that rely on HTTP/2, HTTP/3, async APIs, multiplexing, advanced DNS, WASI, or alternative TLS support can declare urllib3.future as their intended runtime.

Namespace selection

Python packaging has no standard mechanism for one distribution to declare that it is a compatible replacement for another distribution while satisfying existing imports of the original package.

This matters beyond import convenience. Requests extensions and other urllib3 consumers exchange urllib3 exceptions, response objects, connection classes, and type annotations. A separate namespace preserves isolation, but objects from urllib3 and urllib3_future no longer share identity. Existing packages that import urllib3 directly would also continue using the upstream transport.

The default wheel includes both urllib3 and urllib3_future. It also includes a small, inspectable .pth startup script. If files from upstream urllib3 and urllib3.future are mixed in the same urllib3 package directory, the script recreates that directory from the authoritative urllib3_future copy before application imports begin.

The mechanism:

  • Does not patch sys.modules.
  • Does not depend on application import order.
  • Leaves a physical urllib3 package visible to Python, IDEs, type checkers, packagers, and static analysis tools.
  • Becomes a no-op once the environment is consistent.
  • Is excluded entirely from cohabitation builds.

The implementation is available in urllib3_future.pth and hatch_build.py.

This behavior is intentional, environment-wide, and reversible through the documented cohabitation installation mode.

Compatibility policy

The compatibility target is practical drop-in operation for existing urllib3 consumers.

The project preserves urllib3's public top-level import surface and selected private behavior required by major downstream packages. Applicable upstream bug fixes and security patches are reviewed and incorporated.

Compatibility regressions are priority defects. If an existing urllib3 pattern does not work with urllib3.future, please open an issue with a minimal reproducer and the affected downstream package.

Fork releases use the MAJOR.MINOR.9xx version form. The 9xx patch range distinguishes urllib3.future releases from upstream urllib3 releases.

Frequently asked questions

Is this a fork?

Yes. urllib3.future is an independently maintained fork of urllib3 with a different transport architecture and feature scope.

The fork preserves the familiar urllib3 API while adding capabilities that require deeper changes than an extension module can provide. Issues and support requests for urllib3.future should be reported in this repository.

Why a fork instead of a new HTTP client?

A new client API would require applications, Requests integrations, SDKs, and other urllib3 consumers to migrate individually.

The fork keeps the established API and ecosystem contract while allowing the transport implementation to evolve. Applications can modernize their HTTP stack without replacing every integration layered above it.

Why not contribute everything upstream?

We explored the architecture upstream first. The projects chose different technical scopes and development strategies.

urllib3.future prioritizes a unified protocol-neutral backend, transparent HTTP/1.1, HTTP/2, and HTTP/3 negotiation, mirrored async APIs, broad TLS backend choice, and support for older and alternative runtime environments.

Maintaining that scope independently allows each project to evolve according to its own priorities.

Why is namespace replacement the default?

The compatibility objective is that existing code using import urllib3 continues to work without adapters or runtime injection.

Python packaging has no standard concept of one distribution replacing another. The default wheel therefore makes namespace selection before application imports begin. This choice applies to the environment, not one individual dependency.

Cohabitation mode is available when strict namespace separation is preferred.

Why not use an optional extra?

An extra selected by one transitive dependency would still affect every package in the environment while making the environment-wide effect appear local to that dependency.

urllib3.future instead provides two documented modes with different outcomes: drop-in replacement and strict cohabitation.

Why not inject at runtime?

Runtime injection through sys.modules makes behavior depend on import order and hides namespace selection inside application code.

The installation-time strategy runs before application imports and leaves a physical package visible to static and runtime tooling.

Is urllib3.future fully compatible with urllib3?

Compatibility is a primary project objective, but no finite test suite can guarantee compatibility with every application, dependency combination, or private integration.

The project maintains urllib3's public import surface and continuously tests widely used downstream projects. Compatibility failures are investigated as project defects when preserving the behavior is technically and securely reasonable.

Is urllib3.future production-ready?

The project is designed and maintained for production use. It is exercised through a broad Python, TLS, protocol, platform, and downstream compatibility matrix.

Teams should still pin a tested version, run their own integration and load tests, and exercise the transport paths they rely on.

Is it faster than urllib3?

It can be substantially faster for workloads that benefit from connection reuse, concurrency, and HTTP/2 or HTTP/3 multiplexing. A serial HTTP/1.1 workload may show no improvement.

Performance is workload-specific. Use reproducible benchmarks and application-specific testing rather than assuming a universal speedup.

What happens when compatibility breaks?

Compatibility regressions are priority defects. Please report the smallest reproducer and the affected downstream package.

The project regularly accepts compatibility fixes even when a downstream uses an urllib3 internal, provided the behavior is reasonable and preserving it does not compromise protocol correctness or security.

Can upstream urllib3 and urllib3.future coexist?

Yes. Cohabitation mode leaves upstream urllib3 behind import urllib3 and provides the fork through import urllib3_future. Choose a source build with URLLIB3_NO_OVERRIDE=1 or a prebuilt +isolation wheel. Both omit the .pth startup hook. The cohabitation guide walks through installation, verification, and upgrades for both routes.

What are the known platform boundaries?

Emscripten and Pyodide are not currently supported by urllib3.future but WASI is. Use upstream urllib3 on those platforms, optionally through cohabitation mode.

HTTP/3 availability depends on a supported platform and the semi-optional qh3 dependency. ECH and post-quantum capabilities depend on the selected TLS backend and its configuration.

Is there precedent or prior art for in-place replacement?

Yes. A Python distribution name and an import namespace are not the same concept, and Python does not grant a distribution exclusive ownership of an import name. Several established projects have provided an existing import interface through an alternative distribution.

Notable examples include:

  • Pillow succeeded PIL while preserving the established PIL import namespace.
  • PyCryptodome can act as a drop-in replacement for PyCrypto through the Crypto namespace, while PyCryptodomex provides an isolated Cryptodome namespace.
  • mysqlclient continued the MySQL-python interface through the existing MySQLdb namespace.
  • pillow-simd provides an alternative Pillow implementation through the same PIL namespace.
  • setuptools uses distutils-precedence.pth and _distutils_hack to select its bundled implementation of distutils before application imports.
  • gevent and Eventlet provide transparent runtime replacement of standard-library networking, threading, and queue behavior. Existing applications continue using familiar standard interfaces while cooperative implementations operate underneath. This is environment-wide interface substitution within a process rather than a physical package replacement, and its behavior can depend on patch timing and import order.
  • urllib3's own inject_into_urllib3() integration historically replaces its standard-library TLS implementation with a PyOpenSSL-backed implementation while preserving the urllib3-facing API. This is a narrower, runtime-scoped replacement, but it establishes a direct precedent within urllib3 for transparently substituting a core transport implementation.
  • The official OpenCV Python distributions provide four separately named packages: opencv-python, opencv-contrib-python, opencv-python-headless, and opencv-contrib-python-headless. Their documentation explicitly states that all four provide the same cv2 namespace and instructs users to install exactly one because there is no plugin architecture and overlapping installations conflict.

Related replacement mechanisms are also common outside PyPI. Operating-system package managers support concepts such as Provides, Conflicts, and Replaces, and distributors routinely patch or redirect implementations while preserving their established interfaces. For example, some distributions make certifi use the system certificate store without changing the public certifi import API.

These precedents are not identical to urllib3.future. Most replaced an unmaintained project, provided alternate builds of the same project, or relied on an explicit operating-system package manager. urllib3.future is unusual because it independently implements the interface of a widely deployed and actively maintained project, while supporting both drop-in replacement and strict namespace separation.

The novelty is therefore not the idea that an interface can have more than one implementation. The difficult part is sustaining compatibility with urllib3's documented API, historical behavior, downstream integrations, object identity, and frequently used internal interfaces while continuing to evolve the transport architecture.

Anyone may implement the urllib3 interface in principle. In practice, doing so requires accepting its accumulated compatibility constraints as release requirements. urllib3.future treats that obligation as measurable engineering work through the inherited urllib3 suite, downstream project suites, and independent protocol integration tests.

Known compatibility differences

The following intentional differences may affect applications that rely on representation details inherited from HTTP/1 or on urllib3's historical use of the standard library. They do not change the underlying HTTP semantics, but applications and integrations relying on those implementation details may require adjustments.

Header-name casing

HTTP field names are case-insensitive in requests and responses. Upstream urllib3 provides case-insensitive access through HTTPHeaderDict, regardless of the casing used by the application or received from the server.

With HTTP/1, field names can nevertheless retain their original wire casing. This has allowed some client applications to accidentally depend on presentation details such as Content-Type instead of treating it as equivalent to content-type.

Some server applications, middleware, gateways, or custom HTTP parsers may have the same defect and incorrectly require a specific spelling, such as Authorization rather than authorization. When urllib3.future sends a differently cased but semantically equivalent field name, such a server may reject the request, fail to locate the header, or return an internal error such as HTTP 500.

This server-side behavior is rare and violates the HTTP specifications, which define field names as case-insensitive. Such implementations are also inherently incompatible with HTTP/2 and HTTP/3, where field names are required to be lowercase.

urllib3.future normalizes outgoing field names consistently across HTTP/1, HTTP/2, and HTTP/3 instead of exposing protocol-dependent casing. Incoming HTTP/1 field names retain the spelling sent by the server, while incoming HTTP/2 and HTTP/3 field names are lowercase as required by those protocols. The lowercase requirement is not merely a consequence of HPACK, QPACK, or binary framing.

Remediation: Treat header names as case-insensitive on both the client and server. Do not compare or assert their presentation casing. Server applications and middleware should normalize field names before matching them. If a non-compliant server cannot be corrected, use an HTTP client or transport that preserves its HTTP/1 casing requirement.

Reason phrases

HTTP/1 responses may include a server-defined reason phrase. Upstream urllib3 historically exposed that value through response.reason, including its original wording and casing.

For example, an HTTP/1.1 server may return:

HTTP/1.1 200 SUCCESS

and upstream urllib3 may expose:

response.reason == "SUCCESS"

HTTP/2 and HTTP/3 carry only the numeric status code and do not provide a reason phrase. To preserve a stable response.reason API across all supported HTTP versions, urllib3.future derives the canonical phrase from the numeric status code. Unknown status codes use "Unknown".

As a result, a custom HTTP/1 reason phrase is not preserved:

response.status == 200
response.reason == "OK"

This normalization is necessary to provide consistent behavior independently of the negotiated HTTP version.

Remediation: Treat the numeric status code as authoritative. Treat response.reason as an informational, implementation-derived value, and do not depend on server-specific wording or casing.

http.client observability

Upstream urllib3's HTTP/1 implementation relies on the standard library's http.client. Some integrations consequently instrument, monkeypatch, or observe http.client directly instead of instrumenting urllib3.

urllib3.future uses a protocol-independent transport architecture and does not rely on http.client, including for HTTP/1. Instrumentation attached only to http.client therefore does not observe urllib3.future traffic.

This is also an unavoidable boundary for a multi-protocol urllib3 implementation. Even if an implementation retains http.client for HTTP/1, HTTP/2 and HTTP/3 traffic cannot pass through the same inheritance path. An integration observing http.client would then behave inconsistently depending on protocol negotiation: some requests would be visible and others would not.

Remediation: Instrument urllib3 at its own API or transport boundaries. Do not assume that observing or monkeypatching http.client provides complete coverage for a client capable of negotiating multiple HTTP versions.

Release integrity

Releases are published through PyPI trusted publishing and include provenance generated by the release workflow.

The project uses:

  • Commit-pinned GitHub Actions.
  • CodeQL analysis.
  • OpenSSF Scorecard checks.
  • PyPI attestations.
  • SLSA provenance.
  • Public release artifacts and changelog history.

These controls make the build and publication path auditable. They complement, but do not replace, application-specific compatibility and security testing.

urllib3-future is also included in Google's Assured Open Source Software catalog. Assured OSS provides Google-built artifacts with provenance and security metadata; its inclusion is an additional supply-chain option, not a substitute for evaluating the PyPI release or this project's design decisions.

Security disclosures

To report a security vulnerability, use the Tidelift security contact. Tidelift will coordinate the fix and disclosure with the maintainers.

Documentation

Full usage and API documentation is available at urllib3future.readthedocs.io.

Contributing

Contributions are welcome. The specialized CI environments are not expected to be reproduced by every contributor; run the relevant local tests and linting, then let CI exercise the broader matrix.

python -m pip install nox
nox -s test-3.14
nox -s lint

Replace 3.14 with an available supported interpreter version.

See the contributor documentation for protocol, downstream, legacy TLS, and container-based test commands.

Sponsorship

urllib3.future receives recurring maintenance funding and sponsorship. Funding supports compatibility work, security updates, CI infrastructure, protocol maintenance, and downstream testing.

Funding does not replace community review or imply a support SLA. If your company depends on urllib3.future, consider sponsoring its continued maintenance.

A short history

urllib3.future began with a practical question:

Can Python applications gain HTTP/2, HTTP/3, and asynchronous capabilities without migrating the ecosystem away from urllib3?

In May 2023, an experimental contribution to urllib3 demonstrated a unified HTTP/1.1, HTTP/2, and HTTP/3 backend outside http.client. The experiment reached full coverage of its prototype and identified the compatibility, streaming, proxy, TLS, and integration work required for a maintained implementation.

The projects ultimately chose different architectural scopes and development strategies. Upstream urllib3 continued its own roadmap, while the unified protocol backend continued independently and became urllib3.future. Later in 2023, upstream opened a discussion about collaboration; the projects nevertheless continued as separately maintained implementations with different priorities.

Since then, urllib3.future has expanded beyond the original protocol prototype: it gained mirrored synchronous and asynchronous APIs, HTTP/3, multiplexing, advanced resolvers, multiple TLS backends, broad downstream compatibility, and WASI support.

urllib3.future remains grateful for the foundation built by urllib3's maintainers and contributors. Applicable upstream fixes and security patches continue to be reviewed and incorporated. The two projects serve different scopes, and users are free to choose the implementation that best matches their requirements.

2.25.900 Sep 22, 2026
2.24.908 Sep 08, 2026
2.24.907 Sep 05, 2026
2.24.906 Sep 02, 2026
2.24.905 Aug 28, 2026
2.24.904 Aug 24, 2026
2.24.903 Aug 23, 2026
2.24.902 Aug 19, 2026
2.24.901 Aug 15, 2026
2.24.900 Jul 27, 2026
2.23.900 Jul 19, 2026
2.22.901 Jul 09, 2026
2.22.900 Jun 26, 2026
2.21.902 Jun 01, 2026
2.21.901 Jun 01, 2026
2.21.900 May 30, 2026
2.20.907 May 22, 2026
2.20.906 May 21, 2026
2.20.905 May 17, 2026
2.20.904 May 13, 2026
2.20.903 May 12, 2026
2.20.902 May 11, 2026
2.20.901 May 10, 2026
2.20.900 May 09, 2026
2.19.913 Apr 27, 2026
2.19.912 Apr 25, 2026
2.19.911 Apr 24, 2026
2.19.910 Apr 23, 2026
2.19.909 Apr 17, 2026
2.19.908 Apr 14, 2026
2.19.907 Apr 13, 2026
2.19.906 Apr 12, 2026
2.19.905 Apr 10, 2026
2.19.904 Apr 09, 2026
2.19.903 Apr 08, 2026
2.19.902 Apr 04, 2026
2.19.901 Apr 02, 2026
2.19.900 Mar 29, 2026
2.18.901 Mar 26, 2026
2.18.900 Mar 24, 2026
2.17.903 Mar 19, 2026
2.17.902 Mar 16, 2026
2.17.901 Mar 11, 2026
2.17.900 Mar 03, 2026
2.16.900 Feb 22, 2026
2.15.903 Feb 08, 2026
2.15.902 Feb 03, 2026
2.15.901 Dec 22, 2025
2.15.900 Dec 16, 2025
2.14.908 Nov 27, 2025
2.14.907 Nov 14, 2025
2.14.906 Nov 06, 2025
2.14.905 Oct 16, 2025
2.14.904 Oct 12, 2025
2.14.903 Oct 11, 2025
2.14.902 Oct 06, 2025
2.14.901 Oct 02, 2025
2.14.900 Sep 21, 2025
2.13.909 Sep 14, 2025
2.13.908 Sep 10, 2025
2.13.907 Sep 09, 2025
2.13.906 Aug 27, 2025
2.13.905 Aug 23, 2025
2.13.904 Aug 20, 2025
2.13.903 Aug 11, 2025
2.13.902 Aug 10, 2025
2.13.901 Aug 01, 2025
2.13.900 Jun 22, 2025
2.12.922 May 19, 2025
2.12.921 May 17, 2025
2.12.920 May 04, 2025
2.12.919 Apr 28, 2025
2.12.918 Apr 19, 2025
2.12.917 Apr 10, 2025
2.12.916 Apr 09, 2025
2.12.915 Apr 02, 2025
2.12.914 Mar 30, 2025
2.12.913 Mar 21, 2025
2.12.912 Mar 07, 2025
2.12.911 Feb 06, 2025
2.12.910 Jan 28, 2025
2.12.909 Jan 21, 2025
2.12.908 Jan 13, 2025
2.12.907 Jan 12, 2025
2.12.906 Jan 03, 2025
2.12.905 Dec 29, 2024
2.12.904 Dec 22, 2024
2.12.903 Dec 09, 2024
2.12.902 Dec 06, 2024
2.12.901 Dec 05, 2024
2.12.900 Nov 28, 2024
2.11.912 Nov 26, 2024
2.11.911 Nov 14, 2024
2.11.910 Nov 08, 2024
2.11.909 Nov 07, 2024
2.11.908 Nov 03, 2024
2.11.907 Oct 30, 2024
2.11.906 Oct 26, 2024
2.11.905 Oct 26, 2024
2.11.904 Oct 25, 2024
2.11.903 Oct 22, 2024
2.11.902 Oct 22, 2024
2.11.901 Oct 21, 2024
2.11.900 Oct 21, 2024
2.10.906 Oct 17, 2024
2.10.905 Oct 15, 2024
2.10.904 Oct 13, 2024
2.10.903 Oct 13, 2024
2.10.902 Oct 09, 2024
2.10.901 Oct 08, 2024
2.10.900 Oct 07, 2024
2.9.900 Sep 24, 2024
2.8.907 Aug 20, 2024
2.8.906 Aug 15, 2024
2.8.905 Aug 04, 2024
2.8.904 Jul 18, 2024
2.8.903 Jul 16, 2024
2.8.902 Jul 07, 2024
2.8.901 Jun 27, 2024
2.8.900 Jun 24, 2024
2.7.914 Jun 16, 2024
2.7.913 May 31, 2024
2.7.912 May 27, 2024
2.7.911 May 24, 2024
2.7.910 May 22, 2024
2.7.909 May 17, 2024
2.7.908 May 16, 2024
2.7.907 May 06, 2024
2.7.906 May 02, 2024
2.7.905 Apr 28, 2024
2.7.904 Apr 20, 2024
2.7.903 Apr 04, 2024
2.7.902 Apr 03, 2024
2.7.901 Mar 27, 2024
2.7.900 Mar 25, 2024
2.6.906 Mar 18, 2024
2.6.905 Mar 17, 2024
2.6.904 Mar 17, 2024
2.6.903 Mar 10, 2024
2.6.902 Mar 04, 2024
2.6.901 Feb 28, 2024
2.6.900 Feb 26, 2024
2.5.904 Feb 21, 2024
2.5.903 Feb 20, 2024
2.5.902 Feb 04, 2024
2.5.901 Feb 02, 2024
2.5.900 Feb 02, 2024
2.4.906 Jan 19, 2024
2.4.905 Jan 16, 2024
2.4.904 Jan 15, 2024
2.4.903 Jan 07, 2024
2.4.902 Jan 01, 2024
2.4.901 Dec 31, 2023
2.4.900 Dec 30, 2023
2.3.902 Dec 08, 2023
2.3.901 Nov 26, 2023
2.3.900 Nov 18, 2023
2.2.907 Nov 11, 2023
2.2.906 Nov 11, 2023
2.2.905 Nov 08, 2023
2.2.904 Nov 06, 2023
2.2.903 Nov 06, 2023
2.2.902 Nov 05, 2023
2.2.901 Nov 04, 2023
2.2.900 Nov 02, 2023
2.1.903 Oct 23, 2023
2.1.902 Oct 21, 2023
2.1.901 Oct 11, 2023
2.1.900 Oct 08, 2023
2.0.936 Oct 01, 2023
2.0.934 Sep 23, 2023
2.0.933 Sep 21, 2023
2.0.932 Sep 12, 2023
2.0.931 Jul 16, 2023

Wheel compatibility matrix

Platform Python 3
any

Files in release

Extras:
Dependencies:
h11 (<1.0.0,>=0.11.0)
jh2 (<6.0.0,>=5.0.3)
qh3 ( or ) and ( or ) (<3.0.0,>=1.5.4)