Detect Chrome running in headless mode from JavaScript
The user agent string includes HeadlessChrome
instead of Chrome
. This is probably the signal that you're intended to look for, so you could use:
/\bHeadlessChrome\//.test(navigator.userAgent)
Other interesting signals include:
- It looks like
window.chrome
is undefined when headless. [innerWidth, innerHeight]
is[800, 600]
(hardcoded inheadless_browser.cc
), while[outerWidth, outerHeight]
is[0, 0]
(which shouldn't usually happen).
You can check navigator.webdriver
property which is:
The
webdriver
read-only property of thenavigator
interface indicates whether the user agent is controlled by automation....
The
navigator.webdriver
property is true when in:Chrome The
--enable-automation
or the--headless
flag is used.
Firefox Themarionette.enabled
preference or--marionette
flag is passed.
The W3C WebDriver Recommendation describes it as follows:
navigator.webdriver
Defines a standard way for co-operating user agents to inform the document that it is controlled by WebDriver, for example so that alternate code paths can be triggered during automation.
Just read this article by Antoine Vastel which provides a few ways:
- testing user agent with
/HeadlessChrome/.test(window.navigator.userAgent)
, but this is easily spoofed - testing plugins with
navigator.plugins.length == 0
- testing languages with
navigator.languages == ""
- testing WebGL vendor and renderer info (see article for interesting details)
- testing supported features as detected by Modernizr: it seems "hairlines" are not supported (hidpi/retina hairlines, which are CSS borders with less than 1px in width, for being physically 1px on hidpi screens). Test is
!Modernizr["hairline"]
. - testing size of placeholder for missing image. Insert an image with invalid URL, and test for
image.width == 0 && image.height == 0
inimage.onerror
(they found this one to be the most robust).
Can't speak for Google's motivations (is Headless Chrome only about facilitating tests of web applications? Hmmm...), but this could be seen as a list of bugs that might get fixed someday, so one has to wonder for how long those tests will work :)