The Full Anti-Detection Stack: Proxy + Browser + Behavior for 2026
Your proxy is one layer. Anti-bot systems run four. Here is what each layer checks, what tool addresses it, and how they have to work together to actually pass.
Modern anti-bot systems run four independent detection layers. Each layer has to be addressed separately. Failing one means you fail the session, regardless of how well you handled the other three.
- Layer 1 is IP reputation. Datacenter ranges fail immediately. Residential and ISP proxies pass, but passing Layer 1 only means the other three layers now run.
- Layer 2 is TLS fingerprinting, and it fires before any HTTP header is read. Python's requests module has a known JA4 signature that DataDome and Cloudflare flag before your user-agent, cookies, or headers even matter. Fix: curl_cffi or real Chromium.
- Layer 3 is the browser JS environment. navigator.webdriver, canvas fingerprint, WebGL renderer, AudioContext, screen geometry. playwright-stealth patches 12 of the 40+ signals checked. Fix: pair it with Camoufox, or use a proper anti-detect browser for account management work.
- Layer 4 is behavioral analysis. Mouse trajectory entropy, scroll velocity, click coordinate accuracy, request timing regularity. Static time.sleep(2) is as detectable as 1,200 requests per minute. Fix: Bezier-curve mouse simulation, randomized timing from realistic distributions, session warming.
- ISP Static proxies fit session-consistent workflows. Rotating the IP mid-session while keeping the same cookies is a documented bot signal on Cloudflare, DataDome, and Akamai.
I have watched people spend two days debugging a blocked scraper when the fix took four lines. And I have also watched people add four layers of tooling when the target was only running one check. The real problem in both cases is the same one: not knowing which detection layer is actually firing.
Detection in 2026 is not one system. It is a chain. Each link in that chain is independent, evaluated separately, and requires a separate fix. The proxy you chose addresses exactly one link. What happens after that depends on what the other three links find.
This is a breakdown of the full stack. Not just "use residential proxies." All four layers, what each one actually checks, and what to run against each of them.
The Four-Layer Detection Chain (And Why Each One Runs Independently)
Most guides present detection as a single thing. Get a clean IP, rotate it, add some headers, done. That model was accurate in 2019. It is not accurate now.
The detection chain that most serious anti-bot systems run in 2026 looks like this:
The key thing to understand is that these layers do not have awareness of each other's results in the way you might hope. Passing Layer 1 cleanly does not earn you leniency at Layer 2. A perfect Layer 3 fingerprint does not compensate for Layer 4 failures. Each layer runs on its own signals, scores on its own model, and can produce its own outcome.
There is also the coherence problem. Individual signals that each pass their own check can still get flagged when the platform looks at them together. A browser claiming to be Chrome on Windows, with a Canvas fingerprint consistent with Linux, a timezone set to UTC while the IP geo-resolves to Tokyo, and a screen resolution that no real Windows device ships with: each individual signal might pass a narrow check. The combination fails a coherence check that fires after all of them. These are sometimes called Franken-Fingerprints, and they are a reliable sign of a manually assembled anti-detection stack where someone patched the obvious signals without thinking about consistency.
Layer 1: The Proxy (Your Network Identity)
IP reputation is the first check and the fastest one. Anti-bot systems maintain or query databases of IP behavior history and ASN classification. The decision on your IP happens within milliseconds of the TCP connection, before a TLS handshake, before a single HTTP byte.
The ASN tells the system whose IP range this is. AWS, Google Cloud, DigitalOcean, and every major cloud provider have well-documented ASN ranges. A request from AS16509 (Amazon) hits a datacenter classification check before the IP's individual history matters at all. This is why datacenter proxies fail on heavily protected targets even when the specific IP has no prior abuse history. The range is flagged, not the address.
Residential and ISP proxies register under consumer ISP ASNs. Comcast, Verizon, BT, Telkom Indonesia, NTT Communications. These are the same ASN ranges that real users' home connections come from. That classification is what passes the initial check: not the IP's individual reputation, but its network origin.
Residential vs ISP Static: The Actual Difference
Both residential and ISP static proxies pass the ASN classification check. The difference is stability, and that difference matters more than most people realize when you get to the behavioral layer.
Rotating residential proxies draw from real home device IP addresses. Each request, or each session, can come from a different IP within the pool. For large-scale scraping where session continuity does not matter, that is fine. For workflows where the same session needs to persist across multiple page requests, account logins, checkout flows, multi-step form completions, rotating the IP mid-session while the same session cookie remains active produces a location coherence anomaly. The platform sees a session established from an IP in London, then the next request in that same session arriving from an IP in Manchester, under the same cookie. That is a documented bot detection signal on Cloudflare, DataDome, and Akamai.
ISP static proxies give you a fixed IP registered with a consumer ISP, hosted on fast datacenter infrastructure. The IP stays constant for the full duration of your session. Behavioral signals related to location coherence pass without issue because nothing changes. This is the proxy type for any workflow that needs IP stability: anti-detect browser profiles, account management, checkout automation, anything with a session cookie that must outlast more than one page load.
Which Proxy to Use and When
| Proxy Type | Best For | IP Stability | Detection Risk | TorchProxies Price |
|---|---|---|---|---|
| ISP Static | Account management, checkout flows, anti-detect browser profiles, any multi-step session | Fixed | Low | $4/GB |
| Premium Residential | Large-scale data collection, SERP scraping, product data, classified listings | Rotating | Low | $4.5/GB |
| Standard Residential | Mid-volume scraping, 195-country coverage, pay-as-you-go projects | Rotating | Low | $4/GB |
| Plan X (Hybrid) | Complex workflows needing both ISP consistency and residential volume: 120M+ IPs, 180+ countries | Flexible | Low | $5/GB |
Layer 2: TLS Fingerprinting (Before Your Request Even Fires)
This is the one that catches the most people. You have a clean residential IP. You have set headers that look like Chrome. You have rotated carefully. And DataDome still blocks you before returning a single byte of content. The block happens at the TLS layer, and none of your HTTP-level work is relevant to it.
When any HTTPS client connects to a server, it initiates a TLS handshake by sending a ClientHello message. This message contains the list of cipher suites the client supports, the TLS extensions it includes, their ordering, the elliptic curves it prefers, and GREASE values. JA4 hashes these into a single fingerprint. Each HTTP client library produces a distinct hash: Python's requests module has its own, httpx has another, bare curl has another. They are well-documented and widely catalogued by anti-bot vendors.
DataDome scores the TLS ClientHello before reading any payload, and a non-Chrome JA4 signature is enough to escalate to a CAPTCHA challenge regardless of IP type. Akamai adopted JA4 as its commercial TLS fingerprinting standard, specifically because JA4 catches automation libraries that had learned to spoof the older JA3 format. Cloudflare Enterprise Bot Management integrates JA4 into its WAF rule engine. This layer fires before your user-agent, your cookies, or your Accept-Language header are ever examined.
Fix Option 1: curl_cffi
curl_cffi is a Python binding for curl-impersonate that mimics the TLS handshake of real browsers. Unlike standard requests or httpx, curl_cffi patches the libcurl TLS configuration to replicate Chrome's or Firefox's exact cipher suite ordering, extension list, and GREASE values. The result is a JA4 fingerprint that matches a real browser.
For 2026, the maintained browser profiles are chrome124 and chrome131. Either one is the correct default for most production scrapers targeting Cloudflare-protected sites. The library is available on PyPI as curl-cffi and installs as a drop-in for requests: the interface is nearly identical, which makes migration simple.
curl_cffi is the right choice when you do not need a full browser rendering environment: API scraping, request-heavy pipelines, any target where the JS layer is not running active detection. It addresses Layer 2 cleanly without the overhead of spinning up a browser process per request.
Fix Option 2: Real Chromium via Playwright
When the target runs JavaScript-based detection (Layer 3), you need a real browser environment anyway. Playwright launches actual Chromium, which uses Chrome's native TLS stack. The JA4 fingerprint produced is identical to a real Chrome browser because it is a real Chrome browser doing the handshaking.
The important clarification here: playwright-stealth does not fix the TLS layer. Playwright-stealth patches JavaScript properties inside the browser context after the TLS handshake has already completed. The TLS fingerprint is determined at the C++ level by Chromium's network stack, which is not accessible to JavaScript and therefore not accessible to any JavaScript-based stealth plugin. Running Playwright gives you the correct TLS fingerprint. Running playwright-stealth on top of it does not affect that fingerprint either way.
HTTP/2 Frame Ordering
The second connection-layer signal runs alongside JA4: HTTP/2 frame ordering. HTTP/2 sends configuration frames in sequences that differ between browser implementations. Chrome, Firefox, Safari, and curl each produce distinct SETTINGS frame orderings and WINDOW_UPDATE increments. A scraper claiming to be Chrome 124 but sending HTTP/2 frames consistent with curl's output gets flagged at this layer even if the JA4 hash is correct. Akamai's detection specifically catches this combination.
curl_cffi handles HTTP/2 frame ordering correctly for the browser profile you select, because it patches libcurl's HTTP/2 implementation. Playwright running real Chromium handles it correctly by definition. Bare curl or Python HTTP libraries do not.
Layer 3: Browser Fingerprinting (The JavaScript Layer)
Assume the IP passed and the TLS fingerprint matched Chrome. Now the platform injects JavaScript into the page load and starts collecting browser environment signals. This is what most people think of when they hear "bot detection," but it is only Layer 3 of four.
The signals collected at this layer include, but are not limited to:
- navigator.webdriver: the automation flag Playwright sets by default. This is the most basic check and the first thing playwright-stealth patches.
- Canvas fingerprint: the hash of a rendered canvas element. Different GPUs and font rendering stacks produce different pixel outputs. A headless Chrome rendering on a Linux server with no GPU produces a different hash than a real Chrome on Windows 11. Anti-bot systems maintain databases of expected canvas hashes per OS/GPU combination and flag mismatches.
- WebGL renderer and vendor strings: revealing the underlying GPU and driver. A headless browser typically reports a software renderer (SwiftShader, llvmpipe) which is a strong bot signal.
- AudioContext baseValue: a hardware-dependent audio processing signature that differs by device.
- Screen resolution and color depth: compared against claimed hardware.
- navigator.hardwareConcurrency and deviceMemory: the reported CPU core count and RAM must be plausible for the device claimed.
- Installed fonts and plugins: real browsers on real devices have real installed font sets. A headless browser typically has a minimal or empty font list.
- Timezone consistency: the JS-reported timezone must match the IP's geo-location.
Anti-bot systems check more than 40 of these properties and their relationships to each other. playwright-stealth patches approximately 12 of them, specifically the most obvious ones. The gaps in coverage are documented: WebGL renderer spoofing is incomplete in some configurations, navigator.permissions behavior is not always patched, and window.chrome completeness varies across versions. The playwright-stealth npm package has not been updated in over a year as of mid-2026, which means detection systems have had time to learn its patch patterns.
Camoufox: Patching at the Right Layer
Camoufox is a Firefox fork built specifically for anti-detection. The key architectural difference from playwright-stealth is where the patches happen. Playwright-stealth injects JavaScript that overwrites browser properties at the JS level, after the browser's native implementation has run. Camoufox patches Firefox at the C++ implementation level, before JavaScript ever executes. navigator.hardwareConcurrency, WebGL renderers, AudioContext, screen geometry, WebRTC: all spoofed at the source, not at the JS exposure layer. There is nothing for a JavaScript-level detection script to find because the patching has already happened underneath JavaScript.
Camoufox also uses BrowserForge's fingerprint generator to produce statistically realistic device profiles. Rather than picking a random screen resolution and GPU combination, it samples from real-world distribution data, so the profiles it generates match the frequency patterns of actual user traffic. Presenting as a Linux user 5% of the time and a Windows user 75% of the time, for example, matches real-world distributions rather than being an obviously arbitrary selection.
The caveat: Camoufox (v146.0.1-beta.25, January 2026) is explicitly marked experimental. The project went through a maintenance gap through most of 2025 with no updates, and is still recovering. It works well in controlled environments and development setups, and its technical architecture is genuinely superior to JavaScript-level stealth patching. For production workloads that require stability, most teams use playwright-stealth as the default baseline on Chromium and switch to Camoufox selectively on targets where Chromium's fingerprint is specifically being blocked.
Anti-Detect Browsers: When You Need Persistent Profiles
For account management work specifically, managing multiple accounts across social platforms, e-commerce sites, or ad networks, the requirement shifts from one-off request stealth to persistent, coherent browser identity across sessions. Anti-detect browsers are purpose-built for this.
AdsPower (Base plan: $5.40/month for 10 browser profiles; Pro: $30/month for 100 profiles; permanent free plan for 2 profiles) uses a dual-engine architecture with SunBrowser and FlowerBrowser, supports 50+ configurable fingerprint parameters, and includes built-in RPA automation for no-code workflow setup. Multilogin starts at $19/month for 100 profiles and is more resource-intensive but has a longer track record on high-scrutiny targets. Both generate isolated browser profiles where the full fingerprint, user-agent, canvas, WebGL, fonts, screen resolution, timezone, installed plugins, is consistent across sessions for a given account.
These tools are the right choice when you need to maintain long-term account identity. For scraping work where you are not managing persistent accounts, Camoufox or playwright-stealth plus a consistent device profile is sufficient and significantly cheaper.
Layer 4: Behavioral Simulation (The Human Layer)
This is the layer that runs longest, updates continuously, and is the hardest to fake. IP reputation is evaluated once at connection time. TLS fingerprint is evaluated once during the handshake. Browser fingerprint is evaluated at page load. Behavioral signals accumulate across the entire session, and platforms like Cloudflare (via the __cf_bm cookie) and Akamai (via _abck) update the session score in real time as new behavioral data arrives.
What they are actually measuring:
Mouse Trajectory Entropy
Real human mouse movements follow curved, slightly inconsistent paths. The statistical entropy of a movement trace across a session is measurable. Bots produce one of two failure patterns: perfectly linear straight-line movement (near-zero trajectory entropy, statistically impossible for a human producing sustained movement), or no mouse events at all. A trace that is too smooth fails the same behavioral check as an absent trace. The signal is not the presence of movement, it is the naturalness of it.
The fix is Bezier-curve movement simulation with jitter and randomized speed variance. Libraries like humanization-playwright (available on PyPI) and shy-mouse-playwright implement this. The movement path follows a cubic Bezier curve with slight velocity variance and micro-corrections rather than moving in a straight line at constant speed. This is not optional on targets running DataDome or Akamai.
Scroll Depth and Velocity
A session that loads a product page and immediately calls a checkout API without generating any scroll events is not how real users navigate. Platforms track scroll velocity, depth, and the presence of return-scroll events (real users scroll down, then sometimes back up to re-read something). A complete absence of scroll events is itself a signal, as is a single mechanical scroll-to-bottom event with perfectly linear deceleration.
Realistic scroll simulation uses logarithmic deceleration, occasional pauses, variable step sizes, and small mouse movements during the scroll. The goal is a scroll event log that could plausibly have been produced by a person reading at a realistic pace.
Click Coordinate Accuracy
Real users click slightly off-center from element centroids. They sometimes hover over an element before clicking. Occasionally they mis-click and correct. Automated scrapers click at exact pixel coordinates, often at the exact center of every element, every time. DataDome and HUMAN Security collect click coordinate data and compare it against known human distributions. Clicking perfectly at the centroid of every button, on every interaction, across the full session, is a detectable pattern even if every other signal is clean.
Request Timing Distribution
The most misunderstood signal at this layer. The check is not on speed, it is on regularity. A bot making requests at exactly 2.0-second intervals is more obviously automated than one making 1,200 requests per minute with genuine variance in timing. Regularity is the fingerprint, not volume.
Standard exponential backoff, the default advice in almost every scraping guide written before 2024, is now itself a recognized automation pattern. Detection systems have been trained on traffic that includes backoff implementations and can identify the characteristic acceleration-then-deceleration pattern it produces. Randomized delays drawn from realistic human reading and decision timing distributions outperform both fixed intervals and backoff on modern targets.
time.sleep(2) means every request interval is exactly 2.0 seconds. That regularity is more detectable than an interval of 0.1 seconds with natural variance. Draw delays from a realistic distribution: something like a Gaussian centered around your target delay with variance that produces occasional fast and occasional slow intervals, the way actual reading and navigation do.
Session Warming
Platforms like Cloudflare (via __cf_bm) and Akamai (via _abck) accumulate behavioral history across the session. A session that starts with realistic browsing behavior builds a behavioral credit that absorbs more variation in later requests. A session that opens directly on a checkout API, a pricing endpoint, or a protected resource starts with no behavioral credit and is immediately under maximum scrutiny.
Practical session warming means navigating to a homepage or landing page first, generating a realistic dwell time with scroll events and at least one mouse movement, then navigating toward the target. It takes perhaps 10-15 seconds of additional setup time and significantly improves pass rates on behaviorally sensitive targets. I have not found a precise credit threshold that translates directly across platforms, those thresholds are proprietary. What I can say is that a warmed session consistently outperforms a cold one on every hardened target I have worked with.
humanization-playwright) adds randomized Bezier-curve mouse paths, variable typing delays, and realistic scroll behavior to Playwright sessions. shy-mouse-playwright is a lighter alternative focused specifically on mouse movement humanization. Neither replaces the need to address Layers 1-3, but both are necessary additions for targets running DataDome or Akamai.
Putting the Stack Together: Full Architecture
The four layers map to four specific tool choices. Which combination you use depends on the target's detection sophistication.
Stack A is the right call when the target is primarily TLS-aware but not running full JS-based detection. Many sites in this category are protected by WAF rules that evaluate the JA4 hash but do not inject JavaScript behavioral sensors. curl_cffi with an ISP static proxy handles these without any browser overhead.
Stack B is necessary for targets running DataDome, Akamai Bot Manager, or HUMAN Security. These platforms inject JavaScript sensors that require a real browser environment. Playwright with playwright-stealth (or Camoufox on targets where Chromium's fingerprint is blocked) plus behavioral simulation is the complete implementation for these targets.
Both stacks route through Layer 1 the same way. The proxy choice does not change based on which browser tools you use.
Common Stack Mistakes and What They Cost You
Most of the debugging I have done on blocked scrapers comes down to a small set of recurring errors. Each one fails at a specific layer:
| Mistake | Layer That Fails | What You See | Fix |
|---|---|---|---|
| Datacenter proxy + any browser setup | Layer 1 | 403 or challenge before TLS handshake | Switch to ISP static or residential proxy |
| Residential proxy + Python requests | Layer 2 | CAPTCHA or 403 on TLS-aware targets (DataDome, Cloudflare), before headers are read | Replace requests with curl_cffi using chrome131 profile |
| Playwright with no stealth patches | Layer 3 | JS challenge or block: navigator.webdriver is true by default | Add playwright-stealth or switch to Camoufox |
| playwright-stealth with no TLS fix | Layer 2 | Still blocked on DataDome / Cloudflare despite correct UA and navigator | Confirm you are using real Playwright Chromium (not requests + stealth), so TLS is native Chrome |
| Perfect fingerprint, no behavioral simulation | Layer 4 | Gets through initial check, then blocked or challenged mid-session | Add humanization-playwright, session warming, randomized delays |
| Rotating IP mid-session with same cookie | Layer 4 | Session challenged or invalidated after IP change | Use ISP static proxy or sticky session for session-stateful workflows |
| Inconsistent locale / timezone / UA combination | Layer 3 Coherence | Passes individual checks but fails coherence scan: Franken-Fingerprint | Build device profiles from a single consistent template, not piecemeal patches |
Testing Your Stack Before You Hit Production
Running directly at a protected target to test your stack is slow feedback. You get one data point per blocked session and no visibility into which layer failed. There are dedicated testing tools that isolate each layer.
| Tool | What It Tests | Which Layer |
|---|---|---|
| bot.sannysoft.com | navigator.webdriver, window.chrome, WebGL, Canvas, and ~20 other JS automation markers | Layer 3 |
| browserleaks.com | TLS fingerprint, JA4 hash, WebGL renderer, canvas hash, font list, WebRTC leaks | Layer 2 + 3 |
| pixelscan.net | Full fingerprint consistency and coherence check, flags Franken-Fingerprint combinations | Layer 3 Coherence |
| iphey.com | IP reputation, ASN classification, timezone / locale consistency with IP geo-location | Layer 1 + 3 |
Test in this order: iphey.com first to confirm the IP and locale are coherent, then browserleaks.com for TLS and fingerprint, then bot.sannysoft.com for JS-level automation markers, then pixelscan.net for coherence. A complete stack should return clean on all four. Fix issues bottom-up: coherence problems at pixelscan typically trace to mismatched Layer 3 settings that browserleaks will identify specifically.
Frequently Asked Questions
__cf_bm cookie, and IP reputation checks. curl_cffi works well for targets that are primarily TLS-aware but not running full JS-based detection. For sites behind Cloudflare Bot Management, you also need to address the JS fingerprint and behavioral layers.
_abck cookie throughout the session.