How to use proxies with Python HTTPX and aiohttp
In HTTPX, pass the proxy URL when you create the client: httpx.AsyncClient(proxy="http://USERNAME:PASSWORD@HOST:PORT"). In aiohttp, pass it per request: session.get(url, proxy="http://USERNAME:PASSWORD@HOST:PORT").
What you need
- An active CleanProxies plan: static ISP proxies for fixed US IPs, or rotating residential / mobile proxies for pools. The trial works too.
- Your credential line from the dashboard's proxy manager: host (or IP), port, username and password.
- Python 3.9 or later.
pip install httpx(add"httpx[socks]"for SOCKS5) and/orpip install aiohttp(addaiohttp-socksfor SOCKS5).
New to proxies? For the overview, read Using proxies with cURL, Python and Node.js and Best residential proxies for web scraping. This guide goes deeper on Python HTTPX & aiohttp only.
Your CleanProxies credentials
| Product | Line in your dashboard | Notes |
|---|---|---|
| Static ISP proxies | IP:PORT:USER:PASS | One line per dedicated IP. With IP whitelisting turned on, the line is just IP:PORT and no password is sent. |
| Rotating residential and mobile | HOST:PORT:USER:PASS | Generated in the proxy manager. The username carries the location and session you pick, so generate a new list to change them. |
Most tools want the same details as a URL: http://USERNAME:PASSWORD@HOST:PORT for HTTP(S) or socks5://USERNAME:PASSWORD@HOST:PORT for SOCKS5. The examples on this page use those placeholders; copy the host, port, username and password from your CleanProxies dashboard. To convert a whole list at once, paste it into the proxy list formatter.
How to set up CleanProxies in Python HTTPX & aiohttp
- 1
Pick the library
HTTPX has both sync and async clients and an API close to Requests; aiohttp is async-only and very fast for large crawls. - 2
Build the proxy URL
Usehttp://USERNAME:PASSWORD@HOST:PORTfor HTTP(S) orsocks5://USERNAME:PASSWORD@HOST:PORTfor SOCKS5. - 3
Attach it
HTTPX:proxy=on the client. aiohttp:proxy=on each request, or a SOCKS connector on the session. - 4
Limit concurrency
Use anasyncio.Semaphoreso you control how many requests hit each target at once.
HTTPX proxy example
HTTPX 0.28 removed the old proxies= argument. Use proxy= for a single proxy, or mounts= to route different URL patterns through different proxies.
import asyncio
import httpx
PROXY = "http://USERNAME:PASSWORD@HOST:PORT"
async def main():
async with httpx.AsyncClient(proxy=PROXY, timeout=30) as client:
r = await client.get("https://api.ipify.org")
print(r.text)
asyncio.run(main())client = httpx.Client(proxy="socks5://USERNAME:PASSWORD@HOST:PORT", timeout=30)
print(client.get("https://api.ipify.org").text)aiohttp proxy example
aiohttp takes HTTP(S) proxies per request (or as a session default). Put the credentials in the proxy URL: aiohttp 3.14 deprecated the separate proxy_auth= argument. For SOCKS5, the aiohttp-socks connector routes the whole session.
import asyncio
import aiohttp
async def main():
async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=30)) as session:
async with session.get(
"https://api.ipify.org",
proxy="http://USERNAME:PASSWORD@HOST:PORT",
) as r:
print(await r.text())
asyncio.run(main())from aiohttp_socks import ProxyConnector
connector = ProxyConnector.from_url("socks5://USERNAME:PASSWORD@HOST:PORT", rdns=True)
async with aiohttp.ClientSession(connector=connector) as session:
async with session.get("https://api.ipify.org") as r:
print(await r.text())rdns=True makes the proxy resolve hostnames, so DNS lookups don't leave from your own server.
Bounded concurrency across many proxies
import asyncio
import httpx
PROXIES = ["http://USER1:PASS1@IP1:PORT", "http://USER2:PASS2@IP2:PORT"]
URLS = [f"https://example.com/item/{i}" for i in range(100)]
async def main():
clients = [httpx.AsyncClient(proxy=p, timeout=30) for p in PROXIES]
limit = asyncio.Semaphore(20)
async def fetch(i, url):
async with limit:
r = await clients[i % len(clients)].get(url)
return r.status_code
print(await asyncio.gather(*(fetch(i, u) for i, u in enumerate(URLS))))
await asyncio.gather(*(c.aclose() for c in clients))
asyncio.run(main())Static ISP vs rotating residential in Python HTTPX & aiohttp
Static ISP proxies
Give each ISP proxy its own client: the client pools connections to one dedicated US IP, and cookies stay with the account that IP serves.
Rotating residential proxies
A client keeps connections alive, so requests can share an exit IP even on a rotating line. Create short-lived clients (or send Connection: close) when you need a new IP per request; use a sticky list for flows that must stay put.
Verify your exit IP
Run the first HTTPX example: it prints the exit IP. In aiohttp, compare await r.text() from https://api.ipify.org with and without the proxy= argument.
Open What is my IP? through the proxy to see the address and headers a website receives, or paste up to ten lines into the free proxy checker to test connectivity, latency and exit IP before you start.
Troubleshooting Python HTTPX & aiohttp proxy errors
| Problem | Likely cause | Fix |
|---|---|---|
| TypeError: unexpected keyword argument 'proxies' | HTTPX 0.28 removed proxies=. | Use proxy= (one proxy) or mounts= (per-pattern routing). |
| 407 Proxy Authentication Required | Wrong credentials, or a password with @ or : that broke the proxy URL. | Put the credentials in the proxy URL passed as proxy=; URL-encode special characters. |
| Using SOCKS proxy, but the 'socksio' package is not installed | HTTPX SOCKS extra missing. | pip install "httpx[socks]". |
| Many timeouts under load | Too many concurrent requests per IP for the target. | Lower the semaphore, add retries with backoff, and spread work across more IPs. |
| DNS lookups leak over SOCKS5 | Local resolution in the connector. | Set rdns=True in aiohttp-socks. |
Still stuck? Our 24/7 support team answers fast: contact us with the error and the line you used (leave the password out).
Python HTTPX & aiohttp proxy FAQs
HTTPX does by default (trust_env=True). aiohttp only does when you create the session with trust_env=True. An explicit proxy argument is clearer and works the same everywhere.