Skip to content

Python requests Rotating Proxy: Pool vs Gateway, Retries

Two ways to rotate, when each fits, and retry code that does not burn your traffic on a wrong login.

Pool or gateway: what you are choosing between

A pool is a list of proxies that you keep and rotate yourself: each entry is one IP with its own host, port and login. Your code decides which one a request uses, and it knows which one failed.

A gateway is one entry point. You send every request to the same address and the service picks the exit IP. You do not hold a list, and rotation follows the mode you chose when you generated the proxy.

Pool or gateway: which fits

Pool or gateway: which fits
ItemIP pool in your codeGateway entry
Who picks the exit IPYour code, from the listThe service, by the mode you generated
Typical productStatic ISP IPs, one entry per IP; up to 100 per orderRotating residential, billed per GB
When an IP failsYou skip it and try the next entryA new connection normally gets another IP in the mode that rotates
Same IP across several requestsReuse the same entry; the IP does not rotate during the leaseSticky mode, or one Session on one connection
What you maintainThe list, renewals and expiry datesOne entry; the country is part of the proxy you generated

Sources: the Proxy302 product facts file and order page, 15 November 2026. Neither option promises how a target site will react.

Pool: round robin with a retry on the next IP

# pip install requests
import itertools
import time
import requests

# One entry per static IP, copied from My assets (LOGIN:PASSWORD@HOST:PORT)
POOL = [
    "http://LOGIN1:PASSWORD1@HOST1:PORT1",
    "http://LOGIN2:PASSWORD2@HOST2:PORT2",
    "http://LOGIN3:PASSWORD3@HOST3:PORT3",
]
URL = "https://ipinfo.io/ip"
ring = itertools.cycle(POOL)  # round robin; random.choice(POOL) also works

def fetch(url, tries=3):
    last = None
    for attempt in range(tries):
        proxy = next(ring)  # a failed try moves on to the next IP in the pool
        try:
            r = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=(5, 20))
            if r.status_code not in (429, 502, 503, 504):
                return r
        except (requests.exceptions.ProxyError,
                requests.exceptions.Timeout,
                requests.exceptions.ConnectionError) as exc:
            last = exc
        time.sleep(0.5 * 2 ** attempt)  # 0.5 s, 1 s, 2 s
    raise RuntimeError("gave up after %d tries: %s" % (tries, last))

for _ in range(6):
    print(fetch(URL).text.strip())

Example only: fill in HOST, PORT, LOGIN and PASSWORD for each IP from My assets. If a password contains characters such as @ or :, encode it with urllib.parse.quote(password, safe='') before putting it in the URL.

Gateway: a new Session for each new IP, and no retry on 407

# pip install requests
import time
import requests

GATEWAY = "http://LOGIN:PASSWORD@HOST:PORT"  # one gateway entry from My assets
PROXIES = {"http": GATEWAY, "https": GATEWAY}
URL = "https://ipinfo.io/ip"

def fetch(url, tries=3):
    last = None
    for attempt in range(tries):
        # A new Session starts with an empty connection pool, so it opens a new connection.
        # In "new IP per connection" mode that is what gives you a new exit IP.
        with requests.Session() as s:
            try:
                r = s.get(url, proxies=PROXIES, timeout=(5, 20))
            except requests.exceptions.ProxyError as exc:
                if "407" in str(exc):
                    raise  # wrong login: a retry only repeats the refusal
                last = exc
            except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as exc:
                last = exc
            else:
                if r.status_code not in (429, 502, 503, 504):
                    return r
        time.sleep(0.5 * 2 ** attempt)
    raise RuntimeError("gave up after %d tries: %s" % (tries, last))

print([fetch(URL).text.strip() for _ in range(5)])

Example only. Generate the proxy in a mode that gives a new IP per connection first, then copy HOST, PORT, LOGIN and PASSWORD from My assets. For HTTP the rotating residential port is 2222; for SOCKS5 it is 3333 and the URL scheme becomes socks5h:// (pip install "requests[socks]").

Sessions, connections and why the IP repeats

The Requests documentation says a Session uses urllib3 connection pooling, so several requests to the same host reuse one TCP connection. In a gateway mode that changes the IP per connection, that reuse is why the IP does not change between calls. requests.get() outside a Session builds a throwaway Session each time, so it opens a new connection.

One more trap: session.proxies can be overridden by proxy variables in your environment, as the documentation warns. Pass proxies on each call, as the examples do, so the code uses the proxy you meant.

If you need one IP for a login or a multi-step flow, do not fight the connection: use sticky mode, or one static IP, and keep one Session for the whole flow.

What to retry, and what not to

Retry timeouts, connection resets, 429 and 502, 503, 504. Wait longer after each failure: urllib3 Retry computes the pause as backoff_factor * 2 ** (number of previous retries), and it honours Retry-After for 429 and 503. Cap the number of tries.

Do not retry a 407: the proxy refused your login, and the next attempt gets the same answer. Do not answer a stream of 429 from the target site with more IPs either; slow down, because the limit is about your request rate. Retry only requests that are safe to repeat, which for urllib3 means idempotent methods by default.

If you prefer the library route, mount Retry(total=3, backoff_factor=0.5, status_forcelist=[429, 502, 503, 504]) on an HTTPAdapter, as the Requests documentation shows. A hand-written loop is easier when you also want to switch IP between attempts.

Set it up with Proxy302

  1. Step 1: Pick the model

    For a gateway, open the rotating residential page and choose the Exit mode: Choose region / new IP per connection for independent pages, or sticky for one flow. For a pool, open the static ISP page and set Quantity to the number of IPs you want in the list.

  2. Step 2: Protocol and generate

    Keep Protocol on HTTP (port 2222) or choose SOCKS5 (port 3333), then click Review cost and generate. The protocol is fixed per IP for static IPs.

  3. Step 3: Copy the details

    Open My assets and copy HOST, PORT, USERNAME and PASSWORD into the code above.

  4. Step 4: Run and read the output

    Run the script. With a pool you should see the entries in turn; with a gateway in per-connection mode the list of five IPs should change from call to call.

    Expected result A list of exit IPs printed by ipinfo.io.

Troubleshooting

The gateway returns the same IP on every call

Check Did you reuse one Session, or generate the proxy in a sticky mode?

Fix Open a new Session for each request, or generate a new proxy in the new-IP-per-connection mode; existing proxies do not change when you switch the mode.

Stop when If a new Session still repeats the IP, test with curl -x to tell the code from the proxy.

ProxyError with 407

Check Are LOGIN and PASSWORD copied in full, with special characters encoded?

Fix Copy them again from My assets and encode the password with urllib.parse.quote; do not retry in a loop.

Stop when After one correct copy still fails, open a ticket with the order number.

Timeouts on every request

Check Are HOST, PORT and protocol right (HTTP 2222 or SOCKS5 3333 on the gateway)?

Fix Fix the port or protocol, keep the connect timeout short and add the backoff loop above.

Stop when A pool entry that times out repeatedly: skip it and check its end date in My assets.

A stream of 429 from the target site

Check How many requests per second do you send?

Fix Lower the rate and add a pause; Retry honours Retry-After for 429.

Stop when More IPs do not fix a request rate that is too high.

Prices and limits

Rotating residential traffic is billed per GB: the Budget line is US$1.50 per GB (US$1.35 per GB in a 100 GB package) and the Premium line is US$5.00 per GB. A static ISP IP costs US$0.50 for one day and US$7.99 for 30 days, about US$0.27 a day (7.99 / 30). There is no free trial, and the smallest purchase is 1 GB or one IP for one day.

FAQ

How do I rotate proxies in Python requests?

Either keep a list of proxies and pick one for each request in your own code, or send requests to one gateway in a mode that gives a new IP per connection and open a new Session for each request.

Why does my requests.Session keep the same IP?

A Session reuses the TCP connection to the same host, and a gateway in per-connection mode changes the IP only when a new connection opens. Use a new Session per request, or a proxy generated in the per-connection mode.

Should I retry on a 407 error?

No. A 407 means the proxy refused the login, so a retry gets the same answer. Fix LOGIN and PASSWORD first.

How long should I wait between retries?

Grow the pause after each failure. urllib3 Retry uses backoff_factor * 2 ** (number of previous retries) seconds, so a backoff_factor of 0.5 waits 0.5 s, 1 s, 2 s and so on.

Do I need requests[socks] for SOCKS5?

Yes. Install it with pip install "requests[socks]" and use a socks5h:// URL if you want the proxy to resolve domain names.

Reference links

4
  1. Requests: Advanced Usage

    Official documentation · Confirmed on:

    Read on 15 November 2026: a Session uses urllib3 connection pooling and reuses the TCP connection to the same host; the proxies argument, and that session.proxies can be overridden by environment proxies; credentials go in the http://user:pass@host form; socks5h resolves DNS on the proxy; no timeout unless one is set; retries use urllib3 Retry mounted on an HTTPAdapter.

  2. urllib3: Retry

    Official documentation · Confirmed on:

    Read on 15 November 2026: Retry has total, backoff_factor and status_forcelist; the sleep is backoff_factor * 2 ** (number of previous retries); by default only idempotent methods are retried; the Retry-After header is honoured for 413, 429 and 503.

  3. Proxy302 rotating residential order page

    Product observation · Confirmed on:

    Read the Exit mode field on 15 November 2026: Global rotation, Choose region / sticky IP, and Choose region / new IP per connection; the form starts on the sticky option; the new IP comes per connection, not per request.

  4. Proxy302 product facts and price list

    Product observation · Confirmed on:

    Product facts file of the site, checked 15 November 2026: rotating residential Budget US$1.50 per GB (US$1.35 per GB in a 100 GB package) and Premium US$5.00 per GB; static ISP per IP US$0.50 for 1 day and US$7.99 for 30 days; gateway ports HTTP 2222 and SOCKS5 3333; quantity 1 to 100 per order for static IPs; no free trial.

Ready to try it?

Create an account, top up once, then pick rotating residential, static ISP or datacenter IPs and have one running in your browser within minutes.