Voltar ao blog

Como ocultar o uso de Selenium e Puppeteer

Descubra como ocultar efetivamente o uso de Selenium e Puppeteer de sistemas de proteção contra bots. Métodos práticos, exemplos de código e técnicas comprovadas de camuflagem de automação.

📅26 de dezembro de 2025
```html

Guia completo para mascarar Selenium e Puppeteer da detecção

Sistemas modernos de proteção contra bots reconhecem facilmente navegadores automatizados por dezenas de sinais: desde variáveis JavaScript até características do comportamento do WebDriver. Sites utilizam Cloudflare, DataDome, PerimeterX e soluções próprias que bloqueiam até 90% dos pedidos de Selenium e Puppeteer na configuração padrão.

Neste guia, vamos explorar todos os métodos de mascaramento da automação: desde configurações básicas até técnicas avançadas de contorno da detecção. Você receberá soluções prontas com exemplos de código para Python e Node.js que funcionam contra a maioria dos sistemas de proteção.

Como os sites detectam a automação

Sistemas de proteção contra bots analisam o navegador por múltiplos parâmetros ao mesmo tempo. Mesmo que você oculte um sinal, os outros revelarão a automação. Compreender todos os métodos de detecção é a chave para um mascaramento eficaz.

Indicadores do WebDriver

O método mais simples de detecção é verificar variáveis JavaScript que estão presentes apenas em navegadores automatizados:

// Essas variáveis revelam Selenium/Puppeteer
navigator.webdriver === true
window.navigator.webdriver === true
document.$cdc_ // Variável específica do ChromeDriver
window.document.documentElement.getAttribute("webdriver")
navigator.plugins.length === 0 // Navegadores automatizados não têm plugins
navigator.languages === "" // Lista de idiomas vazia

Cloudflare e sistemas semelhantes verificam essas propriedades em primeiro lugar. Se pelo menos uma retornar um resultado positivo — o pedido é bloqueado.

Fingerprinting do navegador

Sistemas avançados criam uma impressão digital única do navegador com base em dezenas de parâmetros:

  • Canvas Fingerprinting — renderização de imagens ocultas e análise de dados de pixels
  • WebGL Fingerprinting — parâmetros do renderizador gráfico e da placa de vídeo
  • Audio Context — características únicas do processamento de áudio
  • Fonts Fingerprinting — lista de fontes instaladas no sistema
  • Screen Resolution — resolução da tela, profundidade de cor, área disponível
  • Timezone & Language — fuso horário, idiomas do navegador, localidade do sistema

Navegadores automatizados frequentemente têm combinações não típicas desses parâmetros. Por exemplo, o Chrome sem cabeça não possui plugins, mas suporta WebGL — tal combinação é extremamente rara entre usuários reais.

Análise comportamental

Sistemas modernos rastreiam padrões de comportamento:

  • Movimentos do mouse — bots movem o cursor em linhas retas ou não se movem de forma alguma
  • Velocidade das ações — preenchimento instantâneo de formulários, velocidade de cliques não humana
  • Padrões de rolagem — saltos bruscos em vez de rolagem suave
  • Eventos de teclado — ausência de atrasos naturais entre as teclas pressionadas
  • Frequência de pedidos — intervalos entre ações muito regulares

Importante: DataDome e PerimeterX utilizam aprendizado de máquina para analisar comportamentos. Eles foram treinados em milhões de sessões e podem reconhecer um bot mesmo com a mascaragem técnica correta, se o comportamento parecer não natural.

Mascaramento básico do Selenium

O Selenium WebDriver na configuração padrão deixa muitos rastros. Vamos considerar uma configuração passo a passo para minimizar a detecção usando Python e ChromeDriver.

Desativando o sinalizador do webdriver

O primeiro passo é ocultar a variável navigator.webdriver. Isso é feito através do Chrome DevTools Protocol:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

# Configuração das opções do Chrome
chrome_options = Options()

# Desativando o sinalizador de automação
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)

# Criando o driver
driver = webdriver.Chrome(options=chrome_options)

# Removendo o webdriver através do CDP
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        })
    '''
})

driver.get('https://example.com')

Configurando User-Agent e outros cabeçalhos

Navegadores sem cabeça frequentemente usam strings de User-Agent desatualizadas ou específicas. É necessário definir um User-Agent atual de um navegador real:

# User-Agent atual do Chrome no Windows
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
chrome_options.add_argument(f'user-agent={user_agent}')

# Argumentos adicionais para mascaramento
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-gpu')

# Tamanho da janela como um usuário real
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--start-maximized')

Adicionando plugins e idiomas

Navegadores automatizados não têm plugins e frequentemente mostram uma lista de idiomas vazia. Corrigimos isso através do CDP:

driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'languages', {
            get: () => ['pt-BR', 'pt', 'en']
        });
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [
                {
                    0: {type: "application/x-google-chrome-pdf", suffixes: "pdf", description: "Portable Document Format"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Plugin"
                },
                {
                    0: {type: "application/pdf", suffixes: "pdf", description: ""},
                    description: "",
                    filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai",
                    length: 1,
                    name: "Chrome PDF Viewer"
                }
            ]
        });
        
        Object.defineProperty(navigator, 'platform', {
            get: () => 'Win32'
        });
    '''
})

Exemplo completo de configuração do Selenium

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import random

def create_stealth_driver():
    chrome_options = Options()
    
    # Configurações básicas de mascaramento
    chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
    chrome_options.add_experimental_option('useAutomationExtension', False)
    chrome_options.add_argument('--disable-blink-features=AutomationControlled')
    
    # User-Agent
    user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
    chrome_options.add_argument(f'user-agent={user_agent}')
    
    # Tamanho da janela
    chrome_options.add_argument('--window-size=1920,1080')
    chrome_options.add_argument('--start-maximized')
    
    driver = webdriver.Chrome(options=chrome_options)
    
    # Script de mascaramento através do CDP
    stealth_script = '''
        Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
        Object.defineProperty(navigator, 'languages', {get: () => ['pt-BR', 'pt']});
        Object.defineProperty(navigator, 'platform', {get: () => 'Win32'});
        
        window.chrome = {
            runtime: {}
        };
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [1, 2, 3, 4, 5]
        });
    '''
    
    driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
        'source': stealth_script
    })
    
    return driver

# Uso
driver = create_stealth_driver()
driver.get('https://bot.sannysoft.com/')  # Site para verificar a detecção

Configuração do Puppeteer para contornar a detecção

O Puppeteer tem os mesmos problemas de detecção que o Selenium. No entanto, para Node.js, existe uma biblioteca pronta chamada puppeteer-extra-plugin-stealth, que automatiza a maioria das configurações de mascaramento.

Instalando puppeteer-extra

npm install puppeteer puppeteer-extra puppeteer-extra-plugin-stealth

Configuração básica com o plugin stealth

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

// Conectando o plugin de mascaramento
puppeteer.use(StealthPlugin());

(async () => {
    const browser = await puppeteer.launch({
        headless: 'new', // Novo modo headless do Chrome
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-dev-shm-usage',
            '--disable-accelerated-2d-canvas',
            '--disable-gpu',
            '--window-size=1920,1080',
            '--disable-web-security',
            '--disable-features=IsolateOrigins,site-per-process'
        ]
    });
    
    const page = await browser.newPage();
    
    // Definindo o viewport
    await page.setViewport({
        width: 1920,
        height: 1080,
        deviceScaleFactor: 1
    });
    
    // Definindo o User-Agent
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
    
    // Cabeçalhos adicionais
    await page.setExtraHTTPHeaders({
        'Accept-Language': 'pt-BR,pt;q=0.9',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
    });
    
    await page.goto('https://bot.sannysoft.com/');
    
    // Captura de tela para verificação
    await page.screenshot({ path: 'test.png' });
    
    await browser.close();
})();

Configuração manual sem plugins

Se você deseja controle total ou não pode usar bibliotecas de terceiros, configure a mascaragem manualmente:

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: ['--no-sandbox', '--disable-setuid-sandbox']
    });
    
    const page = await browser.newPage();
    
    // Redefinindo webdriver e outras propriedades
    await page.evaluateOnNewDocument(() => {
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        });
        
        Object.defineProperty(navigator, 'languages', {
            get: () => ['pt-BR', 'pt']
        });
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [1, 2, 3, 4, 5]
        });
        
        // Mascarando Chrome headless
        Object.defineProperty(navigator, 'platform', {
            get: () => 'Win32'
        });
        
        window.chrome = {
            runtime: {}
        };
        
        // Redefinindo permissões
        const originalQuery = window.navigator.permissions.query;
        window.navigator.permissions.query = (parameters) => (
            parameters.name === 'notifications' ?
                Promise.resolve({ state: Notification.permission }) :
                originalQuery(parameters)
        );
    });
    
    await page.goto('https://example.com');
    await browser.close();
})();

Configuração para contornar o Cloudflare

O Cloudflare utiliza métodos avançados de detecção. Para contornar, é necessário adicionar atrasos aleatórios e emular ações:

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

puppeteer.use(StealthPlugin());

async function bypassCloudflare(url) {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-web-security'
        ]
    });
    
    const page = await browser.newPage();
    
    // User-Agent aleatório
    const userAgents = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
    ];
    await page.setUserAgent(userAgents[Math.floor(Math.random() * userAgents.length)]);
    
    // Navegando para a página
    await page.goto(url, { waitUntil: 'networkidle2' });
    
    // Esperando a verificação do Cloudflare (geralmente 5-10 segundos)
    await page.waitForTimeout(8000);
    
    // Movimento aleatório do mouse
    await page.mouse.move(100, 100);
    await page.mouse.move(200, 200);
    
    const content = await page.content();
    await browser.close();
    
    return content;
}

Combate ao fingerprinting JavaScript

O fingerprinting JavaScript é a criação de uma impressão digital única do navegador com base em muitos parâmetros. Mesmo que você tenha ocultado o webdriver, os sistemas analisam centenas de outras propriedades para identificar a automação.

Principais vetores de fingerprinting

Sistemas de proteção contra bots verificam os seguintes parâmetros:

Parâmetro O que é verificado Risco de detecção
navigator.webdriver Presença do sinalizador de automação Crítico
navigator.plugins Número e tipos de plugins Alto
window.chrome Presença da API do Chrome Médio
navigator.permissions API de permissões do navegador Médio
screen.colorDepth Profundidade de cor da tela Baixo
navigator.hardwareConcurrency Número de núcleos do processador Baixo

Script complexo de mascaramento

O script abaixo redefine a maioria das propriedades problemáticas. Implemente-o através do CDP (Selenium) ou evaluateOnNewDocument (Puppeteer):

const stealthScript = `
    // Removendo o webdriver
    Object.defineProperty(navigator, 'webdriver', {
        get: () => undefined
    });
    
    // Adicionando objeto chrome
    window.chrome = {
        runtime: {},
        loadTimes: function() {},
        csi: function() {},
        app: {}
    };
    
    // Redefinindo permissões
    const originalQuery = window.navigator.permissions.query;
    window.navigator.permissions.query = (parameters) => (
        parameters.name === 'notifications' ?
            Promise.resolve({ state: Notification.permission }) :
            originalQuery(parameters)
    );
    
    // Mascarando plugins
    Object.defineProperty(navigator, 'plugins', {
        get: () => {
            return [
                {
                    0: {type: "application/x-google-chrome-pdf", suffixes: "pdf"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Plugin"
                },
                {
                    0: {type: "application/pdf", suffixes: "pdf"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Viewer"
                },
                {
                    0: {type: "application/x-nacl"},
                    description: "Native Client Executable",
                    filename: "internal-nacl-plugin",
                    length: 2,
                    name: "Native Client"
                }
            ];
        }
    });
    
    // Idiomas
    Object.defineProperty(navigator, 'languages', {
        get: () => ['pt-BR', 'pt']
    });
    
    // Plataforma
    Object.defineProperty(navigator, 'platform', {
        get: () => 'Win32'
    });
    
    // Fornecedor
    Object.defineProperty(navigator, 'vendor', {
        get: () => 'Google Inc.'
    });
    
    // Removendo rastros do Selenium
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;
    
    // Battery API (ausente em headless)
    if (!navigator.getBattery) {
        navigator.getBattery = () => Promise.resolve({
            charging: true,
            chargingTime: 0,
            dischargingTime: Infinity,
            level: 1
        });
    }
`;

Remoção de propriedades do WebDriver

O ChromeDriver e outras implementações do WebDriver adicionam variáveis específicas ao escopo global. Essas variáveis começam com o prefixo cdc_ e são facilmente detectadas pelos sistemas de proteção.

Detecção de variáveis cdc

Verificar a presença dessas variáveis pode ser feito com um simples script:

// Procurando todas as variáveis cdc
for (let key in window) {
    if (key.includes('cdc_')) {
        console.log('Variável WebDriver detectada:', key);
    }
}

// Variáveis típicas do ChromeDriver:
// cdc_adoQpoasnfa76pfcZLmcfl_Array
// cdc_adoQpoasnfa76pfcZLmcfl_Promise
// cdc_adoQpoasnfa76pfcZLmcfl_Symbol
// $cdc_asdjflasutopfhvcZLmcfl_

Método 1: Remoção via CDP

O método mais confiável é remover as variáveis antes de carregar a página através do Chrome DevTools Protocol:

from selenium import webdriver

driver = webdriver.Chrome()

# Removendo todas as variáveis cdc
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        // Removendo variáveis cdc conhecidas
        const cdcProps = [
            'cdc_adoQpoasnfa76pfcZLmcfl_Array',
            'cdc_adoQpoasnfa76pfcZLmcfl_Promise',
            'cdc_adoQpoasnfa76pfcZLmcfl_Symbol',
            '$cdc_asdjflasutopfhvcZLmcfl_'
        ];
        
        cdcProps.forEach(prop => {
            delete window[prop];
        });
        
        // Removendo todas as variáveis que contêm 'cdc_'
        Object.keys(window).forEach(key => {
            if (key.includes('cdc_') || key.includes('$cdc_')) {
                delete window[key];
            }
        });
    '''
})

Método 2: Modificação do ChromeDriver

Uma abordagem mais radical é modificar o arquivo binário do ChromeDriver, substituindo a string cdc_ por outra sequência de caracteres. Isso evita a criação dessas variáveis:

import re

def patch_chromedriver(driver_path):
    """
    Patche o ChromeDriver, substituindo 'cdc_' por uma string aleatória
    """
    with open(driver_path, 'rb') as f:
        content = f.read()
    
    # Substituindo todas as ocorrências de 'cdc_' por 'dog_' (ou qualquer outra string do mesmo comprimento)
    patched = content.replace(b'cdc_', b'dog_')
    
    with open(driver_path, 'wb') as f:
        f.write(patched)
    
    print(f'ChromeDriver patchado: {driver_path}')

# Uso
patch_chromedriver('/path/to/chromedriver')

Atenção: Modificar o arquivo binário do ChromeDriver pode comprometer seu funcionamento. Sempre faça um backup antes de aplicar o patch. Este método pode não funcionar com todas as versões do ChromeDriver.

Método 3: Usando undetected-chromedriver

A biblioteca undetected-chromedriver automaticamente aplica patches ao ChromeDriver ao iniciar:

pip install undetected-chromedriver
import undetected_chromedriver as uc

# Criando o driver com patch automático
driver = uc.Chrome()

driver.get('https://nowsecure.nl/')  # Site para verificar a detecção
input('Pressione Enter para fechar...')
driver.quit()

Mascaramento do Canvas, WebGL e Audio API

Canvas, WebGL e Audio Fingerprinting são métodos de criação de uma impressão digital única com base nas características de renderização gráfica e processamento de som. Cada combinação de navegador, SO e hardware gera um resultado único.

Canvas Fingerprinting

Sistemas desenham uma imagem oculta no Canvas e analisam os pixels resultantes. Navegadores sem cabeça frequentemente produzem resultados não típicos devido à ausência de aceleração de GPU.

// Código típico de Canvas Fingerprinting
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillText('Impressão digital do navegador', 2, 2);
const fingerprint = canvas.toDataURL();

Para proteção, você pode adicionar ruído aleatório à API do Canvas:

const canvasNoiseScript = `
    // Adicionando ruído aleatório ao Canvas
    const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
    const originalToBlob = HTMLCanvasElement.prototype.toBlob;
    const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
    
    // Função para adicionar ruído
    const addNoise = (canvas, context) => {
        const imageData = originalGetImageData.call(context, 0, 0, canvas.width, canvas.height);
        for (let i = 0; i < imageData.data.length; i += 4) {
            // Adicionando ruído mínimo ao RGB (invisível a olho nu)
            imageData.data[i] += Math.floor(Math.random() * 3) - 1;
            imageData.data[i + 1] += Math.floor(Math.random() * 3) - 1;
            imageData.data[i + 2] += Math.floor(Math.random() * 3) - 1;
        }
        context.putImageData(imageData, 0, 0);
    };
    
    // Redefinindo toDataURL
    HTMLCanvasElement.prototype.toDataURL = function() {
        if (this.width > 0 && this.height > 0) {
            const context = this.getContext('2d');
            addNoise(this, context);
        }
        return originalToDataURL.apply(this, arguments);
    };
`;

WebGL Fingerprinting

O WebGL fornece informações sobre a placa de vídeo e drivers. Navegadores sem cabeça frequentemente mostram SwiftShader (renderizador de software) em vez da GPU real:

const webglMaskScript = `
    // Mascarando parâmetros do WebGL
    const getParameter = WebGLRenderingContext.prototype.getParameter;
    WebGLRenderingContext.prototype.getParameter = function(parameter) {
        // UNMASKED_VENDOR_WEBGL
        if (parameter === 37445) {
            return 'Intel Inc.';
        }
        // UNMASKED_RENDERER_WEBGL
        if (parameter === 37446) {
            return 'Intel Iris OpenGL Engine';
        }
        return getParameter.call(this, parameter);
    };
    
    // Também para WebGL2
    if (typeof WebGL2RenderingContext !== 'undefined') {
        const getParameter2 = WebGL2RenderingContext.prototype.getParameter;
        WebGL2RenderingContext.prototype.getParameter = function(parameter) {
            if (parameter === 37445) {
                return 'Intel Inc.';
            }
            if (parameter === 37446) {
                return 'Intel Iris OpenGL Engine';
            }
            return getParameter2.call(this, parameter);
        };
    }
`;

Fingerprinting do Audio Context

A API de áudio também fornece uma impressão digital única. Adicionamos ruído ao processamento de áudio:

const audioMaskScript = `
    // Adicionando ruído ao Audio Context
    const AudioContext = window.AudioContext || window.webkitAudioContext;
    if (AudioContext) {
        const originalCreateAnalyser = AudioContext.prototype.createAnalyser;
        AudioContext.prototype.createAnalyser = function() {
            const analyser = originalCreateAnalyser.call(this);
            const originalGetFloatFrequencyData = analyser.getFloatFrequencyData;
            analyser.getFloatFrequencyData = function(array) {
                originalGetFloatFrequencyData.call(this, array);
                // Adicionando ruído mínimo
                for (let i = 0; i < array.length; i++) {
                    array[i] += Math.random() * 0.0001;
                }
            };
            return analyser;
        };
    }
`;

Imitação do comportamento humano

Mesmo com uma mascaragem técnica perfeita, bots se revelam pelo comportamento. Sistemas de aprendizado de máquina analisam padrões de movimentos do mouse, velocidade das ações e sequência de eventos.

Atrasos aleatórios entre ações

Nunca use atrasos fixos. Usuários reais fazem pausas de duração variável:

import random
import time

def human_delay(min_seconds=1, max_seconds=3):
    """Atraso aleatório imitando um humano"""
    delay = random.uniform(min_seconds, max_seconds)
    time.sleep(delay)

# Uso
driver.get('https://example.com')
human_delay(2, 4)  # Pausa de 2-4 segundos

element = driver.find_element(By.ID, 'search')
human_delay(0.5, 1.5)  # Pausa curta antes da entrada

element.send_keys('consulta de pesquisa')
human_delay(1, 2)

Movimento suave do mouse

Bots movem o mouse em linhas retas ou teleportam o cursor. Usuários reais criam trajetórias curvas com aceleração e desaceleração:

// Puppeteer: movimento suave do mouse
async function humanMouseMove(page, targetX, targetY) {
    const steps = 25; // Número de pontos intermediários
    const currentPos = await page.evaluate(() => ({
        x: window.mouseX || 0,
        y: window.mouseY || 0
    }));
    
    for (let i = 0; i <= steps; i++) {
        const t = i / steps;
        // Usando easing para suavidade
        const ease = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
        
        const x = currentPos.x + (targetX - currentPos.x) * ease;
        const y = currentPos.y + (targetY - currentPos.y) * ease;
        
        await page.mouse.move(x, y);
        await page.waitForTimeout(Math.random() * 10 + 5);
    }
    
    // Salvando a posição
    await page.evaluate((x, y) => {
        window.mouseX = x;
        window.mouseY = y;
    }, targetX, targetY);
}

// Uso
await humanMouseMove(page, 500, 300);
await page.mouse.click(500, 300);

Rolagem natural

Usuários reais rolam suavemente, com paradas para ler o conteúdo:

async function humanScroll(page) {
    const scrollHeight = await page.evaluate(() => document.body.scrollHeight);
    const viewportHeight = await page.evaluate(() => window.innerHeight);
    
    let currentPosition = 0;
    
    while (currentPosition < scrollHeight - viewportHeight) {
        // Passo de rolagem aleatório (200-500px)
        const scrollStep = Math.floor(Math.random() * 300) + 200;
        currentPosition += scrollStep;
        
        // Rolagem suave
        await page.evaluate((pos) => {
            window.scrollTo({
                top: pos,
                behavior: 'smooth'
            });
        }, currentPosition);
        
        // Pausa para "ler" o conteúdo (1-3 segundos)
        await page.waitForTimeout(Math.random() * 2000 + 1000);
    }
}

// Uso
await page.goto('https://example.com');
await humanScroll(page);

Entrada de texto natural

As pessoas digitam em velocidades variadas, cometem erros de digitação e os corrigem:

async function humanTypeText(page, selector, text) {
    await page.click(selector);
    
    for (let char of text) {
        // Atraso aleatório entre as teclas (50-200ms)
        const delay = Math.random() * 150 + 50;
        await page.waitForTimeout(delay);
        
        // 5% de chance de erro de digitação
        if (Math.random() < 0.05) {
            // Digitando um caractere aleatório
            const wrongChar = String.fromCharCode(97 + Math.floor(Math.random() * 26));
            await page.keyboard.type(wrongChar);
            await page.waitForTimeout(100 + Math.random() * 100);
            // Deletando (Backspace)
            await page.keyboard.press('Backspace');
            await page.waitForTimeout(50 + Math.random() * 50);
        }
        
        await page.keyboard.type(char);
    }
}

// Uso
await humanTypeText(page, '#search-input', 'consulta de pesquisa');

Integração de proxy para total anonimato

Mascarar o navegador é inútil se todos os pedidos vêm de um único endereço IP. Sistemas de proteção contra bots rastreiam o número de pedidos de cada IP e bloqueiam atividades suspeitas. Proxies são um componente obrigatório de qualquer automação séria.

Escolhendo o tipo de proxy

Diferentes tarefas exigem diferentes tipos de proxies:

Tipo de proxy Vantagens Aplicação
Proxies residenciais IP real, menos chance de bloqueio Raspagem de dados, acesso a conteúdo geobloqueado
Proxies datacenter Mais rápidos e baratos Testes, automação em larga escala
Proxies móveis IP de dispositivos móveis, alta anonimidade Acesso a aplicativos móveis, testes de aplicativos

Configuração de proxy no Selenium

Para usar um proxy no Selenium, você pode configurar as opções do Chrome:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

# Configuração do proxy
proxy = "http://username:password@proxy_ip:proxy_port"
chrome_options = Options()
chrome_options.add_argument(f'--proxy-server={proxy}')

# Criando o driver
driver = webdriver.Chrome(options=chrome_options)
driver.get('https://example.com')

Bibliotecas e ferramentas prontas

Existem várias bibliotecas e ferramentas que podem facilitar o processo de mascaramento e automação. Aqui estão algumas recomendadas:

  • puppeteer-extra — uma extensão do Puppeteer que permite adicionar plugins como o stealth.
  • undetected-chromedriver — uma biblioteca que contorna a detecção do ChromeDriver.
  • SeleniumBase — uma biblioteca que simplifica o uso do Selenium com funcionalidades adicionais.
  • Scrapy — um framework de raspagem de dados que pode ser integrado com proxies e técnicas de mascaramento.

Teste do nível de detecção

Após implementar as técnicas de mascaramento, é crucial testar o nível de detecção. Você pode usar serviços como:

  • bot.sannysoft.com — um site que verifica se o seu navegador é detectável como um bot.
  • browserleaks.com — um site que fornece informações sobre o seu navegador e pode ajudar a identificar possíveis vazamentos de informações.

Conclusão

Ocultar a automação de navegadores como Selenium e Puppeteer é um desafio, mas com as técnicas e ferramentas certas, é possível minimizar a detecção. A chave é entender como os sistemas de proteção funcionam e adaptar suas abordagens de acordo. Continue testando e ajustando suas configurações para garantir que sua automação permaneça invisível.

```