How to Rotate Proxy IPs: Three Mechanisms Compared
Rotation can happen at the gateway, in your own client code, or as a one-off refresh. How each works, how to set a rate, and what none of them fix.
"Rotate the IP" is the stock advice for nearly every proxy problem, and it is almost always given without saying where the rotation should happen. Three distinct mechanisms hide under that one phrase: rotation performed for you at the gateway on every new connection, rotation you implement yourself by cycling through a pool of static addresses, and a one-off replacement of a single address that has worn out its reputation. They behave differently, they belong to different products, and confusing them wastes money in both directions: you do not need a rotating plan to rotate, and buying one does not remove the need to think about rate.
This guide walks through each mechanism with working commands, then tackles the harder question of how often to rotate against a given target, and finally the class of problems that rotation cannot solve no matter how aggressively you spin.
What does proxy rotation actually mean?
Three different things, depending on who does the rotating: the gateway, your own client, or a manual replacement of a static address. They are not interchangeable, and only the first happens without code.
Gateway-side rotation. You configure a single fixed hostname and our gateway hands each new connection a different exit from the pool. Your code contains no pool logic at all. This is what a rotating plan or a residential plan provides.
Client-side cycling. You hold a list of static addresses (typically a shared or private datacenter plan) and your own code decides which request goes out through which address. Total control, bounded variety. Which of the two suits a given job is a question about the job rather than the product, and rotating versus static proxies works through the trade-offs task by task.
Manual refresh. Paid static plans include a Refresh IP action that swaps one address for a new one. It is not a loop; it is a transplant for an address that has gone bad.
The rest of this guide takes them in turn.
How do I rotate IPs without writing any rotation code?
Buy a rotating plan and point your client at one gateway hostname. Every new connection through it leaves from a different exit, and your code holds no pool, no health checks and no cursor.
On a rotating plan there is exactly one thing to configure. Point your client at the gateway hostname with the credential from your dashboard's Proxies page, and the pool management happens behind it:
curl -x http://USERNAME:PASSWORD@gw-rotating_shared.node4.io:8083 https://api.ipify.org
curl -x http://USERNAME:PASSWORD@gw-rotating_shared.node4.io:8083 https://api.ipify.orgRun it twice. Each command prints the exit address the target saw, and the two runs will generally differ, because each new connection through the gateway is assigned an exit independently.
That word connection is the detail most integrations trip over. The unit of rotation is the TCP connection, not the HTTP request. An HTTP client with keep-alive enabled (which is every modern HTTP client, by default) opens one connection and sends many requests down it, and all of those requests leave from the same exit. If a run appears to rotate far less than expected, you are probably reusing connections. To force a fresh exit per request, disable reuse: in cURL add -H 'Connection: close'; in most libraries, turn off the connection pool or construct a new client per request.
The inverse is also true, and it is not a bug: a few requests deliberately sharing one connection is the cheapest way to keep a short interaction on a single exit. For anything longer than one connection can carry, holding an exit is its own mechanism with its own syntax, covered properly in sticky vs rotating sessions. This guide stays on the rotating side of that line.
The residential gateway rotates the same way at the transport level, with one addition: segments in the username can constrain which slice of the pool your exits are drawn from: a country, a region, a city, a network operator. That syntax lives in country and city targeting.
Client-side cycling: rotation you own
A static plan gives you addresses that do not change, which sounds like the opposite of rotation until you remember that nothing stops you distributing requests across them yourself. The Proxies page lists every address on your plan, and the management API serves the same list as JSON from /proxies/list, the better source, since code that fetches the list at startup automatically picks up any address you later replace.
A minimal round-robin scheduler:
import itertools
import requests
rows = fetch_proxy_list() # GET /proxies/list with your API key
pool = itertools.cycle(rows)
def fetch(url):
p = next(pool)
proxy = f"http://{p['username']}:{p['password']}@{p['host']}:{p['port']}"
return requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=30)Round-robin is the right default because it is predictable: every address carries an equal share of the load, and a per-address problem shows up in your logs as a periodic failure pattern you can actually see. Random selection is marginally better against targets that look for lockstep ordering. The refinement genuinely worth building is error-driven rest: when one address starts drawing 403s or CAPTCHAs from a particular target, take it out of rotation for that target for an hour and let the others carry the load. Addresses recover; continuing to hammer one that is already flagged only deepens the flag. Why is my IP getting blocked describes what those early warnings look like in practice.
What you give up against a gateway is scale of variety: your pool is exactly as large as the plan you bought, so against a single busy target the same addresses come back around quickly. What you gain is control: the mapping from request to address is yours, so you can pin one address to one logged-in account for its whole life while cycling the rest, something a per-connection gateway cannot express. The trade is real, and how many proxies do I need walks through the arithmetic for sizing the static side of it.
Is the Refresh IP button the same as rotation?
No. It retires one static address and issues another in its place, which is a replacement you perform occasionally rather than something that happens per request.
Paid static plans include one more lever. Each proxy row on the Proxies page has a Refresh IP action, also exposed through the API at /proxies/refresh, which retires that address and issues you a different one.
This is maintenance, not a rotation mechanism. The intended use is the address that has accumulated a bad history: blocked outright by the one target you bought it for, or inherited with a reputation problem you only discovered in production. After a refresh the old address is gone for good, so anything that hard-codes it (a config file, a firewall rule, a whitelist a partner maintains on their side) needs updating. That is exactly why reading /proxies/list at startup beats pasting addresses into source code.
If refresh becomes a routine, and you find yourself reaching for it every few days as a target wears each address down, that is the workload telling you it wants gateway-side rotation instead. Refreshing on a schedule is rotation implemented at the most expensive layer available to you. The two are compared directly, with the API call and the connection string side by side, in proxy rotation API or rotating gateway.
How often should I rotate my IP?
Often enough that no single exit crosses the target's per-address threshold inside its window, which is a number you measure rather than choose.
The question is not "how fast can I rotate" but "how many requests will this target tolerate from one address inside a window". Rotation exists to keep each exit below that threshold, so the target's tolerance, not your infrastructure, sets the rate.
You can measure the tolerance rather than guess it. Send from a single address at a modest, steady pace and watch for the first soft resistance: response times stretching, intermittent 429s, a CAPTCHA where a page used to be. Note the requests-per-hour you had reached when that started; take a healthy margin off it and call the result your per-address budget for this target. Your required throughput divided by that budget is the number of exits you need in play at once, and from there the rotation schedule falls out on its own.
Two mistakes dominate. The first is obvious: rotating slower than the budget requires, so each address crosses the threshold and burns. The second is less obvious: rotating far faster than the budget requires is not a free safety margin. On a shared pool it churns exits you had no need to churn, and, more damaging, per-request rotation under a client that carries cookies presents the target with one visitor arriving from hundreds of networks in an hour. That inconsistency is itself a strong signal. Rotation rate and identity handling have to move together, which is where the next section picks up.
For client-side pools, the most robust policy combines both inputs: rotate on a schedule sized from the measured budget, and additionally rotate immediately on a 403, 429 or CAPTCHA, resting the address that drew it.
Will rotating my IP stop me getting blocked?
Only when the block was keyed to the address. Rotation changes the network address and nothing else, so every other identifier in your traffic travels to the new exit unchanged.
Rotation changes the network address and nothing else. Every other identifier in your traffic rides along to the new exit, and any one of them can undo the work:
Cookies. A cookie jar that persists across a rotation lets the target stitch the "different" visitors back together. Worse, the stitched picture (one session spread over many networks) looks less human than no rotation at all. Clear the jar when the exit changes, or scope one jar to each exit.
Logins. An authenticated account is an identity stronger than any address. Rotating underneath a logged-in session does not make the account anonymous; it makes the account look hijacked, which is a common trigger for a forced logout or a verification challenge. Work bound to accounts wants the opposite of rotation: one stable exit per account.
Browser and TLS fingerprints. A headless browser presents the same canvas hash, font list and TLS handshake from every exit. A target correlating on fingerprint sees one machine regardless of what the address says. Rotation narrows nothing here.
Address classification. Cycling within a datacenter pool changes which datacenter address you use, not the fact that it is one. A target that scores traffic by address type scores the new exit the same as the old. No rate setting moves that ceiling; moving it means moving pools, which is the case for residential exits.
And one failure mode is caused by rotation rather than cured by it: any flow where the server holds state against your visit (a login, a shopping cart, a paginated result set) breaks when the exit changes mid-flow. If your symptom is a logout or a vanished cart rather than a block, rotation is the disease, and sticky vs rotating sessions is the treatment.
Where to start
If the workload is stateless fetching at volume, start gateway-side (the plans are compared on the pricing page) and spend your effort on rate measurement rather than pool plumbing. If it is a modest set of targets that need stable, controllable identities, start with static datacenter addresses and the cycling pattern above. The free tier (3 free shared proxies with 1 GB/month bandwidth and 10 concurrent threads) is enough to prototype the client-side scheduler against a real endpoint before committing to either.