You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Selenium Chrome反bot检测 CHR_MEMORY等项失败解决

Selenium Chrome驱动反Bot检测失败问题解决方案

问题背景

基于Python开发的Selenium Chrome驱动在两个公开Bot检测站点存在测试项不通过的情况:

  • 访问bot.sannysoft.com时,CHR_MEMORY检测项结果为FAIL
  • 访问bot.incolumitas.com时,两项检测失败:inconsistentWebWorkerNavigatorPropery: FAIL、inconsistentServiceWorkerNavigatorPropery: FAIL

已尝试Stack Overflow上多数高赞方案,包括修改navigator.webdriver标识规避Selenium检测、手动设置deviceMemory值、伪造navigator全局属性等,均未解决上述三个失败项,其余检测项已全部通过。

针对CHR_MEMORY检测失败,已尝试两种实现方案:

  1. 页面加载后执行JS注入修改属性:
driver.execute_script("Object.defineProperty(navigator, 'deviceMemory', {get: () => 8})")
  1. 通过CDP命令在文档创建前注入属性修改脚本:
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
                   Object.defineProperty(navigator, 'deviceMemory', {
                     get: () => Number(2)
                   });
                   """
 })

上述两种方案执行后,Fp-collect采集到的deviceMemory值确实显示为设置的数值,但仍未通过CHR_MEMORY检测。

核心疑问

  1. WebWorkerNavigatorPropery、ServiceWorkerNavigatorPropery两个检测项的具体含义是什么?
  2. 如何绕过上述两项以及CHR_MEMORY的Bot检测?

检测结果参考

  • sannysoft检测结果截图:sannysoft检测结果
  • incolumitas检测结果截图:incolumitas检测结果

问题解答

两个失败检测项含义

  • inconsistentWebWorkerNavigatorPropery:校验主线程window上下文的navigator属性,与Web Worker独立线程上下文下的navigator属性是否一致。原生Chrome环境中两个上下文的同源navigator属性值完全匹配;若仅修改主线程navigator属性、未同步覆盖Web Worker上下文的对应属性,会直接触发该检测项失败。
  • inconsistentServiceWorkerNavigatorPropery:检测逻辑与前者一致,对比维度为主线程navigator属性与Service Worker线程上下文的navigator属性值,仅修改主线程属性会触发检测失败。

各检测项绕过方案

1. CHR_MEMORY检测绕过

原有方案失效核心原因:CHR_MEMORY并非仅读取主线程navigator.deviceMemory值做判断,而是会交叉校验Chrome内存JSBI接口、Performance内存API等多维度返回的内存数据,单一修改navigator.deviceMemory无法通过交叉校验。
正确实现逻辑:通过CDP的Page.addScriptToEvaluateOnNewDocument接口在文档创建最早期注入脚本,同时覆盖所有内存相关读取入口,且设置的内存值需符合Chrome真实取值规则(仅支持0.25、0.5、1、2、4、8、16、32这类2的幂次固定值,不可自定义随机数值),参考注入代码:

Object.defineProperty(navigator, 'deviceMemory', {
    get: () => 8,
    configurable: true
});
// 同步覆盖performance内存接口返回值
if (window.performance && performance.memory) {
    Object.defineProperty(performance.memory, 'jsHeapSizeLimit', {
        get: () => 8 * 1024 * 1024 * 1024 * 0.9 // 8G物理内存对应堆内存上限约7.2G
    });
    Object.defineProperty(performance.memory, 'totalJSHeapSize', {
        get: () => 8 * 1024 * 1024 * 1024 * 0.2
    });
}

禁止在页面onload阶段执行属性注入,避免页面前置脚本读取到原始属性值。

2. WebWorker/ServiceWorker navigator属性不一致检测绕过

原有注入脚本仅作用于主线程上下文,未覆盖Worker独立线程,导致属性值不匹配。需在CDP初始注入脚本中重写Worker、ServiceWorker的创建逻辑,在Worker初始化阶段同步注入相同的属性修改代码,保证三个上下文的navigator属性完全一致,参考实现:

// 重写Worker构造函数,同步注入属性修改逻辑
const nativeWorker = window.Worker;
window.Worker = function(url, options) {
    const workerIns = new nativeWorker(url, options);
    const injectCode = `
        Object.defineProperty(self.navigator, 'deviceMemory', {get: () => 8});
        // 此处需同步补充所有主线程已修改的navigator属性,包括webdriver、hardwareConcurrency、platform、userAgent等
    `;
    // 向Worker注入代码执行
    workerIns.postMessage({__runCode: injectCode});
    workerIns.addEventListener('message', (e) => {
        if (e.data && e.data.__runCode) {
            eval(e.data.__runCode);
        }
    })
    return workerIns;
}
// 重写ServiceWorker注册逻辑,改写脚本内容后再注册
const nativeSwRegister = window.navigator.serviceWorker.register;
window.navigator.serviceWorker.register = async function(scriptUrl, options) {
    const scriptRes = await fetch(scriptUrl);
    let scriptContent = await scriptRes.text();
    // 前置注入属性修改代码
    scriptContent = `
        Object.defineProperty(self.navigator, 'deviceMemory', {get: () => 8});
        // 此处需同步补充所有主线程已修改的navigator属性,与Worker、主线程配置完全一致
    ` + scriptContent;
    const scriptBlob = new Blob([scriptContent], {type: 'application/javascript'});
    const blobUrl = URL.createObjectURL(scriptBlob);
    return nativeSwRegister.call(this, blobUrl, options);
}

注意:所有主线程中修改过的navigator属性,必须在Web Worker、ServiceWorker上下文做完全相同的赋值,避免出现任何属性值差异。


内容的提问来源于stack exchange,提问作者MrBrendan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 12:54:31