Dual Login
Guides

How to Avoid IP Bans When Scraping: A Practitioner's Guide

Dual Login Team·2026-08-08·23 min read

How to Avoid IP Bans When Scraping: A Practitioner's Guide

IP bans kill scrapers quietly. Learn the detection signals that trigger them, how to rotate proxies properly, and why browser fingerprints matter as much as IPs.

How to Avoid IP Bans When Scraping: A Practitioner's Guide

Every scraper dies the same way. It runs beautifully in testing, collects data for a week or two in production, and then one morning the success rate falls off a cliff. Half the responses are 403s. The other half are CAPTCHA pages your parser happily ingests as if they were product listings. You swap the IP, it works for an hour, and then it dies again — faster this time, because now the site has a signature for you that has nothing to do with your address.

If that story sounds familiar, this guide is for you. Learning how to avoid IP bans when scraping is not about finding one magic proxy provider or one secret header. It's about understanding what anti-bot systems actually measure, and then making sure your crawler doesn't measure like a bot on any of those axes at once. I've spent years running scraping and multi-account infrastructure, and the pattern is always the same: people obsess over IPs, which are maybe half the problem, and ignore everything else — which is why they keep getting banned even after paying for expensive residential proxies.

Rotating proxies and isolated browser profiles working together to avoid IP bans when scraping

Let's take it layer by layer: what a ban really is, which signals trigger one, how to build a proxy strategy that doesn't burn itself down, and why the browser fingerprint attached to each IP quietly decides whether your pool lasts six months or six days.

What an IP ban actually is (and why that matters)

An 'IP ban' sounds like a binary thing — you're on a blacklist or you're not. In practice, modern sites almost never work that way. What you're really dealing with is a scoring system. Every request you send gets scored on dozens of signals: the reputation of the IP's subnet, the rate of requests from that address, the consistency of your headers, your TLS handshake, your browser fingerprint, whether you loaded the page's JavaScript, whether your mouse ever moved. Cross a threshold and the site responds — but the response varies.

Block, ban, shadow ban: know which one you got

It pays to distinguish three outcomes, because each demands a different fix:

A soft block is a rate-limit response, usually an HTTP 429 with a Retry-After header (MDN documents the semantics). This is the site telling you, politely, to slow down. It is recoverable and it is feedback — the best kind of failure, because it tells you exactly what to change. A scraper that treats 429s as generic errors and retries immediately is a scraper that converts soft blocks into hard bans.

A hard ban is a 403, a connection reset, or an interstitial challenge page served to your IP or session regardless of what you request. Sometimes it expires in hours; sometimes the address is poisoned for weeks. Datacenter IPs on well-known hosting ASNs often arrive pre-banned — the site never scored you at all, it just checked the ASN.

A shadow ban is the nasty one. The site keeps serving you 200s, but the content is degraded: stale prices, truncated listings, randomized search results, or an endless CAPTCHA loop dressed up as a page. Shadow bans are why you must validate the content of responses, not just the status code. I've seen teams collect a month of silently poisoned pricing data because their monitoring only counted HTTP errors.

The practical takeaway: build your scraper to classify these three outcomes separately from day one. Everything else in this guide depends on knowing which one you're getting.

The signals that get you banned

Before you can avoid IP bans, you need an honest inventory of what you look like from the server's side. Anti-bot vendors — Cloudflare, DataDome, Akamai, PerimeterX and friends — broadly score four categories.

1. Rate and timing patterns

The oldest signal and still the most common trigger. Humans browse in bursts with long gaps. Naive scrapers issue requests at metronomic intervals — one every 500 ms, forever — often faster than any human could click, and often in an order no human would follow (page 1, 2, 3, 4… of a category listing, sequentially, alphabetically). Rate detection is cheap for the defender and deadly for the attacker because it works even when every other signal is clean.

What matters isn't just requests per second. It's requests per second per IP, per session, per URL pattern, and the shape of the intervals. A pool of 100 proxies each doing a perfectly even one-request-per-two-seconds is trivially distinguishable from 100 humans.

2. The requests themselves: headers, TLS and protocol fingerprints

Every HTTP client betrays itself below the header level. Python's requests, Go's net/http, curl and Node's fetch each produce a distinctive TLS ClientHello — the cipher suites offered, their order, the extensions present. Defenders hash this (the JA3/JA4 family of techniques) and compare it against what your claimed User-Agent should produce. Claim to be Chrome 120 in your User-Agent header while shaking hands like OpenSSL-via-Python, and no amount of IP rotation saves you. The same applies to HTTP/2 settings frames and header ordering —real browsers send headers in a stable, browser-specific order.

This is the single most common reason people conclude 'residential proxies don't work.' The proxies were fine. The client was screaming.

3. Browser-level fingerprints

If the site requires JavaScript, the game moves up a layer. Now the defender can read your canvas rendering, WebGL renderer string, audio-context output, installed font list, screen metrics, timezone, language list, hardware concurrency, device memory, plugin array, and dozens more. Combined, these form a fingerprint that is often unique across millions of users — the EFF's Cover Your Tracks project has been demonstrating this since 2010 and is still the clearest public illustration of how much entropy a browser leaks.

For scraping, the fingerprint matters in two directions. First, an impossible fingerprint gets you banned instantly: a Windows User-Agent with a Linux WebGL renderer, or navigator.hardwareConcurrency of 1 on a machine claiming to be a modern desktop. Second, an identical fingerprint across 200 sessions gets your whole pool banned together — the site links every one of those IPs to a single device and burns them as a cluster. If you're new to this layer, browser fingerprinting explained for beginners is worth twenty minutes before you write another line of scraper code.

4. Behaviour and session coherence

The subtlest category. Do you have cookies from a previous visit? Did you load the CSS and images, or only the HTML? Did you request the JSON endpoint without ever loading the page that calls it? Did your mouse move? Did you scroll before clicking a link that sits below the fold? Did you arrive at a product page with no referrer, having never touched search or a category?

Most sites weight this lightly for anonymous traffic and heavily behind logins. But it's why headless-browser scraping with no interaction at all often fares worse than plain HTTP requests: you've opted into a much richer measurement surface and then failed most of the measurements.

Proxy strategy: the part everyone half-does

Proxies are necessary. They are not sufficient. Here's how to actually use them.

Choose the right proxy type for the target

Proxy type Typical cost Ban resistance Best for Main weakness
Datacenter Cheapest (~$1–3/IP/mo) Low Unprotected sites, APIs, internal tools Whole ASNs pre-blocked; easy to identify
ISP / static residential Medium (~$3–8/IP/mo) Good Long-lived sessions, logged-in scraping Limited pool sizes; burns permanently if flagged
Rotating residential Per-GB (~$3–10/GB) High Large-scale anonymous crawling Shared IPs with unknown history; variable latency
Mobile (4G/5G) Expensive (~$50+/mo) Highest Hard targets, social platforms Cost; heavy CGNAT sharing means noisy neighbours

The mistake I see most often is buying the most expensive tier for a target that doesn't need it, then blowing the budget on volume and running everything through one badly-configured client. A well-behaved scraper on datacenter IPs beats a sloppy one on mobile proxies more often than you'd expect.

One warning about rotating residential pools: you are inheriting someone else's history. If a previous user hammered your target from that exact IP an hour ago, you start in the hole. Test your pool against your specific target before committing to a contract, not against a generic 'am I blocked' checker.

Rotate on the right trigger, not on a timer

Most people rotate per request or per fixed interval. Both are wrong for most targets.

Per-request rotation destroys session coherence. You get a session cookie on IP A, then send it from IP B, then IP C. Real users don't teleport between three ISPs mid-checkout. For any site that tracks sessions, per-request rotation is a tell in itself.

Sticky sessions with event-based rotation is the pattern that holds up. Pin one IP to one logical session — one cookie jar, one fingerprint, one browsing narrative — and rotate only when something meaningful happens: a 429, a challenge page, a content anomaly, the natural end of a task, or a soft cap on requests-per-session that you've tuned by experiment.

When you do rotate, rotate everything together. New IP, new cookie jar, new fingerprint, fresh storage. Half-rotations are worse than none: a new IP carrying the old cookies simply tells the site those two IPs are the same actor.

Spread across subnets, not just addresses

Defenders block at /24 and ASN granularity far more often than at the single-address level. Twenty IPs in 192.0.2.0/24 are, for banning purposes, close to one IP. When you buy a pool, check the subnet distribution. A provider selling you 500 addresses across three subnets is selling you three IPs with extra steps.

Respect the site's own rules where you can

This isn't just ethics, it's self-preservation. robots.txt and rate guidance tell you which paths are monitored aggressively and which are considered fair game. The Robots Exclusion Protocol is a documented standard (RFC 9309), and honouring the paths a site explicitly forbids dramatically reduces the chance you trip a manual review — the kind that ends with your whole ASN blocked rather than one address. Where a public API exists, use it; paying for an API tier is nearly always cheaper than the engineering time spent losing an arms race.

Rate limiting yourself: the discipline that actually works

If I could give one piece of advice to a team whose scrapers keep dying, it would be this: you are going too fast, and you are going too fast in a suspiciously regular way.

Model a human, not a queue

Pick a target throughput per session that a human could plausibly produce. Then add jitter that isn't uniform — real inter-action gaps follow a long-tailed distribution. Someone reads a product page for 4 seconds, then 40, then 8, then leaves for 5 minutes and comes back. A log-normal or Pareto-ish delay distribution looks far more human than sleep(random.uniform(1, 3)).

Also vary what you do, not only when. Interleave category pages, searches and detail pages. Occasionally revisit something. Occasionally load a page and take nothing from it. Sequential enumeration of ?page=1..500 is the most recognisable scraping signature in existence, and the fix is often as simple as shuffling the order and splitting the range across sessions.

Concurrency belongs at the pool level

The number that matters is not 'how many workers do I have' but 'how many concurrent requests hit the target from any single IP'. Usually that number should be 1, sometimes 2. Scale by adding identities, not by adding threads per identity. Ten identities doing one request at a time will outlive two identities doing five, every time — and they'll degrade gracefully instead of all dying at once.

Back off exponentially and honour Retry-After

When you get a 429, stop that identity. Read Retry-After if present and obey it literally. If absent, back off exponentially with jitter and cap the retries. Two 429s in a row on the same IP should retire that IP for the day, not trigger a third attempt. Most ban cascades I've debugged came from retry logic that hammered harder precisely when the site was asking it to stop.

Cache aggressively and fetch less

The cheapest way to avoid IP bans when scraping is to send fewer requests. Conditional requests with If-Modified-Since/ETag, a local cache keyed by URL, and diff-based recrawling (only re-fetch what plausibly changed) can cut volume by 70–90% on catalogue-style targets. Half the 'we need more proxies' conversations I've had should have been 'we need a cache.'

Fingerprints: why your proxies keep dying anyway

Here's the part that separates scrapers who plateau from scrapers who scale. You can do everything above correctly and still burn IPs at an alarming rate, because all your sessions look like the same machine behind different addresses.

Think about what the defender sees. Two hundred requests, two hundred distinct residential IPs across four countries — and every single one reports the same canvas hash, the same WebGL renderer, the same 1920×1080 screen with the same 24-pixel taskbar offset, the same font list, the same Accept-Language, and a timezone that doesn't match the IP's country. That's not two hundred users. That's one automation rig, cheerfully labelling itself. When the site works this out, it doesn't ban one IP. It bans the cluster, and it adds your fingerprint to a watch list so the next pool you buy dies faster.

This is the mechanism behind the most demoralising experience in scraping: upgrading to better proxies and getting worse results.

One identity = IP + fingerprint + storage + behaviour

The unit you should be scaling is not the IP. It's the identity: a coherent bundle of

  • a network address (proxy) with a plausible geography,
  • a browser fingerprint consistent with that geography and with itself,
  • a persistent, isolated storage container (cookies, localStorage, IndexedDB, cache),
  • and a behavioural history that accumulates over time.

Every part has to agree with every other part. A German residential IP with en-US as the only language, a New York timezone and a fingerprint claiming a MacBook while the User-Agent says Windows is not one identity — it's four contradictions stapled together, and each contradiction is a scored signal.

Getting this right by hand is miserable. Setting --user-agent and calling it a fingerprint is the classic beginner error; the deep dive in how to change your browser fingerprint walks through everything that actually needs to move together, and why patching values from JavaScript inside the page leaves traces of its own.

Persistence beats freshness for anything logged-in

For anonymous crawling, fresh identities are fine. For anything behind a login — marketplace seller dashboards, ad platforms, social APIs — freshness is a liability. A brand-new browser with no history, no cookies and no cached assets that immediately signs into an established account is exactly the shape of a credential-stuffing attempt.

What you want there is a small number of long-lived identities, each with its own data directory that survives restarts, accumulates cookies naturally, keeps the same fingerprint for months and always exits through the same IP or at least the same city. That's a completely different operational model from rotating pools, and it's the model that keeps accounts alive. The reasoning is spelled out in the Amazon seller ban-avoidance playbook — the mechanics generalise well beyond Amazon.

Why a VPN doesn't solve this

Worth stating plainly because it comes up constantly: a VPN changes your exit IP and nothing else. Every session through it shares one address and one fingerprint, which is the worst of both worlds — you've made your traffic more concentrated, not less linkable. VPN endpoints are also widely catalogued and often pre-scored as suspicious. The full comparison of an antidetect browser vs a VPN covers where each tool is actually appropriate; for scraping at scale, a VPN is a debugging convenience, not infrastructure.

Headless browsers, and when to skip them

There's a reflex to reach for Puppeteer or Playwright the moment a site fights back. Sometimes that's right. Often it's an expensive way to get banned more thoroughly.

The case for plain HTTP

If the data you need arrives in the initial HTML or from a JSON endpoint you can call directly, plain HTTP is faster, cheaper by an order of magnitude, and exposes far fewer signals. You have no canvas to hash, no WebGL string to contradict your User-Agent, no navigator.webdriver to leak. Your job reduces to getting the TLS fingerprint and header order right, which is a solved problem with the right client library.

Always spend an hour in DevTools looking for the underlying API before committing to browser automation. A surprising share of 'JavaScript-heavy' sites are a thin React shell over a clean, unauthenticated JSON endpoint.

When you genuinely need a browser

You need a real browser when the content is assembled by client-side code you can't reasonably reimplement, when there's a JavaScript-based challenge to solve, when the session requires a login flow with device binding, or when the interaction pattern itself (scrolling, hovering, clicking) is part of what unlocks the data.

In that case, use a real browser, not a stripped-down headless one. navigator.webdriver, the documented Chrome DevTools Protocol automation flags, missing GPU stacks and the absence of a window manager are all detectable. Two rules follow:

First, don't hold a CDP connection you don't need. An attached debugger changes observable browser state. If your workflow can run without an open automation channel — or can attach briefly and detach — take that option.

Second, don't inject your fingerprint from JavaScript. Overriding navigator properties and canvas methods from a content script leaves detectable residue: toString mismatches on patched functions, property descriptors that don't match native ones, timing differences, and — crucially — values that differ between the main thread and a Web Worker, because your injection never reached the worker. Fingerprint spoofing that happens below the JavaScript layer, in the browser engine itself, has none of these tells. This is the core architectural difference between a proper antidetect browser and a Puppeteer stealth plugin, and it's why the plugin approach degrades every time a detection vendor ships an update.

Run browsers as isolated processes

Whichever route you take, each identity needs its own process and its own data directory. Tabs in one browser share storage, share a fingerprint, and share a rendering context — three ways to link identities you meant to keep apart. One profile, one process, one --user-data-dir, one proxy. That's the isolation boundary that actually holds.

Building a scraper that survives: an operational checklist

Strategy is easy to agree with and hard to implement. Here's the concrete version, roughly in the order I'd build it.

Instrument before you scale

You cannot manage a ban rate you don't measure. Log, per request: identity ID, proxy IP, HTTP status, response byte length, whether a known challenge marker appeared in the body, and latency. From that, compute per-identity and per-subnet success rates on a rolling window.

The byte-length and challenge-marker checks are what catch shadow bans. A product page that's normally 180 KB arriving at 14 KB with a 200 status is a block, and only content inspection will tell you.

Retire identities on evidence, and quarantine rather than delete

Give each identity a health score. Drop it below threshold on 429s, challenges and content anomalies. When it fails, quarantine it for 24–72 hours instead of discarding it — many soft bans expire, and an IP with accumulated cookie history is worth more than a fresh one. Track why each identity died; if failures cluster by subnet, provider or fingerprint template, you've found a systemic problem rather than bad luck.

Warm up new identities

Don't send a brand-new identity straight at your highest-value target. Have it browse a few unrelated, low-risk sites first, accumulate some cookies and cache, and establish a plausible history. Then approach the target through the front door — homepage, search, category, detail — rather than deep-linking straight to the page you want. Warm-up costs minutes and routinely doubles identity lifespan on protected targets.

Fail gracefully and never poison your dataset

When an identity gets challenged, that request should be re-queued for a different identity, not retried in place. And every parsed record should carry the identity and timestamp that produced it, so that when you discover an identity was shadow-banned since Tuesday, you can surgically invalidate its output instead of distrusting the whole dataset.

Decide, deliberately, what you won't do

Scraping public data is broadly legal in many jurisdictions, but 'broadly legal' isn't a strategy. Personal data brings the GDPR/CCPA regimes into play. Circumventing an authentication wall is a different legal category from reading a public page. Aggressive crawling that degrades a site's service can attract consequences well beyond an IP ban. Write down your boundaries, put rate ceilings in code rather than in a runbook, and identify your crawler honestly where you can. The teams that operate longest are the ones defenders don't feel obliged to fight.

Where an antidetect browser fits

By now the shape of the solution should be clear: you don't need more IPs, you need more identities — and each identity needs a distinct, internally consistent, persistent browser to live in. That's precisely the problem an antidetect browser solves, and it's why so many scraping teams end up running one alongside their proxy pool rather than instead of it.

The mechanics are covered in what an antidetect browser is and how it works, but the scraping-relevant summary is short. Each profile gets a fingerprint generated to be internally coherent — canvas, WebGL, audio, fonts, screen, UA, timezone, languages all agreeing with each other and with the proxy's geography. Each profile gets its own persistent data directory, so cookies and logins survive restarts and accumulate real history. Each profile gets its own proxy. Each launches as a separate OS process, so there's no shared storage or rendering state to link them. And in a well-built one, the fingerprint is applied inside the browser engine rather than injected as JavaScript — so it reaches Web Workers, has no toString tells, and doesn't break when a detection vendor ships a new probe.

Dual Login was built on exactly that architecture, and it exposes the automation surface scraping actually needs: raw CDP driving that never calls Runtime.enable on the hot path (so navigator.webdriver stays false and clicks are trusted OS-level events), per-profile proxy assignment with SOCKS and authenticated-proxy bridging, WebRTC masked to the proxy exit IP, and a local HTTP API so your existing pipeline can drive profiles without rewriting itself around a new SDK.

If you're evaluating options, the honest advice is to compare rather than take anyone's word for it — GoLogin vs AdsPower covers the two most common incumbents, and if budget is the binding constraint, cheaper Multilogin alternatives that actually work is the more relevant read. Whatever you pick, test it against your targets with your proxies before you scale; a tool that sails through a generic fingerprint checker can still fail the one site you actually care about.

Putting it together: a worked example

Suppose you need daily pricing from a protected retail site with 50,000 SKUs.

The naive build: one server, 20 datacenter proxies, requests with a spoofed User-Agent, 10 threads, sequential SKU enumeration. This works for about a day and then dies permanently, because the TLS fingerprint is Python, the enumeration order is machine-obvious, and 20 datacenter IPs across two subnets is functionally two IPs.

The build that survives:

  1. Cut the volume first. 50,000 SKUs don't all change daily. Tier them — 2,000 high-velocity SKUs daily, the rest weekly on a rolling schedule. You've just reduced daily requests by ~85%.
  2. Find the cheapest surface. Check for a JSON endpoint or structured data in the initial HTML. If pricing arrives without JavaScript, most of the request volume can go through a plain HTTP client with a browser-accurate TLS fingerprint, and no browser at all.
  3. Reserve browsers for what needs them. Use full isolated browser profiles only for the paths that genuinely require JS execution or a challenge solve — maybe 5–10% of requests.
  4. Build 25–40 identities, not 400 proxies. Each one gets a residential IP in a plausible market, a coherent fingerprint, a persistent profile directory and a warm-up history. Spread them across subnets and providers.
  5. One concurrent request per identity, log-normal delays, shuffled SKU order, occasional category and search detours, natural session lengths of 20–60 requests before a clean rotation.
  6. Health-score everything. Retire on the first challenge, quarantine for 48 hours, alert if the population success rate drops 10% in an hour or if median response size shifts.
  7. Cache and diff. Conditional requests, content hashing, and only re-parse what changed.

That build is slower per identity and dramatically faster in aggregate, because it doesn't spend its life recovering from bans. It also costs less: fewer requests, fewer proxies, less engineering time firefighting.

FAQ

How many proxies do I need to avoid IP bans when scraping?

Fewer than you probably think, if each one is paired with a distinct browser identity and a sane request rate. Work backwards from throughput: if a protected target tolerates roughly 30 requests per hour per identity and you need 3,000 requests an hour, that's about 100 identities — not 100 IPs used carelessly. Teams that ask 'how many proxies' usually need to ask 'how few requests' instead, because caching and tiered recrawling routinely cut volume by 70% or more.

Do residential proxies alone stop IP bans?

No, and this is the most expensive misconception in scraping. Residential IPs raise your baseline reputation, but if every session shares one TLS fingerprint, one browser fingerprint and one behavioural pattern, the site links them and bans the cluster. Residential proxies buy you a better starting score; they don't hide a bot that behaves like a bot. Pair them with distinct, consistent fingerprints and human-shaped pacing or you're paying premium prices for the same outcome.

How long should I wait after being banned before retrying?

Depends on the signal. A 429 with Retry-After — obey the header exactly. A 429 without one — exponential backoff starting around 60 seconds, and retire the identity after two consecutive hits. A hard 403 or challenge page — quarantine that IP for at least 24 hours, ideally 48–72. Retrying a hard-banned address quickly is how a temporary block becomes a permanent one, and how one flagged IP drags its whole subnet down with it.

Is it better to rotate IPs on every request or keep sticky sessions?

Sticky sessions win for almost every real target. Per-request rotation breaks session coherence: cookies obtained on one IP arriving from another is behaviour no human produces, and it's easy to detect. Pin an IP to a session and rotate on events — a 429, a challenge, a content anomaly, or the natural end of a task. The one exception is stateless, cookie-free endpoints on unprotected sites, where per-request rotation is harmless.

Can I just use a headless browser with a stealth plugin?

It works until it doesn't, and the failure is sudden. Stealth plugins patch detectable properties from JavaScript inside the page, which leaves its own residue: toString mismatches on overridden functions, property descriptors that don't match native ones, and values that differ between the main thread and Web Workers because the patch never reached the worker. Detection vendors update faster than plugins do. Engine-level fingerprinting — applied below the JavaScript layer — doesn't have those tells.

No. Tooling doesn't change legality, and it's important to be clear about that. What's lawful depends on the data (personal data pulls GDPR/CCPA into scope), whether you crossed an authentication boundary, the site's terms, your jurisdiction, and the load you impose. An antidetect browser is an isolation and consistency tool — it makes legitimate multi-identity work reliable. It doesn't authorise anything you weren't already permitted to do, and it won't protect you from the consequences of scraping you shouldn't be doing.

Conclusion

The teams that scrape successfully for years aren't the ones with the biggest proxy budget. They're the ones who stopped thinking in IPs and started thinking in identities — coherent bundles of network, fingerprint, storage and behaviour that each look like a plausible person doing plausible things at a plausible pace. Get that right and your proxy pool lasts months instead of days, because you're no longer handing the defender a cluster to ban.

The order of operations matters too. Reduce your request volume before you buy capacity. Fix your TLS and header fingerprints before you blame the proxies. Instrument for shadow bans before you trust your data. And when you do need real browsers, give each identity its own isolated, persistent, engine-level-spoofed profile rather than one browser wearing different hats.

If that last part is where your setup is thin, Dual Login is worth a look — many isolated profiles, each with a coherent native fingerprint, its own persistent data directory and its own proxy, plus a local automation API so your existing pipeline can drive them without a rewrite. Spin up a handful of profiles, point them at the target that's been fighting you, and see how the ban rate compares to what you're running now. That test takes an afternoon and it'll tell you more than any vendor page.

Run every account like a separate device

Dual Login gives each profile a real fingerprint, its own proxy and sealed storage — free plan, no card required.