Proxy parsing, formatting & source management for aiohttp, camoufox & socks5
Go to file
disqualifier 993dd12fc2 add package: pyproject + src
AioProxies: proxy parsing/formatting (aiohttp/camoufox/socks5/url) and
source management (session template with {session} + caller fields,
rotating list, static, from_file). config-free, no module globals,
per-instance rotation, never sys.exits on a missing file. also exported
as ProxyManager / aioproxies. optional [net] extra adds aiohttp
current_ip/reset. src/ multi-module, hatchling, zero core deps.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-24 21:36:43 -04:00
src/aioproxies add package: pyproject + src 2026-06-24 21:36:43 -04:00
.gitignore init: proxy parsing, formatting & source management 2026-06-24 21:16:46 -04:00
pyproject.toml add package: pyproject + src 2026-06-24 21:36:43 -04:00
README.md init: proxy parsing, formatting & source management 2026-06-24 21:16:46 -04:00

aioproxies

Proxy parsing, formatting, and source management. Renders proxies for aiohttp/aioweb, camoufox, and socks5; manages session templates (with caller-supplied fields like country/ttl), rotating lists, or a static proxy. Credentials are always injected — never hardcoded.

Install

aioproxies @ git+ssh://git@git.rethinkstudios.io/rethink-public/aioproxies.git@v0.1.0
# network helpers (current_ip / reset) need the extra:
aioproxies[net] @ git+ssh://git@git.rethinkstudios.io/rethink-public/aioproxies.git@v0.1.0

The core has no dependencies. The net extra adds aiohttp for current_ip / reset.

Formatting

from aioproxies import parse

p = parse("1.2.3.4:8080:user:pass")        # or "host:port"
p.aiohttp()    # {"http": "...", "https": "..."}  -> aioweb ExtendedSession(proxies=)
p.camoufox()   # {"server": "...", "username": ..., "password": ...}
p.socks5()     # {"server": "socks5://...", ...}
p.url()        # "http://user:pass@host:port"

Sources

Construct with exactly one source:

from aioproxies import AioProxies

# rotating list (round-robin, shuffled by default)
m = AioProxies(proxies=["h1:1:u:p", "h2:2:u:p"])
m.get()        # next proxy as an aiohttp dict

# session template — {session} is filled with a fresh id each call
m = AioProxies(template="gw.example.io:9000:user_X,sess_{session}:pw")
# a bare {} also works and is treated as the session slot

# static
m = AioProxies(static="1.2.3.4:8080:u:p")

# from a file (raises FileNotFoundError if missing — never exits the process)
m = AioProxies.from_file("proxies.txt")

The class is also exported as ProxyManager and lowercase aioproxies (aliases of AioProxies) — use whichever reads best at your call site.

Location / per-call fields

Templates can carry extra named placeholders the caller fills per call; the lib always fills {session}. This replaces the old location_proxy(country, ttl) / dynamic_proxy(user) helpers — one template, fields supplied at call time:

m = AioProxies(template="portal.io:1080:user_X,country_{country},ttl_{ttl},sess_{session}:pw")

m.next(country="ca", ttl=30)   # lib fills {session}; caller fills {country}/{ttl}
m.get(country="us", ttl=60)    # same, returned as an aiohttp dict

Provider-specific values (account, password, the host, country codes, ASN tables, which providers support geo) are your config — bake them into the template or pass them as fields. The lib only fills placeholders; it never holds credentials.

Provider session strings (e.g. mobile rotation)

# creds come from your config — placeholders shown here
template = (
    "portal.anyip.io:1080:"
    "user_{ACCOUNT},type_mobile,country_{{country}},asn_{{asn}},session_{{session}}:{PASSWORD}"
).format(ACCOUNT=acct, PASSWORD=pw)   # double-braced fields survive this .format()
m = AioProxies(template=template)     # and stay as {country}/{asn}/{session} for the lib
m.next(country="us", asn="7922")

The credentials are baked in once with .format(); the per-call fields and {session} are double-braced ({{country}}) so they pass through that .format() untouched and remain for next(**fields) / the lib to fill.

Network helpers (optional)

from aioproxies.net import current_ip, reset

ip = await current_ip("1.2.3.4:8080:u:p")   # egress ip through the proxy (ipify by default)
await reset("https://provider/reset-url")    # rotate upstream ip

current_ip defaults to ipify and is opt-in; pass test_url= to point elsewhere.

Notes

  • No module-level globals; rotation state is per-instance.
  • A missing proxy file raises, it does not exit the process.
  • Country/ASN tables, provider accounts, and reset URLs are project config — inject them; do not hardcode credentials in shared code.