A headlesschrome is a type of browser that lacks a graphical user interface (GUI). It can run in the background, allowing programmers to control and manipulate the browser through a command-line interface or scripts.
Now, it's time to learn about the methods of detecting and anti-detecting headless browser crawler bots through Nstbrowser!
Headlesschrome is a headless mode of the Google Chrome browser. It allows developers to control and manipulate the Chrome browser via command line or scripts without displaying the browser's user interface. Headlesschrome combines the powerful features of the Chrome browser with the efficiency of headless mode, making it an indispensable tool in modern web development and testing.
Ready to learn more and get special benefits?
Join our Discord referral program to share $1,500 in cash now!
We already know what a headlesschrome is, what it can do, and how it works. Since headless browsers have strong automation features, headless browsers are also often used for anti-crawling purposes. Therefore, detecting their presence is crucial.
Here are common methods of detecting headless browsers with JavaScript code examples and some anti-detection methods:
The user agent is the identifier sent by the browser to the server. By checking whether the user agent contains the word "Headless", we can initially determine whether the request is from a headless browser. This method is often unreliable because the user agent can be forged or modified.
const isHeadlessUserAgent = navigator.userAgent.toLowerCase().includes('headless');
// custom userAgent without 'headless'
Object.defineProperty(navigator, 'userAgent', {
value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
});
Headlesschrome usually does not execute JavaScript or their JavaScript execution capabilities are weak. Therefore, we can determine whether the browser supports JavaScript by executing some simple JavaScript code. This can be achieved by checking the availability of certain JavaScript APIs or features.
const isJavaScriptEnabled = typeof window !== 'undefined';
Certain browser features may be disabled or behave abnormally in a headlesschrome. We can use these features for detection. For example, the Canvas API can be used to detect headless browsers.
const isCanvasSupported = () => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
return !!context;
}
By checking the existence of the navigator.webdriver
property, we can determine whether it is a headlesschrome. Headless browsers usually set this property, whereas normal browsers do not. The relevant source code can be found in Chromium. By checking the presence of this property, we can determine if it is a headlesschrome.
const isWebDriverSupported = () => {
return navigator.webdriver;
}
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
Detecting whether window.chrome
exists can help determine if the browser is in headless mode. In headless mode, this property is usually absent.
const isWindowChromeSupported = () => {
return window.chrome !== undefined;
}
WebRTC is a web standard for real-time communication in browsers. Details can be found on the Webrtc website. Headlesschrome usually disables WebRTC, so we can determine if the browser is headless by checking WebRTC availability.
const isWebRTCSupported = () => {
return !!window.RTCPeerConnection;
}
In headless mode, playing audio or video is usually disabled. By attempting to play audio or video, we can determine if the browser supports audio or video playback and thus if it is a headlesschrome.
const isAudioVideoSupported = () => {
const audio = document.createElement('audio');
const video = document.createElement('video');
return !!(audio.canPlayType && video.canPlayType);
}
Currently, headless browsers cannot operate browser permissions, so they do not support Notification.permission
. Because they do not handle user interface events, they only load and render pages. Therefore, in headlesschrome mode, Notification.permission
and navigator.permissions.query
are inconsistent.
const isHeadlessPermissionMatched = () => {
return navigator.permissions.query({name: 'notifications'})
.then(permissionStatus => {
return Notification.permission === 'denied' && permissionStatus.state === 'prompt';
})
.catch(() => {
return false;
});
};
navigator.plugins
can be used to check the list of plugins present in the browser. By default, browsers install some plugins like Chrome PDF viewer or Google Native Client, but in headless mode, there are usually no plugins. Therefore, we can determine if it is a headlesschrome by checking if the plugin list is empty.
const pluginInstalled = () => {
return navigator.plugins.length > 0
}
const originalPlugins = navigator.plugins;
Object.defineProperty(navigator, 'plugins', {
get: () => originalPlugins
});
In Chrome, navigator.language
and navigator.languages
can be used to get the user's language. The first one is the language of the browser UI, and the second one is the list of user preferred languages. In headless mode, navigator.languages
returns an empty string.
const isHeadlessLanguage = () => {
return !navigator.languages || navigator.languages.length === 0
}
Object.defineProperty(navigator, 'languages', {
value: ['en-US', 'en']
});
Detection Methods:
Anti-detection methods
It should be noted that because headless browsers can simulate the behavior of almost all normal browsers, they will use various anti-detection methods to make headless browsers look more like real users, thereby increasing the difficulty of anti-crawling. Therefore, no matter what method is used to anti-detect headless browsers, it is not absolutely reliable, at least so far.
We can also use fingerprint browsers to bypass headlesschrome detection. Let's take Nstbrowser fingerprint browser as an example. Nstbrowser's API solution is currently one of the best choices to avoid robot detection, and you can get the API key for free.
Next, visit the CreepJS and Areyouheadless headlesschrome detection sites through the Nstbrowser fingerprint browser and my local GoogleChrome browser to compare the headless browser detection effect.
We will use Puppeteer to call the API to start the headless fingerprint browser. Specifically, the LaunchExistBrowser
interface will be used. Of course, you can also choose other APIs you need according to the document.
Before you start, you need to:
Step 1. Download and install Nstbrowser in advance
Step 2. Generate API Key
Step 3. Create a Profile and manually download the kernel. You can also click on the client to start your Profile and then trigger the automatic download of the kernel
After everything is ready, you can start coding. The following code shows how to start the headless mode browser and visit the headless browser detection site and take a screenshot:
import puppeteer from 'puppeteer-core';
// wiat for millseconds
function sleep(millseconds) {
return new Promise(resolve => setTimeout(resolve, millseconds));
}
// visit headless detection site and take screenshots
async function execPuppeteer(browserWSEndpoint) {
try {
const browser = await puppeteer.connect({
browserWSEndpoint: browserWSEndpoint,
defaultViewport: null,
});
const page = await browser.newPage();
// detect headless on creepjs site
await page.goto('https://abrahamjuliot.github.io/creepjs');
await sleep(5 * 1000);
await page.screenshot({ fullPage: true, path: 'detect_headless_creepjs.png' });
// detect headless on areyouheadless site
await page.goto('https://arh.antoinevastel.com/bots/areyouheadless');
await sleep(2 * 1000);
await page.screenshot({ path: 'detect_headless_areyouheadless.png' });
await page.close();
await browser.disconnect();
} catch (err) {
console.error(err);
}
}
// LaunchExistBrowser: Connect to or start an existing browser
// You need to create the corresponding profile in advance
// Support custom config
async function launchAndConnectToBrowser(profileId) {
const host = 'localhost:8848';
const apiKey = 'you api key;
const config = {
headless: true, // support: true, 'new'
autoClose: true,
};
const query = new URLSearchParams({
'x-api-key': apiKey, // required
config: encodeURIComponent(JSON.stringify((config))),
});
const browserWSEndpoint = `ws://${host}/devtool/launch/${profileId}?${query.toString()}`;
console.log('browserWSEndpoint: ', browserWSEndpoint);
await execPuppeteer(browserWSEndpoint);
}
launchAndConnectToBrowser('your profile id').then();
CreepJS test results
Areyouheadless test results
By comparing the running result screenshots with the detection results of my local Google Chrome, I found that the headless detection of these two sites did not recognize that we were using a headlesschrome, which is also the effect we want.
Through the discussion and sample code of this article, we hope to provide developers with effective reference and guidance to improve the security and data protection capabilities of the website.
Detection and anti-detection of a headlesschrome is an evolving technical confrontation process. You can use effective anti-detection tools to deal with the risk of being detected and blocked. Nstbrowser can help you ensure absolute concealment and use advanced technology to unlock network blockades.
In addition, developers need to continue to pay attention to the latest technical developments and update detection strategies to meet new challenges. No matter what method is used to anti-detect headless browsers, it needs to be continuously optimized and improved to ensure its effectiveness and reliability.