How to Use Custom HTTP Clients like httpx with the Anthropic Python SDK
Pass a pre-configured httpx.Client or httpx.AsyncClient instance to the http_client parameter when initializing Anthropic or AsyncAnthropic to override default networking behavior while maintaining full SDK compatibility.
The anthropics/anthropic-sdk-python repository is built entirely on the httpx library, abstracting all HTTP communication through a thin wrapper called BaseClient. By leveraging the http_client parameter, you can inject your own pre-configured httpx instances to fine-tune timeouts, connection limits, and middleware without modifying the SDK source code.
Why Inject a Custom HTTP Client?
When you don't provide an http_client argument, the SDK automatically constructs default clients (DefaultHttpxClient for synchronous operations, DefaultAsyncHttpxClient for async) with sensible defaults for timeouts, connection limits, and redirect following. However, passing a custom client enables you to:
- Configure specific timeout values for long-running inference requests
- Set custom connection pool limits for high-throughput applications
- Implement specific transport layers (Unix sockets, custom TLS configurations)
- Add middleware via httpx event hooks for logging or request modification
- Use alternative async transports like
aiohttpinstead of the default
Passing a Custom httpx Client
The http_client parameter in src/anthropic/_client.py accepts any httpx-compatible instance. The SDK validates the client type in lines 75-84, ensuring you cannot accidentally pass a synchronous client to AsyncAnthropic or vice versa.
Synchronous Custom Clients
For synchronous operations, instantiate Anthropic with a configured httpx.Client:
import httpx
from anthropic import Anthropic
# Build a custom httpx.Client with your own settings
my_client = httpx.Client(
timeout=httpx.Timeout(30.0), # 30-second timeout
limits=httpx.Limits(max_connections=200), # larger connection pool
follow_redirects=True, # same as SDK default
)
# Hand the client to the SDK
anthropic = Anthropic(
api_key="my-anthropic-api-key",
http_client=my_client,
)
response = anthropic.completions.create(
model="claude-3-opus-20240229",
max_tokens=256,
messages=[{"role": "user", "content": "Explain quantum tunnelling"}],
)
print(response.completion)
Relevant source: http_client handling in src/anthropic/_client.py (lines 72-84).
Asynchronous Custom Clients
For async operations, pass an httpx.AsyncClient (or compatible) to AsyncAnthropic:
import httpx
from anthropic import AsyncAnthropic
async_client = httpx.AsyncClient(
timeout=httpx.Timeout(20.0),
limits=httpx.Limits(max_connections=50),
)
async_anthropic = AsyncAnthropic(
api_key="my-key",
http_client=async_client,
)
response = await async_anthropic.completions.create(
model="claude-3-sonnet-20240229",
max_tokens=128,
messages=[{"role": "user", "content": "What is the capital of France?"}],
)
Supplying the wrong client type raises a clear TypeError during initialization.
Customizing SDK Defaults
If you want to keep the SDK's default networking behavior (socket keep-alive options, automatic proxy handling) but tweak specific settings, use the SDK's default client classes rather than raw httpx.Client.
Extending DefaultHttpxClient
The DefaultHttpxClient and DefaultAsyncHttpxClient classes, defined in src/anthropic/_base_client.py (lines 838-896), inherit from httpx.Client and apply SDK-wide defaults before merging your overrides:
from anthropic import Anthropic, DefaultHttpxClient
# Only override the timeout; everything else stays as the SDK defines it
default_like = DefaultHttpxClient(timeout=10.0)
anthropic = Anthropic(api_key="my-key", http_client=default_like)
These classes handle automatic proxy configuration from environment variables and set socket options that the SDK expects.
Using aiohttp Transport
To use aiohttp as the underlying transport instead of httpx's default, install the optional dependency and use DefaultAioHttpClient:
pip install "anthropic[aiohttp]"
import httpx
from anthropic import AsyncAnthropic, DefaultAioHttpClient
# The SDK's DefaultAioHttpClient wraps httpx-aiohttp and respects SDK defaults
aio_client = DefaultAioHttpClient(
timeout=httpx.Timeout(20.0),
limits=httpx.Limits(max_connections=50),
)
async_anthropic = AsyncAnthropic(
api_key="my-key",
http_client=aio_client,
)
Relevant source: async default client in src/anthropic/_base_client.py (lines 1520-1534).
Advanced Configuration Patterns
Request Logging with Event Hooks
Because DefaultHttpxClient inherits from httpx.Client, you can use any httpx feature including event_hooks for request/response middleware:
import httpx
from anthropic import Anthropic, DefaultHttpxClient
def log_request(request: httpx.Request):
print(f"→ {request.method} {request.url}")
client = DefaultHttpxClient(event_hooks={"request": [log_request]})
anthropic = Anthropic(api_key="my-key", http_client=client)
Proxy Configuration
The default client classes automatically read HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, and NO_PROXY environment variables via the helper in src/anthropic/_utils/_httpx.py. You can verify this behavior matches the SDK test suite:
import os
from anthropic import DefaultHttpxClient
os.environ["HTTPS_PROXY"] = "https://proxy.example.org"
client = DefaultHttpxClient()
assert any(mount.pattern == "https://" for mount in client._mounts.items())
For custom clients, configure mounts directly on your httpx.Client instance before passing it to the SDK.
How the SDK Handles HTTP Clients Internally
The SDK's internal BaseClient class serves as the abstraction layer for all HTTP operations. When you provide a custom client:
- Validation:
src/anthropic/_client.pychecks that the client type matches the sync/async nature of the Anthropic client class - Default Construction: If you pass
None, the SDK instantiates_DefaultHttpxClientor_DefaultAsyncHttpxClientfromsrc/anthropic/_base_client.py - Transport Setup: Default clients build a custom transport that adds socket keep-alive options and merges proxy configurations from environment variables
- Lifecycle Management: The SDK uses your client for all requests but does not automatically close it, allowing connection reuse across multiple SDK instances
Summary
- Pass custom
httpx.Clientorhttpx.AsyncClientinstances via thehttp_clientparameter toAnthropicorAsyncAnthropic - Match synchronous clients to
Anthropicand asynchronous clients toAsyncAnthropicto avoidTypeErrorexceptions - Use
DefaultHttpxClientorDefaultAsyncHttpxClientto preserve SDK networking defaults while tweaking specific settings like timeouts - Install
anthropic[aiohttp]and useDefaultAioHttpClientto use aiohttp as the underlying async transport - The SDK respects all httpx configuration including
timeout,limits,transport,mounts, andevent_hooks
Frequently Asked Questions
Can I use aiohttp instead of httpx with the Anthropic SDK?
Yes. Install the optional dependency with pip install "anthropic[aiohttp]" and pass an instance of DefaultAioHttpClient (or any httpx.AsyncClient configured with the aiohttp transport) to the http_client parameter of AsyncAnthropic. This is implemented in src/anthropic/_base_client.py.
What happens if I pass the wrong client type to the SDK?
The SDK validates the client type in src/anthropic/_client.py (lines 75-84). Passing a synchronous httpx.Client to AsyncAnthropic or an httpx.AsyncClient to the synchronous Anthropic class raises a clear TypeError indicating the expected client type for that class.
How do I configure proxy settings when using a custom HTTP client?
When using DefaultHttpxClient or DefaultAsyncHttpxClient, the SDK automatically reads HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables via the helper in src/anthropic/_utils/_httpx.py. For fully custom clients, configure the mounts parameter directly on your httpx.Client instance before passing it to the SDK.
Will the SDK close my custom HTTP client automatically?
No. The SDK deliberately does not close custom clients passed via http_client to avoid interfering with connection reuse patterns. You must manage the client lifecycle yourself, including calling .close() or using the client as a context manager (with httpx.Client() as client:) in your application code.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →