Contact
Stealth & Privacy

How do headless browsers get detected?

Headless browsers (Puppeteer, Playwright, Selenium) are detected through dozens of JavaScript properties that differ from real browser behavior. Detection vectors: 1) navigator.webdriver — set to true in automated browsers. Defense: delete the property via CDP. 2) Missing plugins — headless Chrome has zero plugins. Real Chrome has 2-5 (PDF viewer, etc.). Defense: inject fake plugin data. 3) Missing languages — headless often has empty navigator.languages. Defense: set realistic language array. 4) Chrome-specific objects — real Chrome has window.chrome with specific properties. Headless versions are incomplete. Defense: inject the full object tree. 5) Canvas/WebGL rendering — headless rendering produces different outputs than headed mode. Defense: use headed mode with virtual display (Xvfb on Linux). 6) Timing anomalies — automated actions happen too fast and too consistently. Real users have variable delays. Defense: add realistic random delays. 7) Behavioral signals — no mouse movement, instant scrolling, and perfect element targeting. Defense: simulate human-like mouse paths and scroll behavior. Detection frameworks like DataDome, PerimeterX, and Cloudflare Bot Management combine 50+ signals. Defeating them requires addressing all vectors simultaneously, which is why anti-detect browsers exist — they solve these issues systematically rather than one-by-one.

Still have questions?

Talk to Empirium