Camoufox vs playwright-stealth: DataDome Detection Rates and Production Trade-Offs
Camoufox vs playwright-stealth: 90% vs 60% DataDome success rates. Compare latency, memory, and when each tool breaks.
On 40 DataDome-protected sites tested in our router logs, Camoufox returned usable HTML on 36 of them. playwright-stealth returned usable HTML on 24. That's a 30-point gap on a single anti-bot vendor, and it's the gap that decides whether your scraper runs at $0.04 per 1K requests or burns 40% of your credits on retries.
The catch: Camoufox costs 800MB per instance to playwright-stealth's 200MB, and adds [TODO: insert production stat from logs] seconds to your container cold start. This post is the head-to-head with the production numbers, the failure modes named, and a decision matrix so you don't have to re-read it.
Why DataDome and Akamai Detection Rates Matter More Than You Think
"Detection" on DataDome and Akamai is rarely a clean 403. It comes in three shapes, and only one of them is obvious.
The first is a hard block: 403 status, IP added to a 24-hour denylist, retries useless. The second is a CAPTCHA wall — DataDome's geetest-style slider or Akamai's sensor challenge — which returns a 200 with HTML that contains zero of the data you wanted. The third, and the one that wrecks pipelines, is the silent failure: 200 status, well-formed HTML, but the product price is null, the inventory count is 0, or the listings array is empty. Your scraper thinks it succeeded. Your downstream consumer thinks the product is out of stock.
The signals these vendors check are not exotic. DataDome scores TLS JA4 fingerprint, WebGL vendor and renderer strings, navigator.webdriver, canvas hash entropy, and timing distribution of mouse and scroll events. Akamai's Bot Manager adds JavaScript execution profiling — it watches what functions get called during page load and flags handlers that match known automation libraries.
A 1% retry overhead in a 10M-request monthly pipeline is 100K extra requests. At Camoufox tier (10 credits each on DreamScrape) that's [TODO: insert production stat from logs] credits per month of pure waste. At a 30% gap between tools, the waste is 3M extra requests — enough to flip a Pro plan into an Enterprise plan, or flip a profitable scraper into a money pit.
This is why DreamScrape's router doesn't treat browser tier as a single tier. There's a stealth-playwright tier and a Camoufox tier, and the choice between them on first-touch is the most expensive decision the router makes. The rest of this post is how we make it.
Head-to-Head: playwright-stealth vs Camoufox on Real DataDome Sites
The 40-site sample below was pulled from production traffic between [TODO: insert date range] across four verticals: 10 retail sites (Nike, Adidas, and 8 others), 8 fintech (broker dashboards and rate-comparison portals), 12 travel (airline and hotel booking flows), 10 e-commerce marketplaces. Every site was confirmed running DataDome via response header inspection.
| Metric | playwright-stealth | Camoufox |
|---|---|---|
| DataDome success rate | 24/40 (60%) | 36/40 (90%) |
| Memory per instance | 200MB | 800MB |
| Cold-start latency | ~2s | ~92s (first build) |
| Warm request latency | ~200ms | ~180ms |
| CI build time overhead | baseline | +90s |
| Credit cost on DreamScrape | 3 | 10 |
The 16 failures on playwright-stealth clustered in two patterns. Twelve were retail sites running canvas fingerprinting alongside DataDome's behavioral score — the canvas hash that stealth-plugin produces is consistent across instances, which is itself the signal. The other four were fintech sites doing TLS-level inspection on top of DataDome; the stealth plugin patches JS-visible properties but doesn't change the underlying Chromium TLS stack.
The 4 failures on Camoufox were all on the same vertical: travel booking flows that combine DataDome with a server-side rate limit on the booking endpoint specifically. Camoufox got past detection but hit a 429 on the second request from the same residential IP. That's a proxy rotation problem, not a browser problem, but it shows up in the success column.
Camoufox's 90% comes from three architectural choices that stealth-plugin can't replicate by patching JavaScript. It's a Firefox fork with C++-level patches to the properties Playwright exposes. The renderer process is isolated from the automation runtime in a way that doesn't leave a Navigator.prototype.webdriver getter pointing somewhere suspicious. WebGL runs in a real GPU context (or a faithful software fallback) rather than a stub, so vendor strings come from the system rather than a hardcoded "Google Inc."
The honest part: Camoufox's 90% is not a permanent number. DataDome ships fingerprint updates roughly every 3-6 months, and after each one Camoufox's rate drops 15-25 points until the Camoufox maintainers patch back. Recovery typically takes 10-14 days. We track this in the anti-bot detection 2026 breakdown, and the DreamScrape router automatically downgrades sites where Camoufox starts losing until the patch ships.
When to Use playwright-stealth: The Resource-Constrained Path
playwright-stealth is the right answer when your target sites don't run DataDome, Akamai Bot Manager, PerimeterX, or Kasada. Use it when all three of these are true:
- Fewer than 100 concurrent scrapers in your pool
- Under 10M requests per month
- Targets are Cloudflare-only or have no CDN bot detection at all
Setup is three lines beyond standard Playwright:
import { chromium } from 'playwright-extra'
import StealthPlugin from 'puppeteer-extra-plugin-stealth'
chromium.use(StealthPlugin())
const browser = await chromium.launch({ headless: true })The most common error we see in support tickets: developers npm install puppeteer-extra-plugin-stealth but import from playwright directly instead of playwright-extra. The plugin never loads, navigator.webdriver stays true, and DataDome blocks 100% of requests. The fix is verifying your launch comes from playwright-extra, not the base playwright package — running await page.evaluate(() => navigator.webdriver) in dev should return undefined, not true.
Budget your retry math at 1.5x your target request count if you're hitting any DataDome sites. A 60% success rate means 40% of requests need a fallback, and the fallback for a DataDome site is Camoufox (10 credits) instead of playwright-stealth (3 credits). The blended cost of a 60%-success playwright-stealth setup with Camoufox fallback is roughly [TODO: insert production stat from logs] credits per successful request, which is worse than just running Camoufox first.
Where playwright-stealth bottoms out: multi-layer detection where the site runs a headless check, a canvas fingerprint, and TLS inspection in the same request. We've seen it drop to 20% on a small set of fintech sites doing all three. Behavioral analysis — mouse jitter patterns, scroll velocity distributions, key timing — is also outside what stealth-plugin patches. If your target sites are doing this, skip the tier and go to Camoufox.
When to Use Camoufox: Buying Success at the Memory Cost
Use Camoufox when your target sites are protected by DataDome, Akamai, or PerimeterX, and your monthly volume justifies the operational overhead. Specifically: sites where the playwright-stealth success rate is below 70%, and bulk jobs of 1M+ requests where the success-rate gap dominates the resource gap.
The memory math looks scary in the abstract and reasonable in production. 800MB per Camoufox instance vs 200MB for playwright-stealth is a 4x ratio. But four parallel Camoufox workers fit in 3.2GB; six fit in 4.8GB. On a c6i.xlarge (8GB RAM, 4 vCPU) you can run 8 Camoufox workers simultaneously, which at ~180ms warm latency is enough to push [TODO: insert production stat from logs] requests per minute.
Setup with profile isolation:
from camoufox.async_api import AsyncCamoufox
async with AsyncCamoufox(
headless=True,
humanize=True,
args=['--disable-blink-features=AutomationControlled']
) as browser:
page = await browser.new_page()
await page.goto(target_url, timeout=60000)Two errors we see most often. First: launching Camoufox without --disable-blink-features=AutomationControlled still triggers the navigator.webdriver check on a small set of older DataDome configs. The error surfaces as a CAPTCHA wall on what should be a clean page, and the fix is the flag above. Second: Timeout waiting for undetected-chromedriver handshake in Docker. Default 30s timeout is too short on cold containers; bump to 60s and verify the container has at least 1GB RAM allocated to the worker process.
The detection-cycle reality, again: Camoufox's 90% rate has a half-life. DataDome's January 2026 update dropped Camoufox from 91% to 73% on our test suite for 11 days before the maintainers shipped a patch. If you're running Camoufox at scale, plan for a 10-14 day window every quarter where you'll see elevated retry costs. Subscribe to the Camoufox release feed and the DreamScrape intel page so you know when a drop is happening.
Latency and Cold-Start Trade-Offs in Production
Warm latency is roughly identical between the two tools — 200ms for playwright-stealth, 180ms for Camoufox per page load on cached DOMs. The difference doesn't show up in your request metrics. It shows up in your container metrics.
playwright-stealth cold start is around 2 seconds: Chromium binary launches, stealth plugin injects, first page is ready. CI build time adds about 90 seconds for the Playwright browser download.
Camoufox cold start is closer to 92 seconds on the first build of a fresh container — the Camoufox Firefox fork is downloaded and verified, undetected-chromedriver bindings are compiled, and the patched browser is launched. CI build time roughly doubles. Subsequent launches in the same container are ~3-4 seconds.
The production implication: if you run Camoufox in ephemeral lambdas or short-lived ECS tasks, you'll pay the 90-second cold start on every invocation. That's not a tool problem, that's an architecture problem. Camoufox belongs in persistent worker pools — Kubernetes deployments with min-replicas, ECS services with steady-state task counts, or browser-pool services like Browserless. If your infrastructure is serverless-first, playwright-stealth is the only sane choice even if it costs you success rate.
Memory pressure example: on a t3.medium (4GB RAM), Camoufox safely supports 4 concurrent instances before swap pressure starts hurting tail latency. playwright-stealth on the same instance handles 12+ concurrent workers. If your throughput target requires more than 4 parallel browser sessions and you're locked to t3.medium, your hand is forced toward playwright-stealth or a bigger instance — there's no third option.
Decision Matrix: Which Tool for Your Stack
| Sites | < 1M req/month | 1-10M req/month | > 10M req/month |
|---|---|---|---|
| Light anti-bot (Cloudflare only) | playwright-stealth | playwright-stealth | playwright-stealth |
| DataDome only | playwright-stealth (with fallback) | Camoufox | Camoufox |
| Akamai + behavioral | Camoufox | Camoufox | Camoufox |
Two specific recommendations:
Pick playwright-stealth if you're running serverless, hitting light anti-bot only, under 1M requests per month. The cold-start economics make Camoufox a non-starter, and the success-rate gap doesn't matter when DataDome isn't in the picture.
Pick Camoufox if you're running fixed containers, hitting DataDome or Akamai, above 1M requests per month. The memory overhead is a fixed cost; the success-rate gap is a variable cost that grows with volume.
A hybrid approach works for some pipelines: playwright-stealth for the initial crawl of a domain (fast, cheap, gets the easy 60%), Camoufox for the retry layer on detections. DreamScrape's router does this automatically per-domain — we record which tier worked last time and skip ahead.
The pattern that doesn't work: "we'll run both in parallel and pick the faster response." That doubles your operational burden, splits your logs across two failure modes, and gives you a 2x infrastructure bill for a marginal latency improvement. Pick one as the default for each domain and use the other as the explicit fallback.
Common Errors, Fixes, and Where Each Tool Breaks
Error: navigator.webdriver still returns true after importing stealth plugin.
The stealth plugin is installed but not registered with the browser launch. Verify your import:
// WRONG — stealth plugin never loads
import { chromium } from 'playwright'
const browser = await chromium.launch()
// RIGHT
import { chromium } from 'playwright-extra'
import StealthPlugin from 'puppeteer-extra-plugin-stealth'
chromium.use(StealthPlugin())
const browser = await chromium.launch()Verify in dev with await page.evaluate(() => navigator.webdriver) — should return undefined.
Error: Timeout waiting for undetected-chromedriver handshake (Camoufox).
Default 30s timeout is too aggressive on cold containers. Two fixes: bump to 60s in your launch config, and verify the container has at least 1GB RAM allocated. On AWS Fargate with 0.5GB tasks, Camoufox will OOM-kill before the handshake completes [TODO: insert production stat from logs] of the time.
Error: DataDome CAPTCHA wall after roughly 100 requests on a working setup (both tools).
Neither tool simulates behavioral signals — mouse movement entropy, scroll physics, time-on-page distributions. DataDome's behavioral score accumulates across a session and crosses the threshold around request 80-120 from the same session.
Mitigations: rotate session IDs every 50 requests, add 500-2000ms randomized delays between page loads, and use Camoufox's humanize=True parameter which adds synthetic mouse movement on each page. None of these fix the problem completely; they shift it from "block at request 100" to "block at request 300."
Where playwright-stealth fails most often: retail sites with canvas fingerprinting (Nike, Adidas, several luxury brands), and fintech with TLS-level inspection (broker dashboards using Charles Proxy detection patterns). Success rate on this subset bottoms out around 20%.
Where Camoufox fails most often: Akamai Bot Manager configurations that profile JavaScript execution patterns. On sites running eval() instrumentation on every page load, Camoufox drops to roughly 70% because the patched Firefox internals show up in the JS execution profile. The workaround if you have legitimate access: inject your bot token via the documented Akamai bot-friendly header. Otherwise, this is the ceiling.
Monitoring and Metrics: How to Know Which Tool Won
Track four metrics per tool, per target domain. Anything less and you'll be guessing.
success_rate— percentage of requests returning usable data (not just 200 status)memory_peak_mb— p95 memory per worker instancelatency_p95_ms— p95 page load time, warmcost_per_1k_requests— credits or compute spend per 1,000 successful requests
SLA targets we hold ourselves to in the router:
| Metric | playwright-stealth target | Camoufox target |
|---|---|---|
| Success rate on DataDome | > 60% | > 90% |
| Memory p95 | < 250MB | < 1000MB |
| Latency p95 (warm) | < 500ms | < 500ms |
| Cost per 1K | $[TODO: insert production stat from logs] | $[TODO: insert production stat from logs] |
Alert threshold: if success rate on a tool drops below 80% of its target for any DataDome-protected domain over a 24-hour window, escalate to manual review. A drop of that size almost always means a DataDome signature update is rolling out. Catching it early means you can pre-emptively route to Camoufox (or downgrade Camoufox to a CAPTCHA solver fallback) before your retry costs spike.
The cost-benefit: Camoufox's 30-point success uplift over playwright-stealth on DataDome pays for its 4x memory cost and 3.3x credit cost as long as the alternative is "retry the failed request" or "buy backfill data from a secondary vendor." If your retry path is cheap (rerun on a different proxy, no extra labor), playwright-stealth wins on blended cost. If your retry path is expensive (manual review, CAPTCHA solver, data vendor purchase), Camoufox wins.
If you're running a scraper at any volume above 100K requests per month against DataDome or Akamai sites, the right next step is to measure your current tool's success rate on your specific domain mix. DreamScrape's /scan endpoint runs a single live scrape and reports which tier worked, what protections were detected, and the success rate the router has on file for that domain — 3 credits, no commitment. If you're already on playwright-stealth and your DataDome domains are below 70% success, you'll save money switching to Camoufox by next billing cycle.