Link copied to clipboard!
ProductsPricingUse CasesSolutionsResourcesCompanyFAQ
Get Started
Home Blog Rotate Proxies Automatically
Guides

How to Rotate Proxies Automatically

How rotation works with sticky 4G proxies: change the IP on demand, rotate between several proxies in your own code and know when to keep the same IP.

Rotation spreads requests across IP addresses. You can change the IP on demand from your account or rotate between several proxies in your own code. This guide covers both.

“Rotating proxies” can mean several different things, and mixing them up leads to broken sessions and wasted traffic. Below you will find what each model does, when to use it and Python code for rotation across several proxies, with health tracking and per-proxy pacing.

Key takeaways
  • Your IP stays the same while you work. That is the right default for logins, checkouts and long sessions. After a pause of about 10 minutes without connections, the next connection can get a different IP.
  • Change the IP on demand between jobs, not in the middle of one.
  • To spread a workload, order several proxies and rotate between them in your own code.
  • Rotate on errors and on a plan you choose, and never faster than a site allows.
  • Rotation does not entitle you to exceed a site’s rate limits or ignore its terms.

1.Three models of rotation

Providers use the word “rotation” for different things. This table separates them and shows what you get with Xameleon.

ModelHow it worksSuitsWith Xameleon
Sticky IPThe IP stays while you workLogins, checkouts, long sessions, monitoring that compares results over timeYes, this is how every proxy works
Change on demandYou ask for a new IP when you want oneA clean start between jobsYes, with Change IP in your account; API control is planned
Rotation across your proxiesYour code picks the next of several proxiesSpreading a steady workload across several connectionsYes, order more than one proxy and rotate in your code
Timed or per-request rotationThe provider swaps the IP automaticallyStateless jobs where every request may leave from a different addressNot offered: the IP never changes unless you change it

So “rotate proxies automatically” with Xameleon means your own code choosing between several proxies, and the on-demand change when you want a new IP. The rest of this guide shows how to do both well.

2.Change the IP on demand

Your IP stays the same while you work, so a login or checkout keeps running from one address. When you want a fresh IP, press Change IP in your account: on Shared proxies you are moved to another modem in the same country, and on Exclusive proxies your own modem rotates. A planned API will let you do the same from your code.

Open connections can drop while the address changes, and a new IP can take a few seconds to appear. This helper waits until the exit IP really differs before your job continues:

import time
import requests

def exit_ip(proxies):
    r = requests.get("https://xameleon.cloud/api/tools/ip", proxies=proxies, timeout=(5, 20))
    r.raise_for_status()
    return r.json()["ip"]

def wait_for_new_ip(proxies, old_ip, attempts=12, pause=5):
    for _ in range(attempts):
        time.sleep(pause)
        try:
            ip = exit_ip(proxies)
        except requests.exceptions.RequestException:
            continue                    # the connection may drop for a moment while the IP changes
        if ip != old_ip:
            return ip
    return None

proxy = "http://USERNAME:PASSWORD@HOST:PORT"
proxies = {"http": proxy, "https": proxy}

old_ip = exit_ip(proxies)
input("Press Change IP in your account, then press Enter... ")
print("New IP:", wait_for_new_ip(proxies, old_ip))

Every call creates a new connection, so nothing keeps pointing at the old address. If you use sessions, close them and open new ones after the change.

3.Rotation on the client side

If you have several proxies, cycle through them in your code.

Each proxy has its own connection details in your account, so you can use them side by side. The simplest rotation takes them in turn:

from itertools import cycle
import requests

proxy_urls = [
    "http://USER1:PASS1@HOST1:PORT1",
    "http://USER2:PASS2@HOST2:PORT2",
    "http://USER3:PASS3@HOST3:PORT3",
]
turns = cycle(proxy_urls)

urls = ["https://example.com/page/1", "https://example.com/page/2", "https://example.com/page/3"]

for url in urls:
    proxy = next(turns)
    r = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=(5, 20))
    print(url, r.status_code)

Percent-encode special characters in each username and password, as in the Python proxies guide. That guide also covers sessions, timeouts and retries.

Want to see how this works for your project?
Tell us about your use case and we will suggest a setup.
View Pricing

4.Rotate on errors, not on a whim

Switch to the next proxy after a failure or a rate-limit response, and wait before retrying. Rotating faster than a site allows does not make heavy traffic acceptable.

What you getWhat it meansWhat to do
200The request workedKeep using the same proxy
429 or 503, often with Retry-AfterThe site asks you to slow downRest this proxy, wait at least the Retry-After time and lower your rate
403The site refuses the requestStop and read the site’s terms and robots.txt. More proxies are not the answer
407The proxy rejected your credentialsFix the credentials: rotating does not help
A connection error or a timeoutThe proxy or the network had a problemRest the proxy and retry on another one after a short wait
5xxThe site has a problemRetry later with a growing delay

A small pool class does the bookkeeping. It hands out proxies in turn and lets a failing one rest for a while:

import itertools
import time

class ProxyPool:
    """Hands out proxies in turn and lets the ones that fail rest for a while."""

    def __init__(self, proxy_urls, cooldown=60):
        self.urls = list(proxy_urls)
        self.cooldown = cooldown
        self.resting_until = {}                     # proxy URL -> time it may be used again
        self._turns = itertools.cycle(self.urls)

    def get(self):
        for _ in range(len(self.urls)):
            url = next(self._turns)
            if self.resting_until.get(url, 0) <= time.monotonic():
                return url
        raise RuntimeError("every proxy is resting: wait or add more proxies")

    def rest(self, url):
        self.resting_until[url] = time.monotonic() + self.cooldown

pool = ProxyPool(proxy_urls, cooldown=60)

5.Sticky sessions for multi-step flows

Keep the same IP for a whole login or checkout flow, and change it only when the flow is done. Changing the IP in the middle of a flow can break the session.

Give every flow its own session, bound to one proxy. Cookies and the IP then stay together, and nothing leaks from one proxy to another:

def run_flow(proxy_url, steps):
    """Runs every step of one flow through the same proxy, the same IP and the same cookies."""
    with requests.Session() as session:
        session.proxies.update({"http": proxy_url, "https": proxy_url})
        for step in steps:
            step(session)

def open_home(session):
    session.get("https://example.com/", timeout=(5, 20))

def open_account(session):
    session.get("https://example.com/account", timeout=(5, 20))

flows = [[open_home, open_account], [open_home, open_account]]

for flow in flows:
    run_flow(pool.get(), flow)           # rotate between flows, never inside one

6.Set limits for proxy rotation

Cap concurrency per proxy, add delays and respect target sites' rate limits.

Three limits keep a rotation polite. Pace every proxy separately, run no more workers than your plan’s concurrent connections allow, and watch the traffic you use. Several proxies spread a workload, but the site’s rules apply to the whole workload.

import threading
import time

class RateLimiter:
    """Lets one request through every <interval> seconds for each key (a proxy or a site)."""

    def __init__(self, interval):
        self.interval = interval
        self.next_slot = {}
        self.lock = threading.Lock()

    def wait(self, key):
        with self.lock:
            now = time.monotonic()
            slot = max(self.next_slot.get(key, now), now)
            self.next_slot[key] = slot + self.interval
        time.sleep(slot - now)

limiter = RateLimiter(interval=2.0)      # one request every 2 seconds per proxy

7.Putting it together

This fetch function takes the next proxy that is not resting, waits for that proxy’s turn, rests it on trouble and tries another. A thread pool runs it with a fixed number of workers:

from concurrent.futures import ThreadPoolExecutor
import requests

def fetch(url, attempts=3):
    for _ in range(attempts):
        proxy = pool.get()
        limiter.wait(proxy)                                  # pace every proxy separately
        try:
            r = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=(5, 20))
        except requests.exceptions.RequestException:
            pool.rest(proxy)                                 # a connection problem: let this proxy rest
            continue
        if r.status_code in (407, 429, 503):                 # wrong credentials, or the site asks us to slow down
            pool.rest(proxy)
            continue
        return r
    return None

urls = [f"https://example.com/page/{i}" for i in range(1, 7)]

with ThreadPoolExecutor(max_workers=3) as workers:           # no more workers than your plan allows
    for url, r in zip(urls, workers.map(fetch, urls)):
        print(url, r.status_code if r else "gave up")

The pool is shared by the threads, which is fine for a handful of workers. For a large crawler, put a lock around it or use a queue. Web scraping at scale shows how to set a request budget for the whole job.

8.Common mistakes

  • Changing the IP in the middle of a flow. Logins and checkouts can break when the address changes underneath them.
  • Rotating on every request for no reason. It adds connections, breaks cookies and does not raise a site’s limits.
  • Sharing one session between proxies. Cookies set through one IP end up in requests that leave from another. Use one session per proxy.
  • Retrying forever. Stop after a few attempts and rest the proxy. Never retry 407 or 403 in a loop.
  • Ignoring Retry-After. When a site says how long to wait, wait.
  • Not checking the result. After a change, confirm that the exit IP is new before you continue.

9.FAQs

Does Xameleon rotate my IP automatically?

No. Your IP stays the same while you work, which suits logins and long jobs. Change it on demand from your account; API control is planned. Automatic rotation in this guide means your own code choosing between several proxies.

How many proxies do I need?

Divide the requests per minute you need by the rate one proxy can safely handle within the site’s limits. For example, 120 requests a minute at one request every 2 seconds per proxy (30 a minute) calls for four proxies. Start small and measure.

Should I rotate on every request?

Usually not. Keep one proxy for a whole flow or a batch, and rotate between flows.

Does rotation raise a site’s rate limits?

No. Rotation spreads a legitimate workload across your connections. It does not entitle you to exceed a site’s rate limits or ignore its terms.

How do I know that the IP changed?

Call the IP endpoint before and after the change and compare the results. The wait_for_new_ip helper above does exactly that.

What happens to open connections when I change the IP?

They can drop. Close old sessions and start new ones after the change.

Still have questions about mobile proxies? Visit our FAQ page for detailed answers, or contact our support team — we're here to help.

Rotate proxies automatically: key takeaways and next steps

To rotate proxies automatically, first decide where rotation happens. When you change the IP on demand, you press Change IP in your account and your code stays simple. With client-side rotation, your script cycles through a list of proxies and decides when to switch.

Which rotation method should you choose?

Change the IP on demand between independent jobs, such as checking many product pages in separate runs. Use client-side rotation when you manage several proxies yourself and want to switch after a failed request, with a pause before the retry. You can combine both. Xameleon’s 4G mobile proxies keep your IP while you work and let you change it on demand, and a REST API with rotation control is planned: join the waitlist on the proxy management API page.

How do sticky sessions fit in?

Rotation suits independent requests. When a task has several steps, such as signing in and then viewing a few pages, keep the whole flow on the same IP and change it when the flow is done. Rotation does not change how much traffic a site considers acceptable, so cap concurrency per proxy, add delays and follow each target site’s rate limits, as described in web scraping at scale. For code, start from the Python proxies guide.