Free test available for France , UK or SG on Telegram Join Telegram •
Stealth Browser Automation Guide

How to Use Camoufox to Bypass Anti-Bots in 2026: Mobile Proxy & Playwright Guide

Master Camoufox anti-detect browser with Playwright: C++ stealth fingerprinting, 4G/5G mobile proxy integration, GeoIP matching, and bypassing Cloudflare Turnstile & DataDome.

Playwright & Python October 2, 2026 10 min read
C++ Stealth Hardened Gecko engine
GeoIP Sync Timezone & WebRTC spoofing
99.4% Anti-bot bypass rate
7+ Carrier locations
  • C++ engine-level stealth — patches Mozilla Firefox source code directly, leaving zero detectable JavaScript runtime prototypes or automation flags.
  • Automated GeoIP synchronization — dynamically aligns browser timezone, navigator language, and WebRTC coordinates with your mobile proxy egress IP.
  • Humanized bezier cursor paths — simulates organic mouse acceleration curves and jitter to defeat biometric WAF challenge analyzers.
  • Persistent session clearance — retains Cloudflare Turnstile cf_clearance tokens across runs using cached profile directories.
Anti-Bot Bypass Stealth Automation
Base browserMozilla Firefox (Gecko C++)
API bindingPlaywright (Sync & Async)
Headless modeNative & Xvfb Virtual Display
Proxy protocolHTTP & SOCKS5 with Auth
C++ Layer Masking

Carrier CGNAT Trust

Automated GeoIP Alignment

What Is Camoufox & Why C++ Stealth Matters

AI agents, automated scrapers, and data pipelines need to browse the real web. But standard automation frameworks get blocked within milliseconds. Headless Chromium gets fingerprinted immediately. And traditional stealth plugins? They become the fingerprint.

Camoufox completely eliminates this detection surface by patching Mozilla Firefox at the underlying C++ implementation level. Instead of injecting fragile JavaScript wrappers, every fingerprint parameter—from navigator.hardwareConcurrency, WebGL renderers, and AudioContext to screen geometry and WebRTC—is modified directly inside the Gecko C++ engine before JavaScript ever sees it. No shims, no wrappers, and zero detectable tells.

The Flaw of JS Stealth: Plugins Become the Fingerprint

Tools like puppeteer-extra-plugin-stealth override window.navigator via Object.defineProperty. Modern challenge scripts inspect prototype chains with Function.prototype.toString.call() and measure getter execution timing, exposing the wrapper instantly.

The Camoufox Solution: Native C++ Gecko Modification

Camoufox patches Firefox C++ source code before compilation. The navigator.webdriver variable does not exist in the C++ struct. Hardware concurrency, canvas noise, system fonts, and WebGL parameters are evaluated natively by the OS rendering pipeline with zero JS overhead.

How It Works: Bypassing Cloudflare Turnstile & DataDome Under the Hood

To understand how Camoufox consistently achieves first-pass bypasses against Cloudflare Turnstile, DataDome, and Kasada, you must look at how modern challenge firewalls evaluate incoming traffic. Detection is not a single flag—it is a three-layer verification chain:

Layer 1: JavaScript Runtime Entropy & Prototype Integrity

When a browser loads a Cloudflare-protected page, Turnstile injects challenge script telemetry. It runs client-side proof-of-work (PoW) routines that query low-level browser APIs: WebGL shader precision, AudioContext buffer harmonics, performance.now() high-resolution timers, and navigator property descriptors.

In Chromium-based stealth browsers, these queries execute against JavaScript Proxy objects or patched getters. The microsecond latency delay and slight discrepancies in prototype inheritance immediately flag the session as automated. In Camoufox, these queries hit compiled C++ Gecko routines. The telemetry returned to Cloudflare matches an authentic, real-world Firefox installation down to the last CPU cycle.

Layer 2: Network Stack & GeoIP Parameter Harmony

A pristine browser fingerprint is useless if your egress network leaks automation attributes. Cloudflare correlates client-side browser claims against server-side TCP/IP packet signatures. If your browser reports an Apple macOS environment with British English locale, but the TCP SYN packet has a Linux TTL/window-size signature originating from a French datacenter subnet, Turnstile triggers an unsolvable challenge loop.

Camoufox with geoip=True queries an offline MaxMind database to automatically bind browser timezone, navigator language, and WebRTC STUN candidate filters to your proxy IP. When routed through PXM2 dedicated 4G/5G mobile modems, traffic exits via mobile carrier CGNAT (Carrier Grade NAT). Because millions of legitimate smartphone users share these identical IP blocks, Cloudflare cannot block the subnet without causing massive collateral damage to real consumer traffic.

Layer 3: Behavioral Biometrics & Bezier Acceleration

If Turnstile serves an interactive verification box ('Verify you are human'), standard Playwright clicks teleport the mouse cursor instantaneously to the target coordinate (x, y) with zero intermediate mousemove events. WAF sensors immediately detect linear or instantaneous velocity vectors.

With humanize=True, Camoufox generates organic curved bezier trajectories with realistic human jitter, acceleration, and deceleration curves. When clicking inside cross-origin Turnstile iframes (paired with disable_coop=True), the biometric sensor validates natural human motor behavior, seamlessly dispensing the cf_clearance cookie.

Deep Dive Why C++ Layer Modification Beats JavaScript stealth.js Extensions

Commercial anti-bot engines run micro-benchmarks that inspect JavaScript prototype chains, native function toString() outputs, and execution stack traces. Tools like puppeteer-extra-plugin-stealth override window.navigator via Object.defineProperty. Any modern challenge script can uncover these hooks by executing Function.prototype.toString.call(Object.getOwnPropertyDescriptor(navigator, 'webdriver').get).

Camoufox patches the Mozilla Gecko rendering engine before compilation. The navigator.webdriver variable does not exist at all, C++ font enumeration returns OS-accurate system fonts, and WebGL shader parameters match real hardware without injecting JavaScript wrappers.

System Prerequisites & Installation

Camoufox is distributed as a lightweight Python wrapper that pairs with a customized Firefox binary. Setup requires Python 3.8+ on Windows, macOS, or Linux (Ubuntu/Debian/CentOS).

1. Install the Python Package with GeoIP Extension

Always install the [geoip] extra. This bundles the offline MaxMind database required to automatically align the browser timezone, locale, and WebRTC coordinates with your proxy exit node IP.

Terminal · Pip Installation
pip install -U "camoufox[geoip]" playwright
Installs Python Playwright bindings and offline geolocation database

2. Download the Hardened Firefox Binary

Run the fetch CLI command to download the modified Gecko engine binary. It pulls roughly 250MB once and stores it in your local cache.

Terminal · Fetch Hardened Firefox Binary
camoufox fetch
Automatic download of patched C++ browser binary

3. Quick Launch Verification

Run a test script to verify browser launch, fingerprint injection, and automated cleanup.

Python · Quick Smoke Test
from camoufox.sync_api import Camoufox

# Launch lightweight hardened instance
with Camoufox(headless=True) as browser:
    page = browser.new_page()
    page.goto("https://httpbin.org/headers")
    # Verify genuine Firefox headers without automation flags
    print(page.inner_text("body"))
Returns genuine Firefox user-agent headers without automation flags
Repository Notice: The core repository is maintained at scraperapi/camoufox (master checkpoint releases). Always use the stable camoufox package on PyPI for production deployments rather than experimental branches.

Basic Usage: Synchronous and Asynchronous APIs

Because Camoufox wraps Playwright, it exposes both synchronous and asynchronous contexts. Context managers automatically handle browser lifecycle and child process termination, preventing orphan Firefox zombies on scrapers.

Python · Asynchronous Concurrency with AsyncCamoufox
import asyncio
from camoufox.async_api import AsyncCamoufox

async def scrape_target(browser, target_url):
    page = await browser.new_page()
    try:
        await page.goto(target_url, wait_until="domcontentloaded", timeout=30000)
        title = await page.title()
        print(f"Successfully scraped: {title}")
        return await page.content()
    finally:
        await page.close()

async def main():
    urls = [
        "https://browserleaks.com/javascript",
        "https://browserleaks.com/canvas",
        "https://browserleaks.com/webgl"
    ]
    async with AsyncCamoufox(headless=True) as browser:
        tasks = [scrape_target(browser, u) for u in urls]
        await asyncio.gather(*tasks)

if __name__ == "__main__":
    asyncio.run(main())
Asynchronous concurrency using standard asyncio and Playwright Page contexts

PXM2 4G/5G Mobile Proxy Integration with GeoIP Matching

The most common detection trigger on protected sites is an identity mismatch: a browser reporting London timezone and British English locale while connecting from a French IP. Camoufox eliminates this failure mode when geoip=True is enabled. It resolves the proxy IP through MaxMind, automatically configuring timezone, language, and WebRTC coordinates before the first TLS packet departs.

Python · PXM2 Mobile Proxy Authentication & GeoIP Sync
import requests
from camoufox.sync_api import Camoufox

# PXM2 Dedicated Mobile Proxy credentials
PROXY_HOST = "gate.pxm2.io"
PROXY_PORT = 30001
PROXY_USER = "pxm2_user_demo"
PROXY_PASS = "secret_pass_123"
ROTATION_URL = "https://pxm2.io/api/v1/rotate/userproxy_1029/"

proxy_config = {
    "server": f"http://{PROXY_HOST}:{PROXY_PORT}",
    "username": PROXY_USER,
    "password": PROXY_PASS,
}

def rotate_mobile_ip():
    """Trigger cellular modem reconnect to cycle mobile IP in 5-10 seconds."""
    resp = requests.get(ROTATION_URL, timeout=15)
    if resp.status_code == 200:
        print("[PXM2] Cellular IP successfully rotated!")

# Launch Camoufox with automatic location synchronization
with Camoufox(
    proxy=proxy_config,
    geoip=True,           # Aligns timezone, locale, and WebRTC to proxy IP
    os="windows",         # Consistent OS fingerprint
    headless=True
) as browser:
    page = browser.new_page()
    page.goto("https://iphey.com")
    print("Security evaluation loaded under genuine cellular carrier ASN!")
Full proxy authentication, automatic timezone synchronization, and remote IP rotation
Anti-Bot Defense Why PXM2 Carrier CGNAT Prevents Subnet Bans on Cloudflare & DataDome

Cloud hosting facilities (AWS, DigitalOcean, Hetzner) allocate consecutive /24 IPv4 subnets. When a scraper triggers rate limits, firewalls block the entire 256-address block simultaneously.

In contrast, PXM2 4G/5G mobile proxies route traffic through physical enterprise modems on Tier-1 mobile carriers (Verizon, AT&T, Vodafone, Orange). Mobile operators employ Carrier Grade NAT (CGNAT), where thousands of legitimate smartphones share each public IP. Anti-bot engines cannot ban a cellular CGNAT address without locking out thousands of authentic mobile customers.

Scaling 50+ Concurrent Sessions: Multi-Proxy Pool & Cloudflare Bypass

Running 5 to 10 browser tabs is simple. Running 50 to 100 concurrent headless browser workers scraping protected endpoints or managing multi-account pipelines is where naive automation architectures crash.

When scaling high-concurrency pipelines, engineers face two primary obstacles:

Memory Bottleneck: The 30 GB Chromium Bloat

Spawning 50 individual Chromium browser processes easily demands 25–35 GB of RAM. Tab memory leaks during long scraping loops inevitably trigger Linux OOM-killer (Out of Memory) kills and socket drops.

Anti-Bot Collision: Subnet Ban Cascade

Routing 50 threads through shared datacenter or residential pools triggers Cloudflare rate-limiting. A single flagged request often burns the entire /24 IP subnet, locking out all 50 workers simultaneously.

The solution: Combine AsyncCamoufox with an asynchronous worker semaphore pool, bind each worker to an isolated PXM2 dedicated 4G/5G mobile modem, and enable automatic GeoIP synchronization. Because Camoufox’s C++ engine avoids heavy JS prototype hooks, memory consumption drops by up to 75% while each worker retains independent fingerprint entropy.

Python · High-Concurrency 50+ Session Worker Pool
import asyncio
import aiohttp
from camoufox.async_api import AsyncCamoufox

# Concurrency & Worker Limits: 50 concurrent browser sessions
MAX_CONCURRENT_SESSIONS = 50
semaphore = asyncio.Semaphore(MAX_CONCURRENT_SESSIONS)

# Pool of 50 dedicated PXM2 4G/5G mobile modems (separate ports / credentials)
PXM2_MOBILE_PROXIES = [
    f"http://user_demo:pass_demo@gate.pxm2.io:{30000 + i}"
    for i in range(50)
]

# Remote IP rotation webhook API
PXM2_ROTATE_API = "https://pxm2.io/api/v1/rotate/modem_{id}/"

async def rotate_modem(modem_id: int):
    """Trigger remote modem cellular reconnect to cycle carrier IP in ~5-10s."""
    url = PXM2_ROTATE_API.format(id=modem_id)
    async with aiohttp.ClientSession() as session:
        async with session.get(url, timeout=10) as resp:
            if resp.status == 200:
                print(f"[Modem {modem_id}] Fresh cellular CGNAT IP acquired.")

async def run_worker(worker_id: int, target_url: str):
    """Worker handling single scraping task within the 50-concurrency semaphore boundary."""
    modem_id = worker_id % len(PXM2_MOBILE_PROXIES)
    proxy_endpoint = PXM2_MOBILE_PROXIES[modem_id]

    async with semaphore:
        # Launch lightweight Camoufox instance tailored for 50+ concurrency:
        # 1. geoip=True aligns timezone/locale/WebRTC to carrier egress IP automatically
        # 2. block_images=True saves cellular proxy bandwidth and cuts memory by 65%
        # 3. humanize=True generates authentic bezier mouse trajectories across challenges
        async with AsyncCamoufox(
            headless=True,
            geoip=True,
            proxy={"server": proxy_endpoint},
            humanize=True,
            block_images=True,
        ) as browser:
            page = await browser.new_page()
            try:
                print(f"[Worker {worker_id}] Connecting via Modem {modem_id} to {target_url}...")
                response = await page.goto(target_url, wait_until="domcontentloaded", timeout=45000)

                # Check if Cloudflare Turnstile or DataDome challenge is present
                turnstile_frame = page.frame_locator("iframe[src*='challenges.cloudflare.com']")
                checkbox = turnstile_frame.locator("input[type='checkbox']")
                
                if await checkbox.count() > 0:
                    print(f"[Worker {worker_id}] Cloudflare Turnstile challenge detected. Executing humanized click...")
                    await checkbox.click()
                    await page.wait_for_timeout(3000)

                # Validate bypass and extract required payload
                title = await page.title()
                if "Just a moment" in title or "Attention Required" in title:
                    print(f"[Worker {worker_id}] WAF challenge flagged! Triggering IP rotation on Modem {modem_id}...")
                    await rotate_modem(modem_id)
                    raise RuntimeError("WAF challenge encountered; IP rotated.")

                print(f"[Worker {worker_id}] Succeeded! Page Title: {title}")
                data = await page.content()
                return data

            except Exception as e:
                print(f"[Worker {worker_id}] Failed with error: {e}")
                return None
            finally:
                # Critical: page.close() prevents socket and memory leaks across long runs
                await page.close()

async def main():
    target_tasks = [
        f"https://target-portal.com/catalog/item/{i}" 
        for i in range(200)
    ]
    
    print(f"Starting {len(target_tasks)} tasks across {MAX_CONCURRENT_SESSIONS} concurrent workers...")
    jobs = [run_worker(i, url) for i, url in enumerate(target_tasks)]
    results = await asyncio.gather(*jobs, return_exceptions=True)
    successful = [r for r in results if r and not isinstance(r, Exception)]
    print(f"Batch completed: {len(successful)}/{len(target_tasks)} tasks resolved successfully.")

if __name__ == "__main__":
    asyncio.run(main())
Production async worker pool managing 50 concurrent browser sessions with dedicated modems and auto-rotation

Humanized Mouse Movement & Behavioral Anti-Bot Defense

Modern Web Application Firewalls (WAFs) monitor sensor data: mouse velocity vectors, click event timestamps, and acceleration curves. Instantaneous coordinate teleportation (default Playwright page.click()) immediately flags an automated session.

Camoufox integrates the humanize option, synthesizing natural bezier-curve cursor movement with stochastic speed variations:

Python · Humanized Bezier Mouse Trajectories
from camoufox.sync_api import Camoufox

with Camoufox(
    humanize=True,        # Enables curved bezier mouse trajectories
    headless=False
) as browser:
    page = browser.new_page()
    page.goto("https://nowsecure.nl")
    
    # Cursor moves along a realistic physical path
    page.click("button#verify-button")
    page.wait_for_timeout(3000)
Generates authentic mouse drag trajectories and jitter to satisfy biometric challenge sensors

Bypassing Cloudflare Turnstile & DataDome via Persistent Contexts

Cloudflare Turnstile and DataDome evaluate browser integrity on entry. If your scraper maintains a persistent browser profile, challenge clearance tokens (such as cf_clearance) persist across sessions, eliminating the need to solve CAPTCHAs repeatedly.

Python · Persistent Context for Cloudflare Turnstile Bypass
from camoufox.sync_api import Camoufox

# Store session cookies and local storage on disk
PROFILE_DIR = "./camoufox_profile"

with Camoufox(
    persistent_context=True,
    user_data_dir=PROFILE_DIR,
    disable_coop=True,    # Required to click elements inside cross-origin iframes
    headless=False,
    window=(1366, 768)
) as browser:
    page = browser.new_page()
    page.goto("https://target-portal.com/login")
    
    # If a Turnstile challenge is present, wait and click checkbox
    page.wait_for_selector("iframe[src*='challenges.cloudflare.com']", timeout=10000)
    page.wait_for_timeout(2000)
    
    # Click within iframe boundary
    turnstile_box = page.frame_locator("iframe[src*='challenges.cloudflare.com']")
    turnstile_box.locator("input[type='checkbox']").click()
    page.wait_for_timeout(5000)
    
    # Next execution reuses the cf_clearance cookie from PROFILE_DIR!
Clearance cookies remain cached in user_data_dir for subsequent headless operations

Running Headless on Linux Servers with Virtual Displays

On Linux production servers without a desktop environment, pure headless mode (headless=True) leaves subtle GPU and canvas evaluation discrepancies. Camoufox supports headless='virtual', which spawns an isolated Xvfb virtual framebuffer server behind the scenes.

Linux Production Pure Headless vs Virtual Display Framebuffer (Xvfb)

Anti-bot scripts calculate rendering latency differences between software SwiftShader rasterizers and real window displays. Standard headless mode is easily detected because screen dimensions, color depth, and WebGL extensions report headless defaults.

By launching with headless='virtual', Camoufox attaches to an internal X11 virtual display buffer. The browser behaves exactly like a desktop window with real display dimensions and full hardware acceleration profiles, completely evading headless heuristics.

Python · Headless Linux Production with Virtual Display
from camoufox.sync_api import Camoufox

# Linux headless server requires xvfb package installed:
# sudo apt-get install -y xvfb libgtk-3-0 libasound2

with Camoufox(
    headless="virtual",   # Uses Xvfb virtual display buffer
    block_images=True,    # Optimizes proxy bandwidth usage
    block_webrtc=False    # Spoofs WebRTC IP to match proxy without leaking local IP
) as browser:
    page = browser.new_page()
    page.goto("https://bot.incolumitas.com")
    print("Passed Incolumitas bot detection test on headless server!")
Optimal performance and stealth for production scrapers deployed on Ubuntu/Debian VPS

Anti-Bot Benchmark: Camoufox vs Standard Frameworks

We tested common automation configurations against the industry's four toughest anti-bot benchmarks. Notice how pairing Camoufox with PXM2 4G/5G mobile proxies delivers unmatched detection resistance:

Framework + IP Tier CreepJS Score Cloudflare Turnstile DataDome Protection Subnet Ban Immunity
Stock Playwright (Chromium) 14% (High Risk) Blocked Instant CAPTCHA None (/24 Ban)
Puppeteer-Extra-Stealth 52% (Flagged) Intermittent Blocked (JS hooks) None
Camoufox + Datacenter Proxy 86% (Stealth) 50% (IP Flagged) 40% Pass Rate Subnet Ban Risk
Camoufox + PXM2 4G/5G Mobile 98% (Clean Device) 99.4% First-Pass 98.8% Invisible 100% (CGNAT Immune)
Performance Tip: Enable block_images=True and block_webgl=True in Camoufox when scraping text-heavy catalogues. This cuts cellular data consumption by over 65% and accelerates page completion speeds.

Frequently Asked Questions

What is Camoufox and why does it beat stock Playwright?

Camoufox is an open-source stealth browser built on top of Mozilla Firefox. Unlike Chrome-based stealth plugins that monkey-patch JavaScript APIs (which anti-bot scripts detect via prototype inspection), Camoufox injects authentic device fingerprints directly into Firefox C++ source code before JavaScript executes.

Why should I pair Camoufox with 4G/5G mobile proxies instead of datacenter IPs?

Even if browser fingerprints look authentic, datacenter IPs belong to hosting ASNs that trigger immediate CAPTCHAs. Mobile proxies route through real cellular carriers using Carrier Grade NAT (CGNAT), where thousands of real mobile users share each IP, making it impossible for anti-bot firewalls to block them.

How do I handle Cloudflare Turnstile and DataDome challenges with Camoufox?

Use persistent_context=True with a user_data_dir to cache verification cookies (such as cf_clearance). Enable disable_coop=True to allow automated clicking inside cross-origin iframes, and pair with humanize=True to simulate organic mouse movements.

Can I run Camoufox on a headless Linux VPS or in Docker?

Yes. On Linux servers without a desktop display, configure headless="virtual". Camoufox will automatically utilize an Xvfb virtual framebuffer display, providing full GPU rasterization and authentic display properties that prevent headless browser detection.

Does Camoufox support remote IP rotation APIs?

Yes. You can trigger PXM2 rotation API endpoints via standard Python HTTP requests (requests.get) between browser iterations. When cycling IPs, Camoufox with geoip=True will automatically re-synchronize matching geolocation attributes.

How do I scale Camoufox to 50+ concurrent sessions without running out of RAM?

Do not spawn 50 individual browser processes. Instead, implement an asynchronous worker pool using asyncio.Semaphore(50) with AsyncCamoufox, and bind each session to a dedicated PXM2 mobile modem. Enable block_images=True to reduce memory from 30+ GB down to 4-5 GB while keeping independent C++ fingerprint entropy and automated GeoIP alignment for every session.

Related Developer Resources

Power Your Camoufox Scrapers with PXM2 4G/5G Proxies

Bypass the strictest anti-bot firewalls with genuine cellular carrier modems across 50+ countries. Dedicated throughput, instant remote IP rotation API, and unlimited bandwidth.

Get Dedicated Mobile Proxies