O sistema de detecção de bots da TRACIO identifica navegadores automatizados, ferramentas headless e ataques com scripts usando uma arquitetura de duas camadas: coleta de sinais no cliente e análise no servidor. Ele detecta frameworks de automação populares, navegadores headless, agentes de navegação de IA e navegadores anti-detecção com quase zero falsos positivos, ao mesmo tempo que coloca automaticamente em allowlist os rastreadores legítimos de mecanismos de busca.
O agente de navegador coleta uma variedade de sinais específicos de bots e de validação cruzada que alimentam as decisões no servidor. Os IDs de sinais abaixo são ilustrativos — os IDs internos não são um contrato público estável:
| Sinal | Descrição |
|---|---|
s300 (webdriver) | Flag navigator.webdriver — definida como true por frameworks de automação |
s301 (eval length) | eval.toString().length — Chrome/Edge: 33, Firefox: 37. Outros valores indicam instrumentação. |
s305 (bot composite) | Varre window/document em busca de 14 artefatos de frameworks de automação |
s97 (headless markers) | Artefatos CDP, permissões de notificação, contagem de plugins, dimensões externas |
s157 (automation scan) | Varredura abrangente para Selenium, Puppeteer, PhantomJS, Playwright e mais 10 |
s158 (iframe webdriver) | Cria um iframe oculto e lê navigator.webdriver dentro dele. Pega ferramentas que corrigem o frame principal mas esquecem os iframes. |
s159 (native function) | Exclui Function e Object e testa se os getters são realmente nativos. Detecta instrumentação baseada em Proxy. |
s155 (window CRC32) | Varredura de hash CRC32 de cada propriedade de window para detectar globais de automação injetados |
s163 (devtools trap) | Armadilha de getter de console — detecta quando as DevTools estão ativamente abertas |
O servidor executa um conjunto de detectores cujas saídas ponderadas se combinam em uma pontuação de bot. A pontuação é mapeada para um veredito por meio de limiares — bot quando é ≥ 0.70, suspicious quando ≥ 0.30, caso contrário human — e um sinal de falha imediata (como navigator.webdriver) força um veredito bot de imediato. Vereditos de bot carregam um rótulo bot_type de formato livre.
Detectores representativos e seu efeito:
| Detector | Efeito |
|---|---|
| Flag webdriver | Falha imediata → bot (tipo webdriver) |
| Varredura composta de automação / framework | Peso alto → bot (tipo {framework}) |
| Marcadores headless | Ponderado → bot (tipo headless) |
| Anomalia de eval-length | Ponderado → bot (tipo unknown) |
| Padrão de UA de bad-bot | Ponderado → bot (tipo {label}) |
| Bom bot verificado (DNS reverso) | Allowlist → human |
| Comportamental (taxa / entropia / interação) | Ponderado → bot (tipo rateBot) |
| VM (Enterprise) · Emulador · DevTools (Business+) | Sinais ponderados de dispositivo/adulteração |
Camada e disponibilidade. A detecção de DevTools roda em Business e Enterprise; a detecção de VM é Enterprise; a detecção de emulador roda em todos os planos. Todas funcionam no agente web. A detecção de root, jailbreak, apps clonados/duplicados, Frida e restauração de fábrica depende de sinais nativos de mobile e não é eficaz na implantação apenas web (em desenvolvimento). Confie nos vereditos de automação, headless, agente de IA, anti-detecção, VM/emulador e comportamental, que estão totalmente ativos na web.
A detecção de bots grava um campo bot_result em cada evento (e bot.result no
payload do webhook).
bot_result é um de três valores canônicos:
| Resultado | Descrição |
|---|---|
human | Nenhum indicador de automação encontrado. Rastreadores verificados de mecanismos de busca também resolvem para human. |
bot | Acesso automatizado ou com scripts detectado. Um rótulo bot_type de formato livre o acompanha. |
uncertain | Sinais mistos ou fracos — nem claramente humano nem claramente automatizado. |
Isso é mapeado para o campo de negócio decision (real, fake ou suspicious)
usado em todo o dashboard, e para bot.result no
payload do webhook.
"bot")bot_type é uma string de formato livre. Os valores abaixo são exemplos ilustrativos do
que os detectores emitem, não um enum exaustivo:
| Tipo | Método de Detecção |
|---|---|
webdriver | navigator.webdriver é true |
selenium | Propriedades de window/document específicas do Selenium detectadas |
puppeteer | Indicadores headless de Puppeteer/Chromium correspondidos |
playwright | Marcadores específicos do Playwright ou string de UA detectados |
headless | 2+ de 11 marcadores headless acionados |
phantomjs | Globais do PhantomJS detectados (callPhantom, _phantom) |
nightmare | Globais do NightmareJS detectados |
unknown | Anomalia de eval length ou outros indicadores de automação não específicos |
rateBot | Análise comportamental de taxa excedeu os limiares |
A detecção mais direta. Todos os principais frameworks de automação definem navigator.webdriver = true conforme a especificação WebDriver. Isso é verificado tanto no frame principal (s300) quanto em um iframe oculto (s158) para pegar ferramentas que corrigem apenas o frame principal.
Varredura abrangente das propriedades de window e document em busca de artefatos específicos de frameworks:
| Framework | Propriedades Detectadas |
|---|---|
| Selenium | _Selenium_IDE_Recorder, _selenium, calledSelenium, __selenium_evaluate, $cdc_* (ChromeDriver) |
| Puppeteer | domAutomation, domAutomationController, HeadlessChrome UA |
| Playwright | __playwright, flag automation-controlled |
| PhantomJS | callPhantom, _phantom |
| NightmareJS | __nightmare, nightmare |
| CefSharp | CefSharp |
| Awesomium | awesomium |
| WebDriverIO | wdioElectron |
| Cypress | Propriedade de window __cypress |
A varredura também usa o padrão de regex /^([a-z]){3}_.*_(Array|Promise|Symbol)$/ para detectar os globais auxiliares injetados pelo Selenium.
11 marcadores são avaliados, com um limiar de 2 ou mais para classificação:
| Marcador | Sinal | Condição |
|---|---|---|
| webdriver | s300 | = "true" |
| sabores de vendor ausentes | s28 | Sem objetos chrome/safari em window |
| CDP headless chrome | s305 | headlessChrome = true |
| notification denied | s88 | Notification.permission = "denied" na primeira visita |
| chrome no runtime | s89 | window.chrome existe mas chrome.runtime está ausente |
| single language | s90 | navigator.languages.length <= 1 |
| tela padrão 800x600 | s5 | Resolução padrão do Chrome headless |
| HeadlessChrome UA | UA | User-Agent contém "HeadlessChrome" |
| dimensões externas zero | s97 | outerWidth = 0 e outerHeight = 0 |
| WebGL SwiftShader | s70 | Renderer contém "swiftshader" (GPU em software) |
| WebGL llvmpipe | s70 | Renderer contém "llvmpipe" (GPU em software) |
Bons bots conhecidos são reconhecidos pelo padrão de User-Agent. Cada um é verificado via DNS reverso para evitar falsificação:
.googlebot.com)| Bot | Domínios Permitidos |
|---|---|
.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 |
Se uma requisição afirma ser o Googlebot mas o DNS reverso do seu IP resolve para um domínio estranho (uma incompatibilidade de PTR confirmada, não apenas uma consulta ausente/expirada), ela é classificada como bot (tipo spoofed:google).
Detecção baseada em taxa com pontuação de entropia:
| Taxa (req/min) | Limiar de Entropia | Ação |
|---|---|---|
| 120+ | < 0.1 | bot (tipo: rateBot) |
| 60-120 | < 0.3 | bot (tipo: rateBot) |
| 45-60 | < 0.1 | bot (tipo: rateBot) |
| < 45 | Qualquer | Normal |
Regra adicional: nenhum evento de mouse/teclado após 30+ segundos de idade da sessão classifica a visita como bot com tipo noInteraction.
eval.toString().length produz valores consistentes por engine:
Qualquer outro valor indica que a função eval foi interceptada por um framework de automação, classificando a visita como bot com tipo unknown.
O SDK do cliente expõe um booleano de conveniência, 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)No seu servidor, aja sobre a entrega do webhook. A detecção de bots
fica no objeto bot — bot.result e 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")})A detecção de bots da TRACIO foi projetada para quase zero falsos positivos. No entanto, casos extremos podem ocorrer:
| Cenário | Risco | Mitigação |
|---|---|---|
Extensões de navegador modificando navigator | Baixo | A validação cruzada de múltiplos sinais impede acionamentos por sinal único |
| Software de segurança corporativo | Muito Baixo | A detecção headless exige 2+ marcadores |
| Ferramentas de acessibilidade | Nenhum | APIs de acessibilidade não acionam nenhum sinal de detecção |
| Usuários de VPN/proxy | Nenhum | O uso de VPN é rastreado separadamente da detecção de bots |
Se você encontrar falsos positivos, revise o campo bot.type para entender qual detector foi acionado e ajuste sua política de acordo.