No KYC — no ID, no selfie, no documents · Pay in crypto: BTC, USDT, USDC, ETH, SOL, LTC
Buy with crypto

Guide · Python

Python proxies: requests, httpx, aiohttp and Scrapy

Working code for the four Python clients people use most, with one helper that builds targeted and sticky proxy URLs.

Last updated: · 7 min read

Quick answer

How do I use proxies in Python?

Pass a proxy URL such as http://USERNAME-country-ae:[email protected]:7777 to your HTTP client. Nameless Proxy, a privacy-first, no-KYC proxy provider, works with requests, httpx, aiohttp and Scrapy, and with socks5h:// on port 7778. Targeting lives in the username. Residential traffic starts at $0.53/GB. No KYC — no ID, no selfie, no documents. Pay in crypto.

Python setup at a glance

Proxy URLhttp://USER-country-xx:[email protected]:7777
SOCKS5socks5h://…:7778 with requests[socks]
requestsproxies={"http": url, "https": url}
httpx 0.26+httpx.Client(proxy=url) and httpx.AsyncClient(proxy=url)
aiohttpsession.get(url, proxy=proxy_url) (HTTP proxies)
Scrapyrequest.meta["proxy"], set by a downloader middleware
Sticky IPAdd -session-{id}-ttl-{minutes} after the city, for up to 60 minutes

How do I use a proxy with requests?

Give requests the same proxy URL for both http and https keys. HTTPS targets go through a CONNECT tunnel, so the TLS connection stays between your script and the site. Always set a timeout.

requests: one call through a UAE IP
# pip install requests
import requests

USERNAME = "USERNAME"   # base proxy username from the client area
PASSWORD = "PASSWORD"   # proxy password (not your account password)
HOST = "gw.namelessproxy.com"
HTTP_PORT = 7777
SOCKS_PORT = 7778

proxy = f"http://{USERNAME}-country-ae:{PASSWORD}@{HOST}:{HTTP_PORT}"
proxies = {"http": proxy, "https": proxy}

r = requests.get("https://api.ipify.org?format=json", proxies=proxies, timeout=30)
print(r.json())   # {'ip': '...'}

How do I build targeted and sticky proxy URLs?

Use one helper for every library. The username follows USERNAME-country-{cc}-city-{city}-session-{id}-ttl-{minutes}, so the helper adds parts in that order: country, then city, then session and TTL. Without a session you get a rotating IP; with one, the IP stays the same while the TTL lasts.

proxy_url(): one place for targeting
import uuid

def proxy_url(country, city=None, session=None, ttl=30, scheme="http"):
    """Build a gateway URL. Targeting lives in the username, in this order:
    country -> city -> session -> ttl."""
    user = f"{USERNAME}-country-{country.lower()}"
    if city:
        user += f"-city-{city.lower().replace(' ', '_')}"
        if session:
            user += f"-session-{session}-ttl-{ttl}"
    port = SOCKS_PORT if scheme.startswith("socks") else HTTP_PORT
    return f"{scheme}://{user}:{PASSWORD}@{HOST}:{port}"

def new_session():
    """A fresh session ID = a fresh sticky IP."""
    return uuid.uuid4().hex[:10]

# Rotating IP in Egypt, and a sticky IP in Abu Dhabi for 30 minutes
rotating = proxy_url("eg")
sticky = proxy_url("ae", city="Abu Dhabi", session=new_session(), ttl=30)

How do I use SOCKS5 in Python?

Install the SOCKS extra and use the socks5h:// scheme. The h makes the proxy resolve hostnames, so DNS lookups also exit in the target country. Plain socks5:// resolves DNS on your machine.

requests over SOCKS5
# pip install "requests[socks]"
# socks5h:// = the proxy resolves DNS, so lookups also exit in the target country
proxy = proxy_url("ke", scheme="socks5h")
r = requests.get("https://api.ipify.org", proxies={"http": proxy, "https": proxy}, timeout=30)
print(r.text)

How do I retry failed requests on a new IP?

Retry on connection errors and on 429 and 5xx responses, with exponential backoff and a little random delay. With a rotating username, each new connection can exit from a new IP, so a retry is also a fresh IP. For sticky work, start a new session ID when an IP fails.

Backoff and retry
import random
import time

RETRY_STATUS = {429, 500, 502, 503, 504}

def fetch(url, country="ae", attempts=4):
    """Retry with exponential backoff. Each attempt opens a new connection,
    so a rotating username exits from a new IP."""
    for attempt in range(attempts):
        proxy = proxy_url(country)
        try:
            r = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=30)
            if r.status_code not in RETRY_STATUS:
                return r
        except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
            pass  # ProxyError is a ConnectionError: retry on a new IP
        time.sleep(min(2 ** attempt + random.random(), 30))
    raise RuntimeError(f"Giving up on {url} after {attempts} attempts")

How do I use httpx, sync and async?

Since httpx 0.26, a client takes a single proxy= argument; the old proxies= was removed in 0.28. A client keeps connections alive, and requests on one kept-alive connection share an exit IP. Open a new client, or use a sticky session on purpose, depending on what you need.

httpx: sticky client and async batch
# pip install httpx   (0.26 or later: the argument is "proxy", not "proxies")
import asyncio
import httpx

# Sync: one sticky IP in Nairobi for 10 minutes
with httpx.Client(proxy=proxy_url("ke", city="nairobi", session=new_session(), ttl=10), timeout=30) as client:
    print(client.get("https://api.ipify.org").text)

# Async: 20 connections at most, rotating IPs in Nigeria
async def main(urls):
    limits = httpx.Limits(max_connections=20)
    async with httpx.AsyncClient(proxy=proxy_url("ng"), timeout=30, limits=limits) as client:
        results = await asyncio.gather(*(client.get(u) for u in urls), return_exceptions=True)
    for url, res in zip(urls, results):
        print(url, res.status_code if isinstance(res, httpx.Response) else repr(res))

asyncio.run(main(["https://api.ipify.org"] * 5))

How do I run many requests with aiohttp?

aiohttp takes the proxy per request, with the credentials inside the URL. It supports HTTP proxies only; for SOCKS5 you need an extra package such as aiohttp-socks. Cap concurrency with a semaphore: start around 10 to 20 parallel requests and raise it while your error rate stays low.

aiohttp with a concurrency cap
# pip install aiohttp   (HTTP proxies only; the credentials can sit in the proxy URL)
import asyncio
import aiohttp

async def fetch(session, url, sem):
    async with sem:
        async with session.get(url, proxy=proxy_url("eg")) as r:
            return r.status, await r.text()

async def main(urls):
    sem = asyncio.Semaphore(20)   # concurrency cap
    timeout = aiohttp.ClientTimeout(total=30)
    async with aiohttp.ClientSession(timeout=timeout) as session:
        results = await asyncio.gather(*(fetch(session, u, sem) for u in urls), return_exceptions=True)
    print(results)

asyncio.run(main(["https://api.ipify.org"] * 5))

How do I add the proxy to Scrapy?

Write a small downloader middleware that sets request.meta["proxy"]. Scrapy's built-in HttpProxyMiddleware then turns the credentials into a Proxy-Authorization header. Give your middleware a number below 750 so it runs first. Per-request meta keys let one spider mix countries and sticky sessions.

middlewares.py
# myproject/middlewares.py
USERNAME = "USERNAME"
PASSWORD = "PASSWORD"
GATEWAY = "gw.namelessproxy.com:7777"

class NamelessProxyMiddleware:
    """Set the proxy per request from request.meta:
    country (default 'ae'), optional city, optional session + ttl."""

    def process_request(self, request, spider):
        meta = request.meta
        user = f"{USERNAME}-country-{meta.get('country', 'ae')}"
        if meta.get("city"):
            user += f"-city-{meta['city']}"
            if meta.get("session"):
                user += f"-session-{meta['session']}-ttl-{meta.get('ttl', 10)}"
        # Scrapy's HttpProxyMiddleware turns the credentials into Proxy-Authorization
        meta["proxy"] = f"http://{user}:{PASSWORD}@{GATEWAY}"
settings.py
# myproject/settings.py
DOWNLOADER_MIDDLEWARES = {
    # Below 750 so it runs before Scrapy's built-in HttpProxyMiddleware
    "myproject.middlewares.NamelessProxyMiddleware": 350,
}
CONCURRENT_REQUESTS = 16
DOWNLOAD_TIMEOUT = 30
RETRY_TIMES = 3
RETRY_HTTP_CODES = [429, 500, 502, 503, 504, 408]
AUTOTHROTTLE_ENABLED = True
ROBOTSTXT_OBEY = True

# In a spider:
# yield scrapy.Request(url, meta={"country": "sa", "city": "riyadh", "session": "cart01"})

Frequently asked questions

Why do I get a 407 or ProxyError in Python?

A 407 means the gateway rejected the credentials. Check the base username and the proxy password in the client area, the order of the targeting parts, and any special characters in the password, which must be URL-encoded. A ProxyError without 407 usually means a wrong port or a firewall. Test the same URL with curl from the quick-start guide.

Why does my IP not change between requests?

Your client is probably reusing a kept-alive connection. A requests.Session, an httpx client or an aiohttp session keeps connections open, and one connection keeps one exit IP. For a new IP per request, call requests.get without a session or open a new client. If you added a session ID, the IP is sticky on purpose.

Should I use requests, httpx or aiohttp?

Use requests for simple scripts and small jobs. Use httpx when you want one library for both sync and async code, or HTTP/2. Use aiohttp for large async crawls where you control concurrency yourself. Use Scrapy when you need a full crawler with scheduling, retries and pipelines. All four work with the same proxy URL.

Can one script use several countries at once?

Yes. Targeting is part of each proxy URL, so build a different URL per request or per client: proxy_url("ae") for the UAE and proxy_url("ng") for Nigeria, for example. Traffic is billed from the same balance whatever the country, and the price per GB does not change by country.

How much traffic does a scraper use?

It depends on the pages: an HTML page is often tens to hundreds of kilobytes, while images and scripts add much more. Traffic is counted in decimal GB (1 GB = 1,000,000,000 bytes), and the client area shows daily usage per subscription and sub-user. Fetch only what you parse and skip images to keep costs down.

Does the Python code work with dedicated mobile ports?

Yes, with the port's own host, port, username and password from the client area instead of the gateway values. A dedicated port's country and carrier are chosen when you rent it, and you can move it later. To change its IP from Python, see the mobile IP rotation guide.

Run your Python code through residential IPs

From $0.53/GB, paid in crypto. No KYC — no ID, no selfie, no documents.

From $0.53/GB · no KYC

Buy proxies