NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #3282 most downloaded on PyPI
urllib3.future is a powerful HTTP 1.1, 2, and 3 client with both sync and async interfaces
Last release 6 days ago
22 Sep 2026
Ships fairly regularly
a new release about every 2 weeks
Nearly every release is documented
notes for 60 of the last 60 stable releases
1 version withdrawn
withdrawn after publishing
3 years old
174 releases · first in 2023
One column per quarter.
Fixed unhandled error in HTTP/3 upgrade (TCP+TLS to QUIC) procedure that mainly affect Windows users. If your network silently filter QUIC packets or
MustRedialException error in the consumption of the response (including WS or SEE).Fixed charset transparency setter to not enforce charset=utf-8 in Content-Type anymore due to incompatibilities found in widely requested servers that
charset=utf-8 in Content-Type anymore due to incompatibilities found
in widely requested servers that still don't parse HTTP headers appropriately. We saw a 3rd party report that
a server rejected a request because it expected Content-Type to be exactly "X" and not "X; charset=utf-8".Fixed rare edge cases where upgrading or forcing HTTP/3 over QUIC with zero SSL configuration would lead to an error validating the chain of certifica
load_default_certs
when not needed.Improved performance when creating TLS connection. We removed a redundant ssl_ctx creation due to our caching / reusability for ssl.SSLContext.
@SECLEVEL=0 in the cipher suite.Bumped lower bound of qh3. The crlDistributionPoints getter is now officially implemented in qh3 >= 1.5.4.
crlDistributionPoints getter is now officially implemented in qh3 >= 1.5.4.Fixed long standing missing ciphers kwargs that can be propagated without a custom ssl.SSLContext via (Async)PoolManager and others.
ciphers kwargs that can be propagated without a
custom ssl.SSLContext via (Async)PoolManager and others.crlDistributionPoints not extracted from cert in ConnectionInfo (QUIC layer only).Fixed a memory leakage when downloading large content and specifying a chunk size that is lower than your regular incoming chunk size.
Backported Security fix CVE-2025-50181 (5.3 Medium, GHSA-pq67-6m6q-mj2v) from upstream urllib3 v2.5.0
ca_cert_data as bytes instead of str.OP_NO_RENEGOTIATION in ssl_options when it's not Niquests.qh3 to v1.5.3 due to some significant improvement toward
unifying PKI validation behaviors with Python default expectation (w/ OpenSSL).load_default_certs. We now check if the store is empty, then we load the default certs.Fixed a minor performance regression when reopening or upgrading a HTTPS connection.
Extended in-memory mTLS loading support to every major platforms.
Removed the persisting session ticket after first QUIC handshake. In a effort to be stricter with security and align with our TLS 1.2 and 1.3 OP_NO_TI
OP_NO_TICKET parameter.Fixed http3 has_expired logic to take into account "client side abort without close event". https://github.com/jawah/niquests/issues/240
Fixed http3 QUIC idle timeout did not force the connection to be dropped by the pool.
Improve keepalive handling for connections. We now listen for an incoming pong frame after emitting a ping frame. Moreover we ensure better strictness
keepalive_delay and consider every connection dropped after set delay.Set a bigger initial window size for HTTP/2, and HTTP/3 streams. This improves data streaming performances.
Fixed a performance issue when streaming download by chunk (size) not in phase with incoming packets size.
Fixed a rare thread safety issue when the size of PoolManager is inferior to the thread count. An edge case permitted the creation of two ConnectionPo
ConnectionPool for the same PoolKey.OverwhelmedTraffic in default configuration.happy_eyeballs=True is set with more tasks or threads than the pool size.Added useful repr for PoolManager, ConnectionPool and TrafficPolice (async counterpart included).
PoolManager, ConnectionPool and TrafficPolice (async counterpart included).KeyError upon parsing X509 certificate pulled from the QUIC layer when the certificate contain an unexpected
rfc4514 attribute. (https://github.com/jawah/urllib3.future/issues/217)Automatically grab qh3 for HTTP/3 support with PyPy 3.11
qh3 for HTTP/3 support with PyPy 3.11HTTPResponse starting from Python 3.14
If the Content-Type is invalid or malformed, the constructor stopped initializing some members
that are required in the closing procedure. (e.g. using ctx)Support for IDNA encode via qh3 utils. This allows you to use international domain names without the idna package. Thus avoiding an extra dependency.
qh3 utils. This allows you to use international domain names without the
idna package. Thus avoiding an extra dependency. This is made possible from qh3>=1.4.Fixed a rare issue where the closing of the WebSocket extension would lead to a RecursionError. This happen when the WebSocket state machine ends in a
RecursionError.
This happen when the WebSocket state machine ends in a broken state.Fixed compatibility with upstream urllib3 when third party program invoke deprecated HTTPResponse.getheader or HTTPResponse.getheaders. Those methods…
HTTPResponse.getheader or
HTTPResponse.getheaders. Those methods were planned to be removed in 2.1 (they still have a pending deprecation
that mention 2.1 target in the 2.3 version). As such we immediately restore the methods. (#203)HTTPResponse.read1 heavily simplified as we do already support HTTPResponse.read(-1).
Also mirrored in AsyncHTTPResponse.read1.qh3 for X86/i686 based processors (e.g. win32).RuntimeError, now raises ProtocolError.Fixed silencing the deprecation warning coming from python_socks about the "_socket" parameter.
Fixed our thread safety protection against the experimental free-threaded Python build. As expected, the absence of GIL challenged our implementation
TrafficPolice and
took it to its knees. We reviewed the in-depth logic and improved it for maximum resilience
and performance. We backported some improvements in AsyncTrafficPolice when applicable.python-socks to 2.6.1 (we will have to manually increase the upper bound
each minor/patch version due to our complex integration that invoke private classes/APIs)Improved our logic around caching a ssl_context in a concurrent environment.
Fixed error due to an internal change in python-socks 2.6
Fixed an issue when trying to force load Websocket over HTTP/2 or HTTP/3.
RuntimeError when forcing HTTP/3 by disabling both HTTP/1, and HTTP/2 and the remote is unable to negotiate HTTP/3.
This issue occurred because of our automatic downgrade procedure introduced in our 2.10.x series. The downgrade ends in panic
due to unavailable lower protocols. This only improve the UX by not downgrading and letting the original error out.
See https://github.com/jawah/niquests/issues/189 for original user report.HTTPResponse.shutdown() and nullified it. The fix they attempt to ship only concern
them, we are already safe (based on issue reproduction). See https://github.com/urllib3/urllib3/issues/2868proxy_is_tunneling property to HTTPConnection and HTTPSConnection.
See https://github.com/urllib3/urllib3/pull/3459HTTPSConnection.is_verified to False when using a forwarding proxy.
See https://github.com/urllib3/urllib3/pull/3283NewConnectionError and NameResolutionError.
See https://github.com/urllib3/urllib3/pull/3480Minor improvements on our algorithm that manage multiplexed connection. A) We ensured that when a remote peer sent a Goaway frame, we keep the connect
is_saturated for ConnectionPool to get a hint on whether all allocatable stream are busy.HTTPProtocolFactory.has(...) and ResolverFactory.has(...).ws+wsproto://... for ws=plain websocket and wsproto=implementation.Fixed a rare issue where Happy-Eyeballs algorithm would not respect timeout for a plain HTTP connection where all available endpoints are unreachable.
traffic_police.OverwhelmedTraffic in synchronous context and indefinite hang in asynchronous after awhile.Fixed a thread/task safety issue when closing a SSE extension.
Added built-in support for Server-Side-Event (or SSE) via a WebExtension. It is as simple as doing pm.urlopen("GET", "sse://sse.dev/test"). sse is usi
pm.urlopen("GET", "sse://sse.dev/test"). sse is using https under the hood by default.
To force SSE via plain HTTP, replace sse:// by psse://.
The extension attribute of produced response will be set, and you will be able to consume event promptly.
See the documentation to learn more.CONNECT verb manually outside of its standard usage.urlopen(..., multiplexed=True) from a PoolManager instance.Improved timeout reliability and performance in asynchronous mode.
Improved support for async I/O data reader.
Improved reliability of reusing a specific outgoing port. The feature is no longer experimental.
Fixed DNS-over-QUIC, DNS-over-TLS, and DNS-over-UDP(Cleartext) connection procedure on network that lacks IPv6 access.
source_address and setting happy_eyeballs=True.
We now silently discard the specific port to avoid a conflict / race condition with OS outgoing port allocation.urllib3.util.ssl_.IS_FIPS and set it to False.Added automatic mitigation of using deprecated PROTOCOL_TLS_* constants in ssl_version parameter.
asyncio.TransportSocket and _SelectorSocketTransport partially closed.PROTOCOL_TLS_* constants in ssl_version parameter.Fixed attempt to send ping frame in our discrete background idle watcher when the connection has just been closed.
Fixed unexpected exception when recreating a connection using the same outgoing port. Add SO_REUSEPORT if available, fallback to SO_REUSEADDR. This so
SO_REUSEPORT if available, fallback to SO_REUSEADDR. This socket option
is not bullet proof against reusability errors. Some OS differs in behaviors.Fixed custom loop like uvloop needing advanced error handling on transport close.
Improve (async) close procedure when used in a uvloop.
uvloop.Fixed (low-level) exception leak when using get_response(...) after urlopen(..., multiplexed=True).
get_response(...) after urlopen(..., multiplexed=True).Added viable replacement for connection close detection since we stopped using the function wait_for_read in property is_connected of a HTTPConnection
wait_for_read
in property is_connected of a HTTPConnection object. And we harmonized the behavior whether you use async
or sync.Fixed error in is_connected for a Connection. The logic is no longer applicable due to how urllib3-future grows. We no longer use the function wait_fo
is_connected for a Connection. The logic is no longer applicable due to how urllib3-future grows.
We no longer use the function wait_for_read. Also we stopped using MSG_PEEK for our discrete incoming data watcher
due to suspicious behavior noticed. Finally we shielded any exception from attempting to close a broken socket.Added a discrete task for each instantiated ConnectionPool to watch for unsolicited incoming data. This improves the fix shipped in v2.10.906 and avoi
ConnectionPool to watch for unsolicited incoming data.
This improves the fix shipped in v2.10.906 and avoid having to recycle your multiplexed connection in idle moments.
A new keyword argument is supported in your PoolManager configuration, namely background_watch_delay.
This parameter takes a int or float as the delay between checks. Set it to None to void this background task.
Anything lower than 0.01 will be interpreted as None, therefor disabling the discrete watch.keepalive_delay that
takes a value expressed in seconds for how long urllib3-future should automatically keep the connection alive.
This is done in direct extension to our "discrete task" mentioned just before. We will send PING frame
automatically to the remote peer every 60s by default (after idle for 60s to be clear). The window delay for
sending a PING is configurable via the keepalive_idle_window parameter. Learn more about this in our
documentation.fp in our LowLevelResponse instance to raise AttributeError when it cannot be
accessed. This will help with cachecontrol[filecache] way of determining if response was consumed entirely.Fixed handling aggressive ACKs watcher in some QUIC server implementation leading to a ProtocolError. We're actively working toward a solution that wi
ProtocolError.
We're actively working toward a solution that will avoid to recycle the QUIC connection.Fixed dangling task waiting for timeout when using Happy Eyeballs in a synchronous context.
Fixed thread/task safety with WebSocket R/W operations.
on_post_connection) in retries of failed requests.Fixed exception leaks in ExtensionFromHTTP plugins. Now every extension behave and raise urllib3 own exceptions.
Fixed call to stream(..) on (early) informational responses. The inner fp was set to None and the function is_fp_closed is not meant to handle this ca
stream(..) on (early) informational responses. The inner fp was set to None and the function
is_fp_closed is not meant to handle this case. Through you should never expect a body in those responses.read(), and data returns None for (early) informational responses.Fixed closed state on a WebSocketExtensionFromHTTP when the remote send a CloseConnection event.
>=1.2,<2.Added complete support for Informational Response whether it's an early response or not. We introduced a callback named on_early_response that takes e
on_early_response that takes exactly one parameter, namely a HTTPResponse. You may start leveraging Early Hints!
This works regardless of the negotiated protocol: HTTP/1.1, HTTP/2 or HTTP/3! As always, you may use that feature
in a synchronous or asynchronous context.qh3 lower bound version to v1.2 in order to support Informational Response in HTTP/3 also.ws:// (insecure) and wss:// (secure).
The response will be of status 101 (Switching Protocol) and the body will be None.
Most servers out there only support WebSocket through HTTP/1.1, and using HTTP/2 or HTTP/3 usually ends up in stream (reset) error.
By default, connecting to wss:// or ws:// use HTTP/1.1, but if you desire to leverage the WebSocket through a multiplexed connection,
use wss+rfc8441:// or ws+rfc8441://.
A new property has been introduced in HTTPResponse, namely extension to be able to interact with the websocket
server. Everything is handled automatically, from thread safety to all the protocol logic. See the documentation for more.
This will require the installation of an optional dependency wsproto, to do so, please install urllib3-future with
pip install urllib3-future[ws].:authority (special header) value might be malformed.Restored support for older-and-deprecated PySocks if installed and python-socks is absent for synchronous support of SOCKS proxies.
PySocks if installed and python-socks is absent for synchronous support of SOCKS proxies.trailers in HTTPResponse to reflect that.Fixed http2 maximum frame size error when the remote explicitly set a lower value than the default blocksize. This can happen when facing an Apache (h
Those build often lack TLS 1.3 support and may contain major vulnerabilities, but we have to be optimistic on their awareness. TLS 1.3 / QUIC is also…
qh3 manually
by first upgrading your pip installation by running python -m pip install -U pip.Alt-Svc header and urllib3-future may crash upon it.str body using a bytes value for Content-Type would induce a crash.
This was due to our unicode transparency policy. See https://github.com/jawah/urllib3.future/pull/142Fixed wrong upgrade attempt to QUIC when using a SOCKS proxy. Any usage of a proxy disable HTTP/3 over QUIC as per documented. until proper support is
Proxy-Authorization header to the list of headers to strip from requests when redirecting to a different host.
As before, different headers can be set via Retry.remove_headers_on_redirect.Relaxed h11 constraint around "pending proposal" and coming server event about upgrade. This is made to ensure near perfect compatibility against the
docker-py in our CI/integration pipeline.Added IS_PYOPENSSL constant that is exposed by upstream in urllib3.util.ssl_ submodule.
IS_PYOPENSSL constant that is exposed by upstream in urllib3.util.ssl_ submodule.ImportError) when importing urllib3.contrib.pyopenssl when PyOpenSSL isn't present in environment.boto3, sphinx, and requests to our downstream test cases (nox).Added support for async iterable yielding either bytes or str when passing a body into your requests.
Improved compatibility with httplib exception for IncompleteRead that did not behave exactly like expected (repr/str format over it).
IncompleteRead that did not behave exactly like expected (repr/str format over it).IncompleteRead might not be raised like expected.Support for HTTP/2 with prior knowledge over non-encrypted connection to leverage multiplexing in internal networks. To leverage this feature, you hav
urllib3-future can infer your intent.
Disabling HTTP/1.1 is to be made as follow: PoolManager(disabled_svn={HttpVersion.h11}).LowLevelResponse to help end-users track download speed accordingly if they use
brotli, gzip or zstd transfer-encoding during downloads.Your coding agent can read these notes before it upgrades. Set up the MCP server →