TRACIO 的机器人检测系统采用双层架构识别自动化浏览器、无头工具和脚本化攻击:客户端信号采集与服务端分析。它能以近乎零误报的精度检测主流自动化框架、无头浏览器、AI 浏览智能体和反检测浏览器,同时自动将合法的搜索引擎爬虫加入白名单。
浏览器代理会采集一系列机器人专属信号和交叉验证信号,用于服务端决策。下面的信号 ID 仅为示意 —— 内部 ID 并非稳定的公开契约:
| 信号 | 说明 |
|---|---|
s300 (webdriver) | navigator.webdriver 标志 —— 由自动化框架设置为 true |
s301 (eval length) | eval.toString().length —— Chrome/Edge:33,Firefox:37。其他值表明存在插桩。 |
s305 (bot composite) | 扫描 window/document 中的 14 项自动化框架痕迹 |
s97 (headless markers) | CDP 痕迹、通知权限、插件数量、外部尺寸 |
s157 (automation scan) | 全面扫描 Selenium、Puppeteer、PhantomJS、Playwright 及另外 10 种 |
s158 (iframe webdriver) | 创建隐藏的 iframe 并在其中读取 navigator.webdriver。可捕获那些只修补主框架却遗漏 iframe 的工具。 |
s159 (native function) | 删除 Function 和 Object,测试 getter 是否真正原生。检测基于 Proxy 的插桩。 |
s155 (window CRC32) | 对每个 window 属性进行 CRC32 哈希扫描,以检测注入的自动化全局变量 |
s163 (devtools trap) | Console getter 陷阱 —— 检测 DevTools 是否处于打开状态 |
服务端运行一组检测器,其加权输出组合成一个机器人评分。该评分通过阈值映射到判定结果 —— 当评分 ≥ 0.70 时为
bot,≥ 0.30 时为 suspicious,否则为 human —— 而硬失败信号(例如
navigator.webdriver)会直接强制得出 bot 判定。机器人判定会携带一个
自由格式的 bot_type 标签。
代表性检测器及其效果:
| 检测器 | 效果 |
|---|---|
| Webdriver 标志 | 硬失败 → bot(类型 webdriver) |
| 组合式自动化 / 框架扫描 | 高权重 → bot(类型 {framework}) |
| 无头标记 | 加权 → bot(类型 headless) |
| Eval 长度异常 | 加权 → bot(类型 unknown) |
| 恶意机器人 UA 模式 | 加权 → bot(类型 {label}) |
| 已验证的良性机器人(反向 DNS) | 白名单 → human |
| 行为分析(速率 / 熵 / 交互) | 加权 → bot(类型 rateBot) |
| VM(Enterprise)· 模拟器 · DevTools(Business+) | 加权的设备/篡改信号 |
套餐与可用性。 DevTools 检测在 Business 和 Enterprise 上运行; VM 检测为 Enterprise 专属;模拟器检测在所有套餐上运行。这些均可 在 Web 代理中工作。Root、越狱、克隆/分身应用、Frida 和恢复出厂设置 的检测依赖原生移动端信号,在纯 Web 部署中并不有效(开发中)。请 依赖自动化、无头、AI 智能体、反检测、VM/模拟器和行为判定,它们在 Web 上完全启用。
机器人检测会在每个事件上写入一个 bot_result 字段(在 webhook
负载 中为 bot.result)。
bot_result 为三个规范值之一:
| 结果 | 说明 |
|---|---|
human | 未发现自动化迹象。已验证的搜索引擎爬虫也会解析为 human。 |
bot | 检测到自动化或脚本化访问。会附带一个自由格式的 bot_type 标签。 |
uncertain | 混合或微弱的信号 —— 既不明确为人类,也不明确为自动化。 |
该结果映射到贯穿仪表盘使用的业务 decision 字段(real、fake 或 suspicious),
并映射到 webhook 负载 上的 bot.result。
"bot" 时)bot_type 是一个自由格式的字符串。下面的取值是检测器可能输出内容的示意示例,
并非详尽的枚举:
| 类型 | 检测方法 |
|---|---|
webdriver | navigator.webdriver 为 true |
selenium | 检测到 Selenium 专属的 window/document 属性 |
puppeteer | 匹配到 Puppeteer/Chromium 无头指标 |
playwright | 检测到 Playwright 专属标记或 UA 字符串 |
headless | 触发了 11 个无头标记中的 2 个及以上 |
phantomjs | 检测到 PhantomJS 全局变量(callPhantom、_phantom) |
nightmare | 检测到 NightmareJS 全局变量 |
unknown | Eval 长度异常或其他非特定的自动化迹象 |
rateBot | 行为速率分析超过阈值 |
最直接的检测。所有主流自动化框架都会依照 WebDriver 规范将 navigator.webdriver = true。此项会在主框架(s300)和隐藏 iframe(s158)中分别检查,以捕获那些只修补主框架的工具。
全面扫描 window 和 document 属性中的框架专属痕迹:
| 框架 | 检测到的属性 |
|---|---|
| Selenium | _Selenium_IDE_Recorder、_selenium、calledSelenium、__selenium_evaluate、$cdc_*(ChromeDriver) |
| Puppeteer | domAutomation、domAutomationController、HeadlessChrome UA |
| Playwright | __playwright、automation-controlled 标志 |
| PhantomJS | callPhantom、_phantom |
| NightmareJS | __nightmare、nightmare |
| CefSharp | CefSharp |
| Awesomium | awesomium |
| WebDriverIO | wdioElectron |
| Cypress | __cypress window 属性 |
该扫描还使用正则模式 /^([a-z]){3}_.*_(Array|Promise|Symbol)$/ 来检测 Selenium 注入的辅助全局变量。
评估 11 个标记,达到 2 个及以上即进行归类:
| 标记 | 信号 | 条件 |
|---|---|---|
| webdriver | s300 | = "true" |
| 缺失厂商特征 | s28 | window 上没有 chrome/safari 对象 |
| CDP 无头 chrome | s305 | headlessChrome = true |
| 通知被拒绝 | s88 | 首次访问时 Notification.permission = "denied" |
| chrome 无 runtime | s89 | window.chrome 存在但缺失 chrome.runtime |
| 单一语言 | s90 | navigator.languages.length <= 1 |
| 默认屏幕 800x600 | s5 | 无头 Chrome 默认分辨率 |
| HeadlessChrome UA | UA | User-Agent 包含 "HeadlessChrome" |
| 外部尺寸为零 | s97 | outerWidth = 0 且 outerHeight = 0 |
| WebGL SwiftShader | s70 | 渲染器包含 "swiftshader"(软件 GPU) |
| WebGL llvmpipe | s70 | 渲染器包含 "llvmpipe"(软件 GPU) |
已知的良性机器人通过 User-Agent 模式识别。每一个都通过反向 DNS 验证以防伪造:
.googlebot.com)| 机器人 | 允许的域名 |
|---|---|
.googlebot.com、.google.com | |
| Bing | .search.msn.com |
| Apple | .applebot.apple.com |
| Yahoo | .crawl.yahoo.net |
| Yandex | .yandex.com、.yandex.net、.yandex.ru |
| DuckDuckGo | .duckduckgo.com |
如果某请求声称自己是 Googlebot,但其 IP 的反向 DNS 解析到了外部域名(一次已确认的 PTR 不匹配,而非仅仅是缺失/超时的查询),则会被归类为 bot(类型 spoofed:google)。
基于速率的检测,配合熵评分:
| 速率(req/min) | 熵阈值 | 动作 |
|---|---|---|
| 120+ | < 0.1 | bot(类型:rateBot) |
| 60-120 | < 0.3 | bot(类型:rateBot) |
| 45-60 | < 0.1 | bot(类型:rateBot) |
| < 45 | 任意 | 正常 |
附加规则:会话时长超过 30 秒后仍无鼠标/键盘事件,则将该访问归类为 bot,类型为 noInteraction。
eval.toString().length 在每种引擎上产生一致的值:
任何其他值都表明 eval 函数已被自动化框架挂钩,会将该访问归类为 bot,类型为 unknown。
客户端 SDK 提供了一个便捷布尔值 result.bot.detected:
const result = await tracio.getResult()
if (result.bot.detected) { // Log and block console.warn(`Bot detected (confidence ${result.bot.confidence})`) showCaptcha() return}
// Proceed with loginawait login(credentials)在你的服务端,对 webhook 投递进行处理。机器人检测
位于 bot 对象中 —— bot.result 和 bot.type:
// `event` is the webhook delivery body (/docs/webhooks)app.post("/webhook/tracio", async (req, res) => { const event = req.body
if (event.bot.result === "bot") { await db.blockedRequests.insert({ visitorId: event.visitorId, botType: event.bot.type, ip: event.ip, timestamp: new Date(), }) }
res.status(200).send("OK")})TRACIO 的机器人检测以近乎零误报为设计目标。不过,边缘情况仍可能出现:
| 场景 | 风险 | 缓解措施 |
|---|---|---|
修改 navigator 的浏览器扩展 | 低 | 多信号交叉验证可避免单一信号触发 |
| 企业安全软件 | 极低 | 无头检测需要 2 个及以上标记 |
| 无障碍工具 | 无 | 无障碍 API 不会触发任何检测信号 |
| VPN/代理用户 | 无 | VPN 使用情况与机器人检测分开跟踪 |
如果你遇到误报,请查看 bot.type 字段以了解触发了哪个检测器,并据此调整你的策略。