liarjs.dev
Single test · Headless

Headless browser detection test

Modern headless Chrome is close to the windowed browser, so the tells that remain are few and specific. This page runs each of them against the browser you are using now.

Running 7 checks…
  1. HeadlessChrome in the User-AgentChecking…

    Headless Chrome announces itself in its User-Agent unless the caller overrides the string. The cheapest tell, and the first one anyone patches.

    id: headless-ua
  2. Software rendererChecking…

    Without a GPU, headless Chrome renders WebGL through a software rasteriser such as SwiftShader. A desktop browser a person uses names a real GPU.

    id: headless-gpu
  3. No media devicesChecking…

    enumerateDevices() returns nothing at all: no microphone, camera or speaker, which is typical of servers and containers.

    id: headless-devices
  4. navigator.webdriverChecking…

    Headless is usually driven by something, and WebDriver and stock automation libraries set this flag.

    id: webdriver
  5. DevTools protocol attachedChecking…

    The DevTools Runtime domain that Playwright and Puppeteer switch on for every page, measurable from the page itself.

    id: cdp-runtime
  6. Empty navigator.languagesChecking…

    Some headless and bare automation setups report no languages at all.

    id: langs-empty
  7. No browser UI heightChecking…

    outerHeight equal to innerHeight. Old headless did this; new headless fakes a toolbar, and fullscreen does it too, so this is a weak hint, not proof.

    id: headless-viewport

Why headless is hard to spot now

The old headless mode was a separate, stripped-down browser, and it showed: no plugins, no window chrome, odd defaults. Since Chrome's new headless mode it is the same browser without a window, and most of those differences are gone. What is left comes from the machine it runs on (no GPU, no audio devices), from the strings nobody overrode, and from whatever is driving it.

So a headless Chrome on a real desktop, with its User-Agent rewritten and driven by a tool that never enables the DevTools Runtime domain, can pass every row above. That is the honest limit of passive checks. The main scan adds a human challenge for exactly this case, and the bot detection test lists the full automation axis.

Further reading: CDP, Runtime.enable and the isolated world, and eleven stealth setups scored, which includes headless runs.

Other tests