Web scraping without getting blocked is less about clever tricks and more about looking like exactly what you should be: an ordinary browser, driven at a human pace, from an IP with a clean reputation, collecting only data you are permitted to collect. Most scrapers get blocked because they cut corners on one of those fronts — a raw HTTP client with a giveaway TLS signature, a headless Chrome instance leaking automation flags, or a datacenter IP hammering a target 40 requests a second. This guide covers how modern anti-bot systems actually detect scrapers, why the common approaches fail, and how to build a collection pipeline that is both resilient and responsible.
Before any of the technical detail, one point sets the frame: legitimate scraping and abusive scraping use overlapping tools but live in different worlds. A price-monitoring team pulling public listings under a site's terms, a researcher collecting permitted public data, or an operator working across their own accounts is doing normal work. Someone harvesting personal data unlawfully or bypassing an explicit paywall is not, and no amount of tooling makes that safe or legal. This article is written for the first group. If you are in the second, stop reading and rethink the project.
Everything below assumes you have done the responsible groundwork first. Get that right and the technical layer becomes far easier, because you will not be fighting the target — you will be blending into its normal traffic.
Start with the rules, not the workarounds
Responsible scraping is a discipline, not a disclaimer. Before you write a single request, work through this checklist:
- Prefer the official API. If the target publishes an API, use it. It is faster, more stable, explicitly permitted, and it will not break every time the site ships a redesign. Scraping the HTML is the fallback, not the default.
- Read
robots.txtand the terms of service.robots.txttells you which paths the site asks automated clients to avoid. The terms tell you what data use is permitted. Neither is a mere formality; ignoring them is how legitimate projects turn into legal problems. - Never collect personal data unlawfully. Public visibility is not the same as lawful collection. Under GDPR, CCPA, and similar regimes, personal data carries obligations regardless of whether a login was required. When in doubt, exclude it.
- Rate-limit yourself. Send traffic at a volume the target can absorb without noticing. A polite crawler is indistinguishable from ordinary users; an aggressive one is a denial-of-service event with a friendlier name.
- Identify yourself where appropriate. For permitted research crawls, a descriptive User-Agent with contact details is often welcomed, and some sites will whitelist you rather than block you.
These constraints are not obstacles to working around — they are the reason your project is defensible. They also happen to make you harder to detect, because well-behaved traffic is exactly what detection systems are tuned to ignore.
How anti-bot detection actually works
Modern anti-bot systems do not rely on any single signal. They build a confidence score from dozens of weak signals, and once that score crosses a threshold they throttle you, serve a CAPTCHA, feed you decoy data, or block you outright. Understanding the individual signals is what lets you avoid tripping them. Here are the main ones.
IP reputation and rate patterns
The first and cheapest check is the network layer. Every IP carries a reputation derived from its ASN (datacenter ranges are flagged instantly), its history of abusive behavior, and whether it appears on shared blocklists. On top of reputation sits rate analysis: how many requests per minute, how evenly spaced, how many unique pages, and whether the timing has the mechanical regularity of a script. A single IP requesting 300 product pages in perfectly even 200ms intervals is a scraper with a neon sign on it.
TLS and JA3/JA4 fingerprints
When your client opens an HTTPS connection, the TLS handshake carries a distinctive pattern — the ordered list of cipher suites, extensions, and curves it advertises. Hashed, this becomes a JA3 or the newer JA4 fingerprint. A real Chrome browser produces one recognizable signature; Python's requests, Go's net/http, and Node's default agent each produce their own, and none of them match any real browser. Anti-bot vendors keep libraries of these. You can send a perfect set of browser headers and still be unmasked at the TLS layer before a single byte of HTML is exchanged.
HTTP header order and composition
Browsers send headers in a specific, consistent order and include a specific set (sec-ch-ua, sec-fetch-*, accept-language, and so on). HTTP libraries send a different, often alphabetized order and omit the client-hint headers entirely. Header order and presence is a strong tell, independent of the header values, and it is one of the easiest ways to spot a scraper masquerading as a browser.
Headless browser signatures
Running real Chrome solves the TLS and header problems, but default headless Chrome introduces new ones. navigator.webdriver returns true. The HeadlessChrome token appears in the User-Agent. Automation frameworks inject variables and CDP artifacts. Missing or inconsistent properties — no plugins, a WebGL renderer that reads SwiftShader, permission states that never match a real profile — all flag the session. Detection scripts probe dozens of these in the first few hundred milliseconds after page load.
Fingerprint entropy and consistency
Beyond the headless tells, every browser exposes a fingerprint: canvas and WebGL rendering hashes, audio-stack output, installed fonts, screen and color-depth values, hardware concurrency, timezone, and language. Anti-bot systems look for two failure modes. First, low entropy or impossible combinations — a Linux User-Agent with Windows fonts, or a timezone that contradicts the IP's geolocation. Second, repetition — the identical fingerprint appearing across hundreds of sessions, which is the signature of a scraping farm. Our companion piece on browser fingerprinting breaks down each surface in detail.
Behavioral timing and interaction
Advanced systems watch how the session behaves after load. Real users move the mouse in curved paths, scroll unevenly, pause to read, and mistype. Scripts click exact coordinates instantly, navigate with zero dwell time, and never generate the incidental events a human hand produces. Behavioral models flag the absence of this noise as readily as its wrong presence.
Honeypots and CAPTCHA triggers
Finally, sites plant honeypot links — anchors hidden by CSS that a human never sees but a naive crawler follows — and use following them as an instant-block signal. When the aggregate score is uncertain, the system escalates to a CAPTCHA as a tiebreaker. A CAPTCHA is not the problem itself; it is the visible symptom of a score you already lost several signals ago.
Why raw HTTP clients fail on modern sites
The instinct for a fast scraper is to skip the browser entirely and hit endpoints with an HTTP client. On a static server-rendered site that still works. On the modern web it usually does not, for two reasons.
The first is rendering. Most non-trivial sites are JavaScript applications that fetch data client-side and assemble the DOM in the browser. The HTML you receive from a raw GET is a near-empty shell; the content you want arrives via XHR/fetch calls, often to signed or token-gated endpoints, and often only after other scripts have run. Reproducing that by hand means reverse-engineering the site's private API on every change it ships.
The second is detection, covered above. Even when you can reach a JSON endpoint directly, the TLS fingerprint, header order, and missing client-hint headers mark you as non-browser traffic. You can invest heavily in TLS-spoofing libraries and hand-crafted header sets, but you are now maintaining a fragile impersonation of a browser instead of using one. For anything defended, that trade rarely pays off.
Why default headless Chrome is trivially detected
Switching to a real browser engine fixes rendering and the network-layer fingerprints in one move. But default headless Chrome or a stock Puppeteer/Selenium setup is detected almost as easily as an HTTP client, because automation frameworks were built for testing, not stealth. Out of the box they announce themselves:
navigator.webdriveristrue.- The User-Agent contains
HeadlessChrome. - CDP (Chrome DevTools Protocol) attachment and
Runtime.enableusage are observable. - WebGL reports a software renderer; fonts and plugins are sparse or absent.
- The automation infobar and various injected globals betray the driver.
Patching these one at a time with stealth plugins is an arms race you are structurally losing: each plugin is a public, fingerprintable patch, and detection vendors test against them directly. The durable answer is not to patch a testing tool into looking like a browser, but to drive a browser that never looked like a testing tool in the first place.
The real-browser-with-real-fingerprint approach
The approach that holds up is a real browser engine presenting a genuine, internally consistent fingerprint, driven without leaving automation traces. This is the model of a purpose-built antidetect browser, and it differs from a stealth-plugin stack in where the spoofing happens.
The critical distinction is native versus injected. Stealth plugins inject JavaScript to overwrite properties like navigator or the canvas API after the page loads. That injection is itself detectable — the overridden functions no longer look native, the timing is observable, and Web Workers and cross-origin iframes often see the real, unpatched values because the injection never reached them. A native approach applies the fingerprint inside the browser core, so canvas, WebGL, audio, fonts, screen, User-Agent, timezone, languages, and geolocation are consistent everywhere the page can look — including inside Web Workers and iframes, where injected patches routinely leak the truth.
Dual Login is built on this model: a custom Chromium engine where the fingerprint is applied natively in the browser core rather than through JavaScript injection. Each profile carries fully isolated cookies, localStorage, and cache in sealed storage that survives restarts and is portable across machines, so a long-running collection session keeps its identity instead of resetting into a fresh, suspicious state on every run. For scraping specifically, that consistency is the whole game — a fingerprint that never contradicts itself is one the entropy checks cannot flag.
Automation runs over raw CDP or plain HTTP endpoints — goto, click, type, screenshot, OCR-based clicks, network capture — and navigator.webdriver stays false with no automation banners. It works with Selenium, Puppeteer, and Playwright, so you keep your existing scripts while shedding the tells those frameworks normally carry. You can verify what any profile actually exposes with the free browser fingerprint checker before you point it at a real target.
Proxy strategy for scraping
The cleanest browser fingerprint in the world will not save a scrape running from a blacklisted datacenter IP. Proxy strategy is half the battle, and it splits along two axes: rotation and IP type.
Rotating versus sticky sessions
- Rotating proxies assign a new IP per request or on a short interval. They suit high-volume collection of independent public pages where no session state matters — a product catalog, a set of search results. Rotation spreads your request rate across many IPs so no single address shows a suspicious pattern.
- Sticky (session) proxies hold one IP for the life of a session. They are mandatory whenever you are logged in or the site ties a session cookie to an IP; rotating mid-session — a login from São Paulo followed instantly by a request from Warsaw — is an obvious anomaly that triggers immediate re-authentication or a block.
Residential versus datacenter
The right IP type depends on how hard the target defends itself. The full trade-off is covered in our residential vs datacenter proxies guide, but the short version:
- Datacenter proxies are cheap and fast, and fine for lightly-defended or API-first targets. On anything with a serious anti-bot layer they are flagged by ASN before you send a request.
- Residential and mobile proxies route through real consumer connections, so their reputation is clean and they blend into ordinary traffic. They cost more and run slower, but on a well-defended target they are the difference between data and a block page.
Match the tier to the target. Do not pay residential prices to scrape an unprotected site, and do not waste a week fighting a hardened target with datacenter IPs.
Whichever you choose, the proxy and the fingerprint must agree. If your exit IP geolocates to Germany, the browser's timezone, locale, and language should say Germany too, and WebRTC must not leak your real address. Dual Login handles per-profile HTTP, HTTPS, and SOCKS5 proxies (with or without auth) and auto-matches timezone, locale, and geolocation to the proxy exit IP, with WebRTC masked to that IP natively — closing the most common contradiction between network and browser layers.
Detection method versus mitigation
The following table maps each detection signal to the practical mitigation. Treat it as a checklist for auditing your own pipeline.
| Detection method | What it catches | Mitigation |
|---|---|---|
| IP reputation (ASN, blocklists) | Datacenter and abused IPs | Residential/mobile proxies matched to target tier |
| Request-rate analysis | High volume, mechanical timing | Rate-limit; randomize intervals; cap concurrency |
| TLS / JA3–JA4 fingerprint | Non-browser HTTP clients | Drive a real browser engine, not an HTTP library |
| HTTP header order and client hints | Libraries faking browser headers | Real browser sends correct order and sec-ch-* natively |
Headless signatures (webdriver, CDP) |
Default Puppeteer/Selenium | Antidetect browser; webdriver:false, no automation banners |
| Fingerprint entropy/consistency | Impossible or repeated fingerprints | Native, internally consistent per-profile fingerprints |
| Behavioral timing | Instant clicks, zero dwell | Human-paced actions, scrolling, randomized delays |
| Honeypot links | Crawlers following hidden anchors | Respect CSS visibility; never follow display:none links |
| CAPTCHA escalation | Uncertain aggregate score | Slow down and improve IP quality — do not auto-solve |
Concurrency and politeness
Concurrency is where disciplined scrapers separate from blocked ones. The goal is throughput that stays under the target's radar, not maximum requests per second.
- Cap concurrent sessions per target. Start low — two or three parallel profiles — and raise only if the target shows no stress signals. Each profile should look like a separate, unhurried user.
- Randomize timing. Add jitter to delays between requests and actions. Mechanical regularity is itself a fingerprint; a spread of 3–8 seconds beats a fixed 5.
- Distribute across IPs and identities. One clean fingerprint plus one clean IP per logical session. Running twenty sessions through one IP or one fingerprint concentrates risk exactly where detection looks.
- Back off on stress signals. When you see 429s, slow responses, or the first CAPTCHA, reduce rate immediately. Pushing through is how a soft throttle becomes a hard IP ban.
- Respect crawl windows. Where a site publishes preferred crawl times or a
Crawl-delay, honor them.
Politeness is not only ethical; it is the most reliable anti-block technique there is. A crawler the target barely notices is a crawler it does not block.
Session and cookie management
For anything involving login or persistent state, session handling determines whether you look like a returning user or a fresh anomaly every run. Real users accumulate cookies, keep localStorage between visits, and return with the same identity for weeks.
Isolate each identity completely: one profile, one cookie jar, one localStorage, one cache, one proxy. Cross-contamination — profile A's cookies surfacing under profile B's fingerprint — is a strong linkage signal that collapses your separate identities into one detectable cluster. Persistence matters just as much: a session that keeps its cookies and storage across restarts looks like a real returning user, while one that starts empty every time looks like automation. This is why sealed, per-profile storage that survives restarts and moves with you across machines is worth more for scraping than it first appears. Managing many such identities cleanly is the same discipline covered in managing multiple accounts; bulk cookie and login import, and CSV-based profile creation, keep it manageable at scale.
Handling CAPTCHAs the legitimate way
When CAPTCHAs appear, treat them as a diagnostic, not an obstacle to bulldoze. A CAPTCHA means your session already lost enough signals that the system is unsure about you. The legitimate response addresses the cause:
- Slow down. Reduce request rate and add dwell time. Frequently the CAPTCHA rate collapses once your timing looks human.
- Improve IP quality. Move from datacenter to residential IPs, or rotate away from an address that has accumulated a bad reputation on this target.
- Fix fingerprint contradictions. A timezone or language that disagrees with the IP is a common trigger. Verify consistency with a fingerprint checker.
- Reconsider the target. Persistent CAPTCHAs on a site that clearly does not want automated access is a signal to stop and check whether an API or a data license exists instead.
What this guide does not endorse is wiring an automated solving service into a pipeline that scrapes a target which prohibits it. That crosses from resilience into evasion of an explicit boundary, and it is exactly the behavior that turns a defensible project into an indefensible one.
Parsing and pipeline reliability
Getting the page is half the job; turning it into clean data reliably is the other half. A scrape that silently returns malformed rows is worse than one that fails loudly.
- Parse defensively. Sites change markup constantly. Prefer stable selectors, and validate that extracted fields match expected types and ranges before writing them.
- Detect soft failures. A block often returns a 200 with a CAPTCHA or empty template, not an error code. Assert on content — expected element present, row count in a sane range — and treat a violated assertion as a failure to retry or alert on.
- Retry with backoff, and cap it. Transient failures deserve a few retries with exponential backoff. Persistent failure against one identity should rotate the identity or pause the job, not hammer forever.
- Separate collection from parsing. Store raw responses, then parse in a second pass. When a selector breaks you can re-parse history instead of re-scraping, which is both faster and kinder to the target.
- Monitor block rate as a first-class metric. A rising block or CAPTCHA rate is your earliest warning that a fingerprint, proxy pool, or pace needs attention.
A minimal defensive extraction pass looks like this:
def extract_rows(html):
doc = parse(html)
if doc.select_one("form#captcha") or not doc.select(".product"):
raise BlockedResponse("no products found — likely soft block")
rows = []
for el in doc.select(".product"):
price = el.select_one(".price")
if price and price.text.strip():
rows.append({"title": el.select_one(".title").text.strip(),
"price": price.text.strip()})
return rows
The point is not the parser itself but the guard at the top: it turns a silent soft-block into an explicit, retryable failure.
FAQ
Is web scraping legal?
Scraping public data is broadly permissible in many jurisdictions, but legality depends on what you collect and how. Respect robots.txt and terms of service, avoid personal data unless you have a lawful basis, do not circumvent access controls, and prefer official APIs. When a project touches personal or copyrighted data, get legal advice rather than guessing.
Why do I get blocked even with a good proxy?
Because the proxy is only one signal. If your TLS fingerprint says Python, your headless Chrome sets navigator.webdriver to true, or your fingerprint contradicts the proxy's geolocation, a clean IP will not save you. Blocking is a composite score; you have to pass the browser and behavioral checks too.
Do I need a real browser to scrape?
For static, server-rendered pages, no — an HTTP client is faster. For JavaScript-heavy sites or defended targets, yes. A real browser renders client-side content and produces genuine TLS and header fingerprints that HTTP clients cannot fake reliably.
What is the difference between a stealth plugin and an antidetect browser?
A stealth plugin injects JavaScript to patch a standard browser after load, which is itself detectable and often leaks inside Web Workers and iframes. An antidetect browser like Dual Login applies the fingerprint natively in the engine, so it is consistent everywhere and leaves no injection trace.
How fast can I scrape without getting blocked?
There is no universal number — it depends on the target's tolerance. Start conservative (a few concurrent sessions, several seconds between requests, jittered), watch for 429s and CAPTCHAs, and raise the rate only while those stay at zero. Politeness beats speed every time.
Are datacenter proxies ever fine?
Yes — for API-first or lightly defended targets they are cheaper and faster with no downside. Reserve residential and mobile proxies for targets whose anti-bot layer flags datacenter ASNs, and match the tier to the defense rather than overpaying by default.
Final thoughts
Scraping without getting blocked comes down to coherence: a real browser, a consistent fingerprint, an IP whose reputation and geolocation agree with that fingerprint, a human pace, and a project scoped to data you are permitted to collect. Miss any one and the composite score catches you; get them all aligned and you look like exactly what a detection system is built to ignore — an ordinary user.
If you want the browser layer handled without maintaining a stealth-plugin arms race, Dual Login gives you a native-fingerprint Chromium engine, isolated per-profile storage, per-profile proxies with matched timezone and masked WebRTC, and automation over CDP or HTTP that keeps navigator.webdriver false. The free plan includes 10 profiles with no credit card, so you can test a real collection workflow end to end before committing — compare it against the alternatives, check the pricing, or download the desktop app for Windows, macOS, or Linux and see how your current pipeline holds up with a clean identity underneath it.