2026 年 Playwright 隐身模式:真正重要的 7 个补丁
Source: Dev.to
原始的 playwright‑stealth npm 包已经一年多没有更新。
如果你直接使用它,许多最关键的检测仍未被修补。
下面是 2026 年仍然重要的 7 个浏览器指纹修补,并附有可通过 page.addInitScript() 注入的可用代码。
1. navigator.webdriver → undefined
await page.addInitScript(() => {
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined, // note: undefined, not false
configurable: true
});
});2. navigator.plugins 与 navigator.mimeTypes
await page.addInitScript(() => {
const plugins = [
{
name: 'PDF Viewer',
description: 'Portable Document Format',
filename: 'internal-pdf-viewer'
},
{
name: 'Chrome PDF Viewer',
description: '',
filename: 'internal-pdf-viewer'
},
{
name: 'Chromium PDF Viewer',
description: '',
filename: 'internal-pdf-viewer'
},
{
name: 'Microsoft Edge PDF Viewer',
description: '',
filename: 'internal-pdf-viewer'
},
{
name: 'WebKit built-in PDF',
description: '',
filename: 'internal-pdf-viewer'
}
];
Object.defineProperty(navigator, 'plugins', {
get: () =>
Object.assign(plugins, {
item: i => plugins[i],
namedItem: n => plugins.find(p => p.name === n),
refresh: () => {}
}),
configurable: true
});
Object.defineProperty(navigator, 'mimeTypes', {
get: () => ({
length: 2,
item: i => null,
namedItem: n => null
}),
configurable: true
});
});3. window.chrome(包括 loadTimes 与 csi)
await page.addInitScript(() => {
if (!window.chrome) window.chrome = {};
window.chrome.app = {
isInstalled: false,
InstallState: {
DISABLED: 'disabled',
INSTALLED: 'installed',
NOT_INSTALLED: 'not_installed'
},
RunningState: {
CANNOT_RUN: 'cannot_run',
READY_TO_RUN: 'ready_to_run',
RUNNING: 'running'
}
};
window.chrome.runtime = {
OnInstalledReason: {
CHROME_UPDATE: 'chrome_update',
INSTALL: 'install',
SHARED_MODULE_UPDATE: 'shared_module_update',
UPDATE: 'update'
},
OnRestartRequiredReason: {
APP_UPDATE: 'app_update',
OS_UPDATE: 'os_update',
PERIODIC: 'periodic'
},
PlatformArch: {
ARM: 'arm',
ARM64: 'arm64',
MIPS: 'mips',
MIPS64: 'mips64',
X86_32: 'x86-32',
X86_64: 'x86-64'
},
PlatformOs: {
ANDROID: 'android',
CROS: 'cros',
LINUX: 'linux',
MAC: 'mac',
OPENBSD: 'openbsd',
WIN: 'win'
},
RequestUpdateCheckStatus: {
NO_UPDATE: 'no_update',
THROTTLED: 'throttled',
UPDATE_AVAILABLE: 'update_available'
},
id: undefined,
connect: () => {},
sendMessage: () => {}
};
// Required: loadTimes and csi (missing from most stealth libraries)
window.chrome.loadTimes = function () {
return {
requestTime: Date.now() / 1000,
startLoadTime: Date.now() / 1000,
commitLoadTime: Date.now() / 1000,
finishDocumentLoadTime: 0,
finishLoadTime: 0,
firstPaintTime: 0,
firstPaintAfterLoadTime: 0,
navigationType: 'Other',
wasFetchedViaSpdy: false,
wasNpnNegotiated: false,
npnNegotiatedProtocol: 'unknown',
wasAlternateProtocolAvailable: false,
connectionInfo: 'http/1.1'
};
};
window.chrome.csi = function () {
return {
startE: Date.now(),
onloadT: Date.now(),
pageT: 3000 + Math.random() * 1000,
tran: 15
};
};
});4. navigator.permissions(通知)
await page.addInitScript(() => {
const originalQuery = navigator.permissions.query.bind(navigator.permissions);
navigator.permissions.query = parameters =>
parameters.name === 'notifications'
? Promise.resolve({ state: Notification.permission })
: originalQuery(parameters);
});5. WebGL 指纹(供应商 & 渲染器)
await page.addInitScript(() => {
const getParameter = WebGLRenderingContext.prototype.getParameter;
WebGLRenderingContext.prototype.getParameter = function (parameter) {
// 37445 → UNMASKED_VENDOR_WEBGL
// 37446 → UNMASKED_RENDERER_WEBGL
if (parameter === 37445) return 'Intel Inc.'; // replace with your target GPU vendor
if (parameter === 37446) return 'Intel Iris OpenGL Engine'; // replace with your target GPU renderer
return getParameter.call(this, parameter);
};
});提示: 将 GPU 字符串替换为符合目标受众的值(例如,针对高级用户使用 NVIDIA,普通笔记本使用 Intel)。
6. navigator.language 与 navigator.languages
await page.addInitScript(() => {
Object.defineProperty(navigator, 'language', {
get: () => 'en-US' // adjust to your proxy location
});
Object.defineProperty(navigator, 'languages', {
get: () => ['en-US', 'en'] // adjust as needed
});
});7. 基于 iframe 的检测(在嵌套框架中修补 webdriver)
await page.addInitScript(() => {
const origCreateElement = document.createElement.bind(document);
document.createElement = function (...args) {
const element = origCreateElement(...args);
if (args[0].toLowerCase() === 'iframe') {
const origContentWindow = Object.getOwnPropertyDescriptor(
HTMLIFrameElement.prototype,
'contentWindow'
).get;
Object.defineProperty(element, 'contentWindow', {
get: function () {
const win = origContentWindow.call(this);
if (win) {
Object.defineProperty(win.navigator, 'webdriver', {
get: () => undefined,
configurable: true
});
}
return win;
},
configurable: true
});
}
return element;
};
});助手:一次性应用所有补丁
async function applyStealthPatches(page) {
// Patch 1 – webdriver
await page.addInitScript(() => {
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined,
configurable: true
});
});
// Patch 2 – plugins & mimeTypes
await page.addInitScript(/* code from section 2 */);
// Patch 3 – window.chrome (including loadTimes & csi)
await page.addInitScript(/* code from section 3 */);
// Patch 4 – permissions (notifications)
await page.addInitScript(/* code from section 4 */);
// Patch 5 – WebGL vendor/renderer
await page.addInitScript(/* code from section 5 */);
// Patch 6 – language & languages
await page.addInitScript(/* code from section 6 */);
// Patch 7 – iframe detection
await page.addInitScript(/* code from section 7 */);
}您可以直接内联这些代码片段,或将它们保存在单独的辅助文件中以提升可读性。
示例用法
import { chromium } from 'playwright';
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
userAgent:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
viewport: { width: 1920, height: 1080 }
});
const page = await context.newPage();
await applyStealthPatches(page);
// Now navigate to the target site
await page.goto('https://example.com');这些补丁覆盖了 2026 年观察到的最常见失败模式(WebGL、权限、window.chrome、HTTP/2 JA3 泄漏、iframe 检测等)。根据您模拟的代理或设备的配置,调整相应的数值(GPU 字符串、语言、用户代理等)。
TL;DR
即使进行完美的浏览器补丁,网络层的 TLS 指纹仍然会暴露 Node.js/Playwright(例如,对抗 Kasada)。
选项
- Playwright + residential proxies + CAPTCHA services – 约为 $3‑$8 每 1 K 请求
- Pre‑built cloud actors 为您处理整个堆栈
即用解决方案
Apify Scrapers Bundle – $29
包括预先配置了隐身设置的演员,针对最常见的抓取目标(LinkedIn、Amazon、Google Maps、Twitter),为您节省调试周期。n8n AI Automation Pack – $39
提供 5 个可投入生产的工作流。
Need help?
Which anti‑bot system are you trying to work around? Drop a comment with the domain — I’ll tell you whether patches are enough or if you need a different approach.
相关工具
facebook-public-scraperthreads-profile-scraper