pypi / urllib3
urllib3
What changed in urllib3 2, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-18.
12 breaking12 security3 deprecations4 new APIs and options2 performance4 behavior and defaults1 tooling25 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initurllib3 263 changes
Breaking changes 12
A supported-length fingerprint containing non-hexadecimal characters now raises SSLError instead of binascii.Error.
Forwarding through an HTTPS proxy no longer applies target SNI, assertions, or client credentials to proxy handshakes; the proxy SSL context and identity checks are respected.
PoolManager no longer passes assert_hostname and assert_fingerprint parameters to HTTP connection pools.
Retries of request bodies with tell() but no seek() now raise UnrewindableBodyError instead of ValueError.
HTTP(S) host parsing now strictly enforces RFC 3986 syntax, rejects invalid host input, and normalizes percent-encoded octets according to RFC 3986.
The minimum supported pyOpenSSL version is now 19.0.0.
Support for end-of-life PyPy3.10 has been removed.
Support for end-of-life Python 3.9 has been removed.
Retry-After times greater than 6 hours are treated as 6 hours by default.
Custom decompressors must be updated to respect the changed API.
Removed in favor of HTTPResponse.headers.get(name, default).
Removed in favor of HTTPResponse.headers.
Security 12
is_ipaddress() now detects non-standard IPv4 forms accepted by socket.connect, ensuring SSL certificate verification uses the correct mode for those addresses.
HTTPS proxy TLS settings are no longer ignored or overridden by destination TLS settings. Configure proxy CA certificates and client certificates in proxy_ssl_context.
Safeguards prevent potential security issues when proxy tunneling handles invalid characters in the proxy host and HTTP headers.
urllib3: Chunked Deflate streaming can enter an infinite loop
urllib3: HTTPResponse.stream()/read_chunked() buffers an unbounded chunk-size line into memory
Fixed streaming API cases that bypassed decompression-bomb safeguards after partial reads or when using the official Brotli library.
ProxyManager pools now strip sensitive headers specified in this setting when redirecting to a different host.
Fixed a security issue that bypassed streaming API decompression-bomb safeguards when following HTTP redirects.
Chained encodings are limited to 5 to prevent denial-of-service attacks that exhaust resources during decoding.
Reading small chunks of highly compressed content is safer and more efficient, preventing excessive resource consumption when only a small amount of data is requested.
urllib3 allows an unbounded number of links in the decompression chain
urllib3 streaming API improperly handles highly compressed data
Deprecations 3
Using an empty collection for Retry.allowed_methods to retry any verb is deprecated.
Removal of deprecated features has been rescheduled to version 3.0.
Existing deprecation notices now use FutureWarning instead of DeprecationWarning for better visibility.
New APIs and options 4
urllib3.util.make_headers() now accepts a basic_auth_encoding parameter.
urllib3.util.make_headers() now accepts a proxy_basic_auth_encoding parameter.
The result of parse_url() now has an auth_decoded convenience property.
The result of parse_url() now has an auth_decoded_joined convenience property.
Performance 2
Streamed response decoding is faster.
Content decoding is faster due to an optimization to BytesQueueBuffer.
Behavior and default changes 4
The default pool queue class is resolved from the queue module after ConnectionPool instantiation, allowing late monkey-patching such as by gevent.
String representations now include host and port information.
Bytes keys can now be used to retrieve, delete, and test membership in HTTPHeaderDict.
Support for Python 3.14 free-threading builds is now explicit.
Tooling 1
A test dependency group containing the minimum dependencies needed to run the test suite is available for downstream packagers.
Fixes and other changes 25
Handling of HTTP 303 redirects is fixed for requests with chunked or file-like bodies.
URL fragments are stripped from absolute request targets before HTTPConnectionPool.urlopen() and HTTP proxy forwarding send requests.
An invalid timeout argument on a pool created with block=True now raises ValueError instead of a misleading FullPoolError.
Unread response data is discarded in 64 KiB chunks, matching the default amt used by HTTPResponse.stream(...).
Obsolete folded response header lines are replaced with spaces in accordance with RFC 9112, preventing raw CRLF sequences from appearing in header values such as Set-Cookie.
Explicit :0 values are preserved instead of being replaced with default ports 80 or 443 across URL parsing, pool selection, proxy configuration, connection_from_url(), and HTTP/2 request authority.
proxy_ssl_context now works with ProxyManager when use_forwarding_for_https=True. Passing ssl_context instead emits a FutureWarning and will raise an error in v3.0.
Percent-encoded SOCKS proxy credentials are decoded before authentication with the proxy server.
An AttributeError on Python built with OpenSSL 4+ is fixed when ssl.PROTOCOL_TLSv1 no longer exists.
Certificate subject reading and encrypted private-key loading use cryptography APIs, avoiding DeprecationWarning from pyOpenSSL 26.3.0+.
The type annotation now accepts memoryview as well as bytearray, matching the io.RawIOBase.readinto contract and enabling use with io.BufferedReader without type errors.
Fixed LocationParseError for paths resembling schemeless URIs passed to urlopen().
Calling read with amt=None now includes decompressed data buffered from previous partial reads.
With cache_content=True, read() now caches the complete response after a partial read.
read_chunked() now handles amt=0.
stream() now handles amt=0.
The type alias now includes Iterable[str], matching documented and runtime behavior for chunked request bodies.
Fixed VerifiedHTTPSConnection on Emscripten.
Fixed read_chunked() to properly handle leftover data in the decoder's buffer when reading compressed chunked responses.
Restores the previously removed HTTPResponse.getheader() method.
Restores the previously removed HTTPResponse.getheaders() method.
Fixed use in Emscripten when no explicit port is provided.
Handling of expandable variables is fixed.
The zstd extra installs backports.zstd instead of zstandard on Python 3.13 and earlier.
Redirect handling is fixed when an integer is passed for the retries parameter.