• 5 min read
OpenAI’s Python SDK now uses HTTPX2, changing TLS trust stores, custom transports, mocks and HTTP client types for Python applications.
Image: GitHub
OpenAI’s Python SDK has replaced its underlying HTTP client with HTTPX2, a maintained fork and continuation of the HTTPX project stewarded by Pydantic. For applications that use the SDK’s default client, ordinary API calls still use the same SDK interfaces. The migration affects code that imports HTTPX directly, injects a custom client, implements authentication or transport hooks, or depends on HTTPX-specific test tooling.
The SDK installs HTTPX2 automatically with pip install openai
; it no longer installs the legacy httpx
package as a transitive dependency. The OpenAI migration guide says existing calls, parsed response models, streaming APIs, authentication, retries and numeric timeouts continue to work when an OpenAI
or AsyncOpenAI
client is created without a custom http_client
.
The compatibility boundary is the transport layer. HTTPX2 uses its own request, response, exception, transport and configuration classes, so code that reaches below the SDK’s resource APIs must update its imports and type assumptions.
| Existing HTTPX object | HTTPX2 replacement |
|---|---|
httpx.Client |
httpx2.Client |
httpx.AsyncClient |
httpx2.AsyncClient |
httpx.Timeout |
httpx2.Timeout |
httpx.URL |
httpx2.URL |
httpx.Limits |
httpx2.Limits |
httpx.HTTPTransport |
httpx2.HTTPTransport |
httpx.MockTransport |
httpx2.MockTransport |
TLS changes affect certificate verification #
The default certificate-verification behavior has changed even for applications that never construct an HTTP client themselves. Legacy HTTPX verified certificates against the CA bundle shipped by certifi
; HTTPX2 uses the operating system’s trust store, and the OpenAI SDK no longer installs certifi
.
That can expose failures in minimal container images without system CA certificates, corporate environments that use TLS-inspecting proxies, and deployments that depended on a customized or modified certifi
bundle. The fix is to install the required certificates into the operating-system trust store or point the process at an explicit bundle with SSL_CERT_FILE
. SSL_CERT_DIR
can be used when trusted certificates are kept in a directory. Those environment variables are honored when trust_env=True
, which is the default.
Applications that need deterministic trust configuration can create an ssl.SSLContext
and pass it through the SDK’s HTTPX2 helper:
ssl_context = ssl.create_default_context(cafile=“/path/to/ca-bundle.pem”) client = OpenAI(http_client=DefaultHttpx2Client(verify=ssl_context)) ```
The asynchronous equivalent is `DefaultAsyncHttpx2Client`
. The SDK’s `aiohttp`
transport follows the same HTTPX2 TLS settings.
## Custom clients and instrumentation need updates
OpenAI provides `DefaultHttpx2Client`
and `DefaultAsyncHttpx2Client`
helpers that retain the SDK’s recommended timeout, connection-pool and redirect defaults. A proxy client, for example, should now use `DefaultHttpx2Client(proxy=“http://proxy.example.com:8080”)`
. Directly constructed `httpx2.Client`
and `httpx2.AsyncClient`
instances are supported, but their own defaults apply unless the application configures them.
The old `DefaultHttpxClient`
and `DefaultAsyncHttpxClient`
names still work, but they now construct HTTPX2 clients. The newer names make the dependency explicit and are the preferred form for new code. Custom transports, mounted transports, proxy adapters and connection-pool instrumentation must target HTTPX2's transport interfaces rather than HTTPX’s.
The same applies to hooks and authentication handlers. A request logger should type its argument as `httpx2.Request`
, and subclasses of HTTP authentication or transport interfaces must inherit from the corresponding HTTPX2 class. Third-party tracing, middleware and authentication integrations need explicit HTTPX2 support; they will not automatically become compatible because the SDK-level API is unchanged.
HTTPX2 itself presents a broadly requests-compatible API with synchronous and asynchronous clients, strict timeouts, connection pooling, proxy support and access to both WSGI and ASGI applications. HTTP/1.1 is part of the normal package; HTTP/2 support is available through the optional `httpx2[http2]`
installation. The [HTTPX2 project repository](https://github.com/pydantic/httpx2) identifies `httpcore2`
as its transport layer, with `h11`
handling HTTP/1.1 and `anyio`
providing structured concurrency for asyncio and Trio. TLS verification is built around the `truststore`
dependency.
## Raw responses, streaming and tests
Parsed OpenAI response models do not change, but native transport-facing objects now belong to HTTPX2. Raw responses returned through the SDK expose `httpx2.Response`
and `httpx2.Request`
objects, and the underlying causes of SDK connection and timeout exceptions are HTTPX2 exceptions. Applications should generally continue catching SDK exceptions such as `openai.APITimeoutError`
and `openai.APIConnectionError`
rather than coupling error handling to the transport layer.
That type guarantee applies only to native HTTPX2 clients. If an application deliberately injects a legacy `httpx.Client`
, raw responses and exceptions remain legacy HTTPX objects. Supplying `cast_to=httpx2.Response`
does not convert a legacy response into an HTTPX2 response.
Test suites need the same adjustment. HTTPX2 mocks must receive `httpx2.Request`
objects and return `httpx2.Response`
objects through `httpx2.MockTransport`
. A RESPX installation that patches only legacy HTTPX will not intercept the SDK’s default HTTPX2 client; the project says developers must move to an HTTPX2-compatible RESPX version or fork.
The migration guide includes a temporary escape hatch for systems that cannot immediately replace an HTTPX-only transport, integration or mocking library. Developers can install `httpx`
themselves and inject a legacy client, but the SDK’s public type annotations accept HTTPX2 clients, so mypy, Pyright and similar tools will reject the legacy object without `cast(Any, …)`
or a targeted type ignore. The legacy path is explicitly a migration aid and may be discontinued.
The same caveat covers existing `httpx-aiohttp`
integrations: they must be installed separately and injected as legacy clients. For new asynchronous deployments, OpenAI recommends `pip install 'openai[aiohttp]'`
and `DefaultAioHttpClient()`
, which uses an HTTPX2-native async client rather than the external legacy adapter.
Code that stays at the OpenAI SDK’s high-level API may require no source changes, but its certificate environment still needs review. Any service that owns transport configuration, observes raw requests, instruments connections or mocks HTTP calls should treat this as a dependency migration rather than a simple package rename.
## Frequently asked questions
## Do OpenAI Python SDK API calls need code changes?+
Not when the SDK’s default HTTP client is used. Existing API calls, parsed response models, streaming APIs, authentication, retries and numeric timeouts continue to work, although TLS trust-store behavior changes.
## Why is certificate verification failing after the update?+
HTTPX2 uses the operating system trust store instead of certifi, which the SDK no longer installs. Minimal containers or corporate proxy environments may need system CA certificates or SSL_CERT_FILE and SSL_CERT_DIR configuration.
## Can applications keep using legacy HTTPX?+
Yes, temporarily. Install httpx yourself and inject a legacy client, but static type checkers require a workaround and the migration path may be discontinued.
## Does OpenAI’s SDK include HTTP/2 automatically?+
The SDK installs HTTPX2 automatically, but HTTPX2's optional HTTP/2 support requires the httpx2[http2] extra.
[Tomas Berg](/authors/tomas-berg/)
Computing Editor
Tomas lives in the terminal. He covers chips, laptops, and operating systems with a focus on performance and efficiency. He reads kernel changelogs the way other people read fiction, and he's always on the hunt for the perfect mechanical keyboard switch. If it processes data, Tomas has an opinion on it.