Python httpx and aiohttp with AeonProxy proxies

Route httpx and aiohttp requests, sync or async, through residential or mobile IPs, with the login in the proxy URL.

Protocols
HTTP and HTTPS sites over an HTTP proxy, or SOCKS5 with httpx[socks] or aiohttp-socks
Authentication
Login and password in the proxy URL
Rotation
A new IP per connection, or one IP per -sid- key for up to 60 minutes
Works with
Residential and mobile proxies

Before you start

  • Python 3.10 or newer, then pip install httpx or pip install aiohttp, or both.
  • Your proxy login and password from the Residential or Mobile page of the dashboard.
  • Traffic on the product you use: a login without traffic gets 402.
Connection details
Host
gate.aeonproxy.com
Port (HTTP / HTTPS)
7000
Port (SOCKS5)
7001
Login
your proxy login, with targeting keys if you need them: LOGIN-cc-us-sid-abc123
Password
your proxy password

Copy the login and password from the Residential or Mobile page of the dashboard; the generator there also writes ready lines. Key syntax: targeting and sessions.

httpx: rotating proxy

Pass the proxy URL with the login and password as proxy=. The scheme stays http:// for HTTPS sites: httpx opens a CONNECT tunnel through the proxy.

import httpx

proxy = "http://LOGIN-cc-us:[email protected]:7000"
limits = httpx.Limits(max_keepalive_connections=0)  # a new connection, so a new IP, per request

with httpx.Client(proxy=proxy, limits=limits, timeout=30) as client:
    for _ in range(3):
        print(client.get("https://api.ipify.org").text)

A Client sends the next request down the open connection, and the gateway picks the IP per connection: without limits, our three test requests shared one tunnel and one IP.

httpx: sticky session with AsyncClient

Add -sid- with a key of letters and digits, and -ttl- with the minutes to keep the IP (1–60). Every connection with the same key leaves from the same IP, so the five parallel requests below share it.

import asyncio
import secrets
import httpx

async def main():
    sid = secrets.token_hex(4)  # one key = one IP for up to ttl minutes
    proxy = f"http://LOGIN-cc-de-sid-{sid}-ttl-30:[email protected]:7000"
    async with httpx.AsyncClient(proxy=proxy, timeout=30) as client:
        replies = await asyncio.gather(*(client.get("https://api.ipify.org") for _ in range(5)))
        print([r.text for r in replies])  # the same IP five times

asyncio.run(main())

httpx: SOCKS5

Install pip install "httpx[socks]" and use port 7001. With socks5:// or socks5h://, httpx sends the host name to the proxy, so DNS is resolved there and not on your machine.

import httpx

proxy = "socks5://LOGIN-cc-gb:[email protected]:7001"
with httpx.Client(proxy=proxy, timeout=30) as client:
    print(client.get("https://api.ipify.org").text)

aiohttp: HTTP proxy

aiohttp takes proxy= per request or once per ClientSession. A session also reuses connections, so the connector below has force_close=True for a new IP per request.

import asyncio
import aiohttp

PROXY = "http://LOGIN-cc-us:[email protected]:7000"

async def main():
    connector = aiohttp.TCPConnector(force_close=True)  # no keep-alive: a new IP per request
    timeout = aiohttp.ClientTimeout(total=30)
    async with aiohttp.ClientSession(connector=connector, timeout=timeout) as session:
        for _ in range(3):
            async with session.get("https://api.ipify.org", proxy=PROXY) as r:
                print(await r.text())

asyncio.run(main())

aiohttp writes the proxy URL, password included, into ClientHttpProxyError messages. To keep the password out of logs, send it as a header instead: proxy_headers={"Proxy-Authorization": aiohttp.encode_basic_auth(login, password)} (aiohttp 3.14 or newer). The older proxy_auth=aiohttp.BasicAuth(...) is deprecated.

aiohttp: one sticky IP per worker

Give each task its own key. The three workers below run in parallel, each on its own IP for up to 15 minutes.

import asyncio
import secrets
import aiohttp

async def worker(session, n):
    sid = secrets.token_hex(4)  # each worker keeps its own IP
    proxy = f"http://LOGIN-cc-us-sid-{sid}-ttl-15:[email protected]:7000"
    for _ in range(2):
        async with session.get("https://api.ipify.org", proxy=proxy) as r:
            print(n, sid, await r.text())

async def main():
    async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=30)) as session:
        await asyncio.gather(*(worker(session, n) for n in range(3)))

asyncio.run(main())

aiohttp: SOCKS5

aiohttp has no SOCKS support of its own: a socks5:// URL in proxy= fails with Bad status line. Install aiohttp-socks and pass its connector to the session; rdns=True, its default, sends the host name to the proxy.

import asyncio
import aiohttp
from aiohttp_socks import ProxyConnector

async def main():
    connector = ProxyConnector.from_url("socks5://LOGIN-cc-gb:[email protected]:7001", rdns=True)
    async with aiohttp.ClientSession(connector=connector) as session:
        async with session.get("https://api.ipify.org") as r:
            print(await r.text())

asyncio.run(main())

If it does not work

What you seeWhat to check
httpx.ProxyError: 407 Proxy Authentication Required or ClientHttpProxyError: 407The login, the password, or a key in the login that is not in the lists (a misspelled city, for example).
The same errors with 402 or 502402: no traffic left on the product, or the sub-user reached its limit. 502: the exit failed; retry, and a rotating login takes a new IP.
httpx.ConnectTimeout or ReadTimeouthttpx gives up after 5 seconds by default. Pass timeout=30, as in the examples.
TypeError: ... unexpected keyword argument 'proxies'Code written for older httpx: 0.28 removed proxies=. Use proxy=.
ImportError: Using SOCKS proxy, but the 'socksio' package is not installedInstall httpx[socks].
Invalid username/password (httpx) or Username and password authentication failure (aiohttp-socks)The SOCKS5 login: the same checks as for 407.
Every request shows the same IPThe client reuses one connection. Turn keep-alive off as shown, or give each request its own -sid- key.

Questions

In httpx a client has one proxy, so open one client per country. In aiohttp the proxy is set per request, so one session can send each request with its own -cc- key.

As many as your code opens: bought traffic has no thread or connection limit on the gateway. Both libraries cap a client at 100 connections by default; raise httpx.Limits(max_connections=...) or TCPConnector(limit=...) if you need more.

Proxy questions? Ask support in the live chat.