HTTPX Proxy Guide: HTTP, SOCKS5 and Async Python Examples
An HTTPX proxy configuration belongs on the client that sends your requests. Start with one known endpoint, confirm authentication and routing, then reuse that client for a batch. This guide covers HTTP proxies, HTTPS destinations through CONNECT, optional SOCKS5 support, and bounded asynchronous requests. The examples use the HTTPX 0.28 API; older tutorials using proxies= need updating because that argument was removed in 0.28. HTTPX release notes document the change.
If you are choosing a Python client, the Python proxies overview explains the broader options. For the synchronous Requests library, use the separate Python Requests proxy tutorial.
Install HTTPX and keep configuration outside code
python -m pip install "httpx>=0.28,<0.29"
python -c "import httpx; print(httpx.__version__)"
Read BP_PROXY_HOST, BP_PROXY_PORT, BP_PROXY_USER, BP_PROXY_PASSWORD, and BP_TARGET_URL from your process environment. These are application-specific variable names: HTTPX does not automatically interpret them. Set the target to a diagnostic endpoint you control before using your normal workload. Supply credentials through your deployment’s secret mechanism, and avoid putting a password in command history.
Check the host and port against your account’s endpoint details. A copied host:port pair still needs a URL scheme; the proxy formatter helps identify format differences. Keep a stable label such as proxy-a for diagnostics rather than displaying the complete authenticated URL.
Authenticate an HTTP proxy with a synchronous client
Build the URL from separate components. Encoding the username and password with quote(..., safe="") prevents characters such as @, /, and # from changing URL structure. Encode each credential once, before joining it into the URL. Proxy authentication is different from destination authentication: auth= on a request is not the place for your proxy password.
import os
from urllib.parse import quote
import httpx
user = quote(os.environ["BP_PROXY_USER"], safe="")
password = quote(os.environ["BP_PROXY_PASSWORD"], safe="")
host = os.environ["BP_PROXY_HOST"]
port = int(os.environ["BP_PROXY_PORT"])
proxy = f"http://{user}:{password}@{host}:{port}"
timeout = httpx.Timeout(20.0, connect=5.0, pool=5.0)
with httpx.Client(proxy=proxy, timeout=timeout,
trust_env=False, follow_redirects=False) as client:
response = client.get(os.environ["BP_TARGET_URL"])
response.raise_for_status()
print("status", response.status_code)
The context manager closes the client and its connections. Reuse it for several requests when possible. This example disables automatic redirects so the first response is visible during diagnosis; a redirect requires your own decision about the next destination. See the proxy authentication guide for username/password versus IP authorization.
Why an HTTPS destination often uses an HTTP proxy URL
In https://your-target.example/, the scheme describes the destination. In http://proxy.example:8080, it describes the connection to the proxy. For an HTTPS destination, an HTTP proxy can create a tunnel with CONNECT; HTTPX then negotiates TLS with the destination through that tunnel. Changing the proxy URL to https:// means requesting TLS to the proxy itself and requires a compatible endpoint. It is not required merely because your target uses HTTPS. HTTPX’s proxy documentation explains both forwarding and tunnelling.
Leave certificate verification enabled. A certificate error deserves a check of the trust chain, target hostname, and runtime certificates. Treat changing the scheme as a protocol choice, not a certificate workaround.
Use SOCKS5 when the endpoint supports it
python -m pip install "httpx[socks]>=0.28,<0.29"
For a SOCKS5 endpoint, construct the same credential-safe URL with socks5:// instead of http://, then pass it to Client(proxy=...) or AsyncClient(proxy=...). The extra installs HTTPX’s optional SOCKS dependency. Installing it does not convert an HTTP-only endpoint into a SOCKS service; confirm the protocol and port supplied for your proxy.
Keep protocol tests separate. A working HTTP connection to one port does not establish that SOCKS5 works on another. Verify a single request before adding scheduling, rotation, or retries.
Bound concurrency with one AsyncClient
The following block reuses the already constructed proxy and timeout. Each task waits for a semaphore slot, while the connection limit places a second bound on the client. Four is an example starting value, not a measured optimum. Increase it only after observing your endpoint’s capacity and the destination’s rate limits.
import asyncio
async def fetch_many(urls):
gate = asyncio.Semaphore(4)
limits = httpx.Limits(max_connections=4, max_keepalive_connections=4)
async with httpx.AsyncClient(proxy=proxy, timeout=timeout,
limits=limits, trust_env=False) as client:
async def fetch(url):
async with gate:
response = await client.get(url)
response.raise_for_status()
return response.status_code
return await asyncio.gather(*(fetch(url) for url in urls))
Creating a fresh client inside every task loses connection reuse. For a large input, feed a bounded worker queue instead of creating one task per URL. The downloadable example handles errors inside each task; the compact block above lets an error propagate to its caller. HTTPX’s async guide describes client lifetime and cleanup.
Set timeouts and identify the failing stage
The example gives connect and pool acquisition five seconds, with twenty seconds for read and write operations. HTTPX timeouts cover individual stages; they are not a single total deadline for an entire multi-request batch. A PoolTimeout can indicate local contention rather than an unreachable proxy. The timeout reference and connection limits explain those controls.
| Signal | First check |
|---|---|
ProxyError or CONNECT rejection |
Endpoint scheme, credentials, and permitted destination port. |
| HTTP 407 | Proxy authentication; for HTTPS, rejection may surface as a proxy exception. |
ConnectTimeout or ConnectError |
Proxy reachability, address, port, DNS, and firewall. |
PoolTimeout |
Concurrent work and whether responses/connections are being released. |
| HTTP 403 or 429 | Response source, destination policy, and request rate before deciding to retry. |
Catch HTTPStatusError for unsuccessful HTTP responses and RequestError for request failures. Log the exception class, status, attempt count, and a proxy label. Avoid logging str(exc), request headers, complete URLs, or response bodies by default. The exception hierarchy helps keep these cases distinct; our proxy error reference provides a broader diagnosis sequence.
HTTPX normally reads standard proxy environment variables. Here, trust_env=False keeps this client’s routing explicit; it also disables HTTPX’s environment-derived certificate settings, so configure an intended custom trust store explicitly. See the environment reference.
Download and verify the example
Download the HTTPX sync/async example. Its --check mode validates configuration without opening a connection. Run python -B httpx-proxy-examples.py --check, then remove --check for one real request. Add --async for a four-request batch or --scheme socks5 for a verified SOCKS endpoint. A successful status alone does not prove routing: compare the egress reported by your controlled endpoint, and use the proxy tester as a separate endpoint check.
Frequently asked questions
Can I pass proxy= to client.get()?
Configure the proxy when creating a Client or AsyncClient. Top-level httpx.get() accepts it, but a client’s request method does not use the same configuration signature.
Does HTTPX rotate proxies automatically?
No. Assign work to clients configured for your chosen endpoints. Track failures per endpoint and preserve one endpoint for a session that needs a stable egress address.
Does async make a blocked request succeed?
Concurrency changes scheduling. It does not change credentials, destination permissions, or a server’s response policy.
Which guide should I use for another async library?
The aiohttp guide covers sessions and proxy headers; the Scrapy guide covers crawler middleware. Browse the developer proxy examples for other clients.
For a stable endpoint to configure in your application, review the BuyProxies dedicated proxy plans and match the supplied protocol and authentication method to your workload.
Official sources
- HTTPX proxy configuration
- HTTPX async support
- HTTPX timeouts
- HTTPX resource limits
- HTTPX environment variables
- HTTPX exceptions
- HTTPX 0.28 release notes
- Python URL quoting
Technical references reviewed October 2, 2026. See our editorial policy and testing methodology.
