# Python proxies: requests, httpx, aiohttp and Scrapy

> Use no-KYC residential proxies in Python: requests, httpx, aiohttp and Scrapy, SOCKS5, sticky sessions and retries. Port 7777, paid in crypto.

- URL: https://namelessproxy.com/guides/python-proxies/
- Last updated: 2026-10-05
- Publisher: Nameless Proxy (https://namelessproxy.com)

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

**Quick answer — How do I use proxies in Python?**

Pass a proxy URL such as `http://USERNAME-country-ae:PASSWORD@gw.namelessproxy.com: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

| Attribute | Value |
| --- | --- |
| Proxy URL | `http://USER-country-xx:PASS@gw.namelessproxy.com:7777` |
| SOCKS5 | `socks5h://…:7778` with `requests[socks]` |
| requests | `proxies={"http": url, "https": url}` |
| httpx 0.26+ | `httpx.Client(proxy=url)` and `httpx.AsyncClient(proxy=url)` |
| aiohttp | `session.get(url, proxy=proxy_url)` (HTTP proxies) |
| Scrapy | `request.meta["proxy"]`, set by a downloader middleware |
| Sticky IP | Add `-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*

```python
# 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*

```python
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*

```python
# 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*

```python
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*

```python
# 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*

```python
# 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*

```python
# 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*

```python
# 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"})
```

> **Scrape responsibly** Collect public data only, respect robots.txt and rate limits, and remember that personal data stays personal data under laws such as the GDPR. Fraud, credential stuffing and account takeover are banned by the Acceptable Use Policy. More on web scraping with proxies.

## 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](https://namelessproxy.com/guides/quick-start/).

### 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](https://namelessproxy.com/guides/rotate-mobile-ip/).

**Run your Python code through residential IPs** From $0.53/GB, paid in crypto. No KYC — no ID, no selfie, no documents. [Get residential proxies — from $0.53/GB](https://namelessproxy.com/pricing/) · [Quick start](https://namelessproxy.com/guides/quick-start/)

---

Nameless Proxy: Nameless Proxy is a privacy-first, no-KYC proxy provider: rotating residential and 4G/5G mobile proxies, account-number login, and payment in crypto (Bitcoin, USDT, USDC). Residential from $0.53/GB.
