openai-python/httpx2.md at main · openai/openai-python
Migrating to HTTPX2
[](https://github.com/openai/openai-python/blob/main/httpx2.md#migrating-to-httpx2)
The OpenAI Python SDK now uses HTTPX2 for its synchronous and asynchronous HTTP clients. HTTPX2 is installed automatically with `openai`; the previous `httpx` package is not. This guide explains what changes for applications that interact with the SDK's HTTP layer.
If you use the SDK's default HTTP client
[](https://github.com/openai/openai-python/blob/main/httpx2.md#if-you-use-the-sdks-default-http-client) If you construct an `OpenAI` or `AsyncOpenAI` client without providing `http_client`, your existing API calls, parsed response models, streaming APIs, authentication, retries, and numeric timeouts continue to work:
from openai import OpenAI
client = OpenAI(timeout=30.0) response = client.responses.create(model="gpt-5.5", input="Hello")
No HTTPX2 extra or separate installation is required:
pip install openai
If your application imported `httpx` only because an earlier SDK installed it transitively, add your own `httpx` dependency or migrate those imports to `httpx2`. Installing the SDK no longer installs `httpx` for you.
TLS certificates and trust stores
[](https://github.com/openai/openai-python/blob/main/httpx2.md#tls-certificates-and-trust-stores)
**HTTPX2 changes the default TLS trust store, including for applications that use the SDK's default HTTP client.** HTTPX previously verified certificates against the CA bundle provided by `certifi`. HTTPX2 instead uses the operating-system trust store, and the SDK no longer installs `certifi`.
This can break certificate verification in minimal container images without system CA certificates, environments using corporate TLS-inspecting proxies, and deployments that relied on a custom or modified `certifi` bundle. Install the required CA certificates in the operating-system trust store, or configure an explicit certificate bundle:
export SSL_CERT_FILE=/path/to/ca-bundle.pem
Alternatively, configure a directory of trusted CA certificates:
export SSL_CERT_DIR=/path/to/ca-directory
These environment variables are honored when `trust_env=True`, which is the default. To control trust explicitly on a custom client, pass an `ssl.SSLContext` through `verify`:
import ssl from openai import OpenAI, DefaultHttpx2Client
ssl_context = ssl.create_default_context(cafile="/path/to/ca-bundle.pem") client = OpenAI(http_client=DefaultHttpx2Client(verify=ssl_context))
Use `DefaultAsyncHttpx2Client(verify=ssl_context)` for the equivalent async configuration. The SDK's aiohttp transport uses the same HTTPX2 TLS settings.
If you provide a custom HTTP client
[](https://github.com/openai/openai-python/blob/main/httpx2.md#if-you-provide-a-custom-http-client) Use HTTPX2 clients and HTTPX2 configuration objects. The SDK provides helpers that preserve its recommended timeout, connection-pool, and redirect defaults:
import httpx2 from openai import OpenAI, AsyncOpenAI, DefaultHttpx2Client, DefaultAsyncHttpx2Client
proxy_client = OpenAI(http_client=DefaultHttpx2Client(proxy="http://proxy.example.com:8080"))
transport_client = OpenAI( http_client=DefaultHttpx2Client( transport=httpx2.HTTPTransport(local_address="0.0.0.0"), timeout=httpx2.Timeout(30.0, connect=5.0), ) )
async_client = AsyncOpenAI(http_client=DefaultAsyncHttpx2Client(timeout=httpx2.Timeout(30.0)))
Directly constructed `httpx2.Client` and `httpx2.AsyncClient` instances are also supported. When you construct a client directly, its own HTTPX2 defaults apply unless you configure them yourself.
The existing `DefaultHttpxClient` and `DefaultAsyncHttpxClient` names continue to work, but now construct HTTPX2 clients. Prefer `DefaultHttpx2Client` and `DefaultAsyncHttpx2Client` when making the HTTP client family explicit.
Module-level configuration follows the same rule:
import openai
openai.http_client = openai.DefaultHttpx2Client()
Timeouts, URLs, transports, and connection settings
[](https://github.com/openai/openai-python/blob/main/httpx2.md#timeouts-urls-transports-and-connection-settings) Replace HTTPX-specific objects with the corresponding HTTPX2 objects:
| Previous object | HTTPX2 object | | --- | --- | | `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.AsyncHTTPTransport` | `httpx2.AsyncHTTPTransport` | | `httpx.MockTransport` | `httpx2.MockTransport` |
For example, a granular SDK timeout becomes:
import httpx2 from openai import OpenAI
client = OpenAI(timeout=httpx2.Timeout(60.0, connect=5.0, read=20.0))
Numeric timeout values do not change. Existing string URLs do not change. Custom transport subclasses, mounted transports, proxy integrations, and connection-pool instrumentation must target HTTPX2's transport interfaces.
Authentication and event hooks
[](https://github.com/openai/openai-python/blob/main/httpx2.md#authentication-and-event-hooks) Authentication handlers and hooks receive HTTPX2 request and response objects. Update custom auth classes and annotations accordingly:
import httpx2 from openai import OpenAI, DefaultHttpx2Client
def log_request(request: httpx2.Request) -> None: print(request.method, request.url)
client = OpenAI(http_client=DefaultHttpx2Client(event_hooks={"request": [log_request]}))
If you subclass an HTTP authentication or transport interface, subclass the matching `httpx2` class. Third-party instrumentation, tracing middleware, and auth integrations must explicitly support HTTPX2.
Raw responses, streaming, and exceptions
[](https://github.com/openai/openai-python/blob/main/httpx2.md#raw-responses-streaming-and-exceptions) Parsed SDK response models are unchanged. When using a native HTTPX2 client, transport-facing objects belong to HTTPX2:
import httpx2 from openai import OpenAI
client = OpenAI() response = client.models.with_raw_response.list()
assert isinstance(response.http_response, httpx2.Response) assert isinstance(response.http_request, httpx2.Request)
With a native client, use `cast_to=httpx2.Response` when requesting an unparsed HTTP response. Streaming response wrappers also expose HTTPX2 response objects. Application code should usually catch SDK exceptions such as `openai.APITimeoutError` and `openai.APIConnectionError`; with a native client, an exception's underlying transport cause is an HTTPX2 exception.
These type guarantees apply only to native HTTPX2 clients. An injected legacy HTTPX client produces `httpx.Request`, `httpx.Response`, and HTTPX transport exceptions instead, even if `cast_to=httpx2.Response` is supplied.
aiohttp
[](https://github.com/openai/openai-python/blob/main/httpx2.md#aiohttp) The supported aiohttp extra uses an HTTPX2-native transport. It does not install legacy HTTPX or the external `httpx-aiohttp` adapter:
pip install 'openai[aiohttp]'
from openai import AsyncOpenAI, DefaultAioHttpClient
client = AsyncOpenAI(http_client=DefaultAioHttpClient())
`DefaultAioHttpClient()` is an `httpx2.AsyncClient`. Applications using this helper do not need to construct or import the transport directly.
Request mocking and tests
[](https://github.com/openai/openai-python/blob/main/httpx2.md#request-mocking-and-tests) Mocks must intercept HTTPX2 requests and return HTTPX2 responses. For example:
import httpx2 from openai import OpenAI
def handler(request: httpx2.Request) -> httpx2.Response: return httpx2.Response( 200, request=request, json={"object": "list", "data": []}, )
client = OpenAI(http_client=httpx2.Client(transport=httpx2.MockTransport(handler))) assert client.models.list().data == []
If your test suite uses RESPX, update to an HTTPX2-compatible RESPX version or fork. A RESPX version that patches only legacy HTTPX cannot intercept the SDK's default HTTPX2 client. If you cannot migrate that integration immediately, the temporary legacy-client escape hatch below lets existing HTTPX-only RESPX setups continue to work while you migrate.
Temporary escape hatch: a legacy HTTPX client
[](https://github.com/openai/openai-python/blob/main/httpx2.md#temporary-escape-hatch-a-legacy-httpx-client) Applications that depend on an HTTPX-only transport, integration, or mocking library can explicitly install legacy HTTPX and inject a legacy client:
pip install openai httpx
**Legacy HTTPX support is runtime-only.** The SDK's public type annotations accept HTTPX2 clients, so passing a legacy client directly fails static type checking in mypy, Pyright, and similar tools. Use `cast(Any, ...)` or a targeted type-ignore when deliberately choosing this compatibility path:
from typing import Any, cast
import httpx from openai import OpenAI
client = OpenAI(http_client=cast(Any, httpx.Client()))
The asynchronous form requires the same workaround:
from typing import Any, cast
import httpx from openai import AsyncOpenAI
client = AsyncOpenAI(http_client=cast(Any, httpx.AsyncClient()))
Legacy clients preserve the HTTPX request, response, and exception families. Request raw responses as `httpx.Response`, using the same type-checking workaround for the legacy response class:
from typing import Any, cast
import httpx from openai import OpenAI
client = OpenAI(http_client=cast(Any, httpx.Client())) response = client.get("/models", cast_to=cast(Any, httpx.Response))
assert isinstance(response, httpx.Response)
Passing `cast_to=httpx2.Response` does not convert a legacy HTTPX response into an HTTPX2 response. Install and maintain the legacy dependency yourself. Legacy HTTPX support is provided as a migration aid and may be discontinued.
Existing legacy aiohttp adapters
[](https://github.com/openai/openai-python/blob/main/httpx2.md#existing-legacy-aiohttp-adapters) If you must retain an existing `httpx-aiohttp` integration, install it explicitly and inject its legacy client:
pip install openai httpx-aiohttp
from typing import Any, cast
from httpx_aiohttp import HttpxAiohttpClient from openai import AsyncOpenAI
client = AsyncOpenAI(http_client=cast(Any, HttpxAiohttpClient()))
This path is covered by dedicated compatibility tests, including a real request through the aiohttp transport, but remains a temporary escape hatch. Prefer `openai[aiohttp]` and `DefaultAioHttpClient()` for new code.