无头浏览器(headless browser)是一种没有图形用户界面(GUI)的浏览器。它可以在后台运行,允许程序员通过命令行接口或脚本来控制和操作浏览器。
现在,是时候开始通过 Nstbrowser 了解检测和反检测无头浏览器爬虫机器人的方法了!
无头 Chrome(Headless Chrome)是 Google Chrome 浏览器的一种无头模式。它允许开发者通过命令行或脚本来控制和操作Chrome浏览器,而不需要显示浏览器的用户界面。无头Chrome结合了Chrome浏览器的强大功能和无头模式的高效性,是现代Web开发和测试中不可或缺的工具。
抓取网页时经常被封锁?
Nstbrowser 全面解锁网站,避免被检测
Try Free Nstbrowser Now!
我们已经知道什么是无头浏览器、无头浏览器能干嘛以及它是如何工作的。由于无头浏览器具备很强的自动化特性,无头浏览器也经常被用于反爬虫目的。因此检测它的存在变得至关重要.
以下是常见的以Javascript代码为实例的无头浏览器的检测手段及部分反检测方法:
用户代理是浏览器发送给服务器的标识,通过检查用户代理中是否包含 "Headless" 字样可以初步判断请求是否来自于无头浏览器。这种方法往往并不可靠,因为用户代理可以被伪造或修改。
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'
});
无头浏览器通常不会执行JavaScript或其JavaScript执行能力较弱,因此我们可以通过执行一些简单的JavaScript代码来判断浏览器是否支持JavaScript。这可以通过检查某些JavaScript API 或功能是否可用来实现。
const isJavaScriptEnabled = typeof window !== 'undefined';
某些浏览器特性在无头浏览器中可能会被禁用或表现异常,我们可以利用这些特性来进行检测。例如,Canvas API 可以用于检测无头浏览器。
const isCanvasSupported = () => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
return !!context;
}
通过检测 navigator.webdriver
属性的存在来判断是否是无头浏览器。无头浏览器通常会设置这个属性,而正常的浏览器不会,相关源码:Chromium 源码,可以通过检测这个属性的存在,来判断是否是Chrome headless。
const isWebDriverSupported = () => {
return navigator.webdriver;
}
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
检测 window.chrome
是否存在可以帮助判断浏览器是否为无头模式。在无头模式下,这个属性通常是不存在的。
const isWindowChromeSupported = () => {
return window.chrome !== undefined;
}
WebRTC 是浏览器中用于实时通信的Web标准,详情可以参考Webrtc官网,无头浏览器通常会禁用WebRTC,所以可以通过检测WebRTC的可用性来判断浏览器是否为无头浏览器。
const isWebRTCSupported = () => {
return !!window.RTCPeerConnection;
}
在无头模式下通常会禁用播放音频或视频,通过尝试播放音频或视频,我们可以检测浏览器是否支持音频或视频播放,从而判断是否为无头浏览器。
const isAudioVideoSupported = () => {
const audio = document.createElement('audio');
const video = document.createElement('video');
return !!(audio.canPlayType && video.canPlayType);
}
目前无头浏览器还无法对浏览器权限进行操作,所以不支持Notification.permission
,因为它们不处理用户界面的事件,只进行页面加载和渲染,所以在无头浏览器模式下Notification.permission
和navigator.permissions.query
是不一致的。
const isHeadlessPermissionMatched = () => {
return navigator.permissions.query({name: 'notifications'})
.then(permissionStatus => {
return Notification.permission === 'denied' && permissionStatus.state === 'prompt';
})
.catch(() => {
return false;
});
};
navigator.plugins
可以查看浏览器中存在的插件列表。浏览器默认情况下会安装一些插件如:Chrome PDF viewer或者Google Native Client等,但是在无头模式下一般不会有任何插件,所以可以通过插件列表是否为空来判断是否是无头浏览器。
const pluginInstalled = () => {
return navigator.plugins.length > 0
}
const originalPlugins = navigator.plugins;
Object.defineProperty(navigator, 'plugins', {
get: () => originalPlugins
});
在Chrome中,可以通过navigator.language
和 navigator.languages
来获取用户使用的语言,第一个是浏览器UI的语言,第二个是用户偏好语言的列表。在无头模式下,navigator.languages
会返回一个空的字符串。
const isHeadlessLanguage = () => {
return !navigator.languages || navigator.languages.length === 0
}
Object.defineProperty(navigator, 'languages', {
value: ['en-US', 'en']
});
检测方法:
反检测方法
需要注意的是,因为无头浏览器可以模拟几乎所有正常浏览器的行为,会利用各种反检测手段来使得无头浏览器看起来更像真实用户的行为,从而提高反爬虫的难度,所以无论用什么方法来反检测无头浏览器都不是绝对可靠的,至少到目前为止是如此。
我们也可以利用指纹浏览器来绕过无头浏览器检测,我们以 Nstbrowser 指纹浏览器为例。Nstbrowser的 API 解决方案是目前避免机器人检测的最佳选择之一,您可以免费获取 API 密钥。
接下来,通过Nstbrowser指纹浏览器和我本地 GoogleChrome 浏览器,分别访问 CreepJS 和 Areyouheadless 无头浏览器检测站点来对比无头浏览器检测效果。
我们将使用 Puppeteer 调用API的方式来启动无头指纹浏览器,具体会用到 LaunchExistBrowser
接口,当然你也可以根据文档选择自己需要的其他的API。
开始之前你需要:
一切准备就绪之后就可以编码了。下面代码展示了启动无头模式浏览器并访问无头浏览器检测站点并截图:
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测试结果
Areyouheadless测试结果
通过运行结果截图对比我本地 Google Chrome 的检测结果发现这两个站点的无头检测均未识别到我们使用的是无头浏览器,这也是我们想要的效果。
通过本文的探讨和示例代码,希望能为开发者提供有效的参考和指导,提升网站的安全性和数据保护能力。
无头浏览器的检测和反检测是一个不断演进的技术对抗过程。可以借助有效的反检测工具应对被检测和被封锁的风险,Nstbrowser 可以帮助你保证绝对的隐蔽性,并且使用先进的技术解锁网络封锁。
此外,开发者需要持续关注最新的技术动态,更新检测策略,以应对新的挑战。无论用什么方法来反检测无头浏览器,都需要不断优化和改进,以确保其有效性和可靠性。