Назад к блогу

Как скрыть использование Selenium и Puppeteer

Узнайте, как эффективно скрыть использование Selenium и Puppeteer от систем антибот-защиты. Практические методы, примеры кода и проверенные техники маскировки автоматизации.

📅26 декабря 2025 г.

Полное руководство по маскировке Selenium и Puppeteer от детекции

Современные системы антибот-защиты легко распознают автоматизированные браузеры по десяткам признаков: от переменных JavaScript до особенностей поведения WebDriver. Сайты используют Cloudflare, DataDome, PerimeterX и собственные решения, которые блокируют до 90% запросов от Selenium и Puppeteer в стандартной конфигурации.

В этом руководстве разберём все методы маскировки автоматизации: от базовых настроек до продвинутых техник обхода детекции. Вы получите готовые решения с примерами кода для Python и Node.js, которые работают против большинства защитных систем.

Как сайты обнаруживают автоматизацию

Системы антибот-защиты анализируют браузер по множеству параметров одновременно. Даже если вы скроете один признак, остальные выдадут автоматизацию. Понимание всех методов детекции — ключ к эффективной маскировке.

WebDriver-индикаторы

Самый простой метод обнаружения — проверка JavaScript-переменных, которые присутствуют только в автоматизированных браузерах:

// Эти переменные выдают Selenium/Puppeteer
navigator.webdriver === true
window.navigator.webdriver === true
document.$cdc_ // ChromeDriver специфичная переменная
window.document.documentElement.getAttribute("webdriver")
navigator.plugins.length === 0 // У автоматизированных браузеров нет плагинов
navigator.languages === "" // Пустой список языков

Cloudflare и подобные системы проверяют эти свойства в первую очередь. Если хотя бы одно возвращает положительный результат — запрос блокируется.

Фингерпринтинг браузера

Продвинутые системы создают уникальный отпечаток браузера на основе десятков параметров:

  • Canvas Fingerprinting — рендеринг скрытых изображений и анализ пиксельных данных
  • WebGL Fingerprinting — параметры графического рендерера и видеокарты
  • Audio Context — уникальные характеристики аудио-обработки
  • Fonts Fingerprinting — список установленных шрифтов в системе
  • Screen Resolution — разрешение экрана, глубина цвета, доступная область
  • Timezone & Language — часовой пояс, языки браузера, локаль системы

Автоматизированные браузеры часто имеют нетипичные комбинации этих параметров. Например, Headless Chrome не имеет плагинов, но поддерживает WebGL — такая комбинация встречается крайне редко у реальных пользователей.

Поведенческий анализ

Современные системы отслеживают паттерны поведения:

  • Движения мыши — боты двигают курсор по прямым линиям или не двигают вообще
  • Скорость действий — мгновенное заполнение форм, нечеловеческая скорость кликов
  • Паттерны скроллинга — резкие прыжки вместо плавной прокрутки
  • События клавиатуры — отсутствие естественных задержек между нажатиями
  • Частота запросов — слишком регулярные интервалы между действиями

Важно: DataDome и PerimeterX используют машинное обучение для анализа поведения. Они обучены на миллионах сессий и могут распознать бота даже при правильной маскировке технических параметров, если поведение выглядит неестественно.

Базовая маскировка Selenium

Selenium WebDriver в стандартной конфигурации оставляет множество следов. Рассмотрим пошаговую настройку для минимизации детекции на примере Python и ChromeDriver.

Отключение флага webdriver

Первый шаг — скрыть переменную navigator.webdriver. Это делается через Chrome DevTools Protocol:

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

# Настройка опций Chrome
chrome_options = Options()

# Отключаем флаг автоматизации
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)

# Создаём драйвер
driver = webdriver.Chrome(options=chrome_options)

# Удаляем webdriver через CDP
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        })
    '''
})

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

Настройка User-Agent и других заголовков

Headless-браузеры часто используют устаревшие или специфичные User-Agent строки. Необходимо установить актуальный User-Agent реального браузера:

# Актуальный User-Agent Chrome на 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}')

# Дополнительные аргументы для маскировки
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')

# Размер окна как у реального пользователя
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--start-maximized')

Добавление плагинов и языков

Автоматизированные браузеры не имеют плагинов и часто показывают пустой список языков. Исправляем это через CDP:

driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'languages', {
            get: () => ['en-US', 'en', 'ru']
        });
        
        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'
        });
    '''
})

Полный пример настройки Selenium

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

def create_stealth_driver():
    chrome_options = Options()
    
    # Базовые настройки маскировки
    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}')
    
    # Размер окна
    chrome_options.add_argument('--window-size=1920,1080')
    chrome_options.add_argument('--start-maximized')
    
    driver = webdriver.Chrome(options=chrome_options)
    
    # Скрипт маскировки через CDP
    stealth_script = '''
        Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
        Object.defineProperty(navigator, 'languages', {get: () => ['en-US', 'en']});
        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

# Использование
driver = create_stealth_driver()
driver.get('https://bot.sannysoft.com/')  # Сайт для проверки детекции

Настройка Puppeteer для обхода детекции

Puppeteer имеет те же проблемы с детекцией, что и Selenium. Однако для Node.js существует готовая библиотека puppeteer-extra-plugin-stealth, которая автоматизирует большинство настроек маскировки.

Установка puppeteer-extra

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

Базовая конфигурация с плагином stealth

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

// Подключаем плагин маскировки
puppeteer.use(StealthPlugin());

(async () => {
    const browser = await puppeteer.launch({
        headless: 'new', // Новый headless режим 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();
    
    // Устанавливаем viewport
    await page.setViewport({
        width: 1920,
        height: 1080,
        deviceScaleFactor: 1
    });
    
    // Устанавливаем 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');
    
    // Дополнительные заголовки
    await page.setExtraHTTPHeaders({
        'Accept-Language': 'en-US,en;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/');
    
    // Скриншот для проверки
    await page.screenshot({ path: 'test.png' });
    
    await browser.close();
})();

Ручная настройка без плагинов

Если вы хотите полный контроль или не можете использовать сторонние библиотеки, настройте маскировку вручную:

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: ['--no-sandbox', '--disable-setuid-sandbox']
    });
    
    const page = await browser.newPage();
    
    // Переопределяем webdriver и другие свойства
    await page.evaluateOnNewDocument(() => {
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        });
        
        Object.defineProperty(navigator, 'languages', {
            get: () => ['en-US', 'en']
        });
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [1, 2, 3, 4, 5]
        });
        
        // Маскируем Chrome headless
        Object.defineProperty(navigator, 'platform', {
            get: () => 'Win32'
        });
        
        window.chrome = {
            runtime: {}
        };
        
        // Переопределяем permissions
        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();
})();

Настройка для обхода Cloudflare

Cloudflare использует продвинутые методы детекции. Для обхода необходимо добавить случайные задержки и эмуляцию действий:

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
    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)]);
    
    // Переход на страницу
    await page.goto(url, { waitUntil: 'networkidle2' });
    
    // Ждём проверку Cloudflare (обычно 5-10 секунд)
    await page.waitForTimeout(8000);
    
    // Случайное движение мыши
    await page.mouse.move(100, 100);
    await page.mouse.move(200, 200);
    
    const content = await page.content();
    await browser.close();
    
    return content;
}

Борьба с JavaScript-фингерпринтингом

JavaScript-фингерпринтинг — это создание уникального отпечатка браузера на основе множества параметров. Даже если вы скрыли webdriver, системы анализируют сотни других свойств для выявления автоматизации.

Основные векторы фингерпринтинга

Системы антибот-защиты проверяют следующие параметры:

Параметр Что проверяется Риск детекции
navigator.webdriver Наличие флага автоматизации Критический
navigator.plugins Количество и типы плагинов Высокий
window.chrome Наличие Chrome API Средний
navigator.permissions API разрешений браузера Средний
screen.colorDepth Глубина цвета экрана Низкий
navigator.hardwareConcurrency Количество ядер процессора Низкий

Комплексный скрипт маскировки

Скрипт ниже переопределяет большинство проблемных свойств. Внедряйте его через CDP (Selenium) или evaluateOnNewDocument (Puppeteer):

const stealthScript = `
    // Удаляем webdriver
    Object.defineProperty(navigator, 'webdriver', {
        get: () => undefined
    });
    
    // Добавляем chrome объект
    window.chrome = {
        runtime: {},
        loadTimes: function() {},
        csi: function() {},
        app: {}
    };
    
    // Переопределяем permissions
    const originalQuery = window.navigator.permissions.query;
    window.navigator.permissions.query = (parameters) => (
        parameters.name === 'notifications' ?
            Promise.resolve({ state: Notification.permission }) :
            originalQuery(parameters)
    );
    
    // Маскируем плагины
    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"
                }
            ];
        }
    });
    
    // Языки
    Object.defineProperty(navigator, 'languages', {
        get: () => ['en-US', 'en']
    });
    
    // Platform
    Object.defineProperty(navigator, 'platform', {
        get: () => 'Win32'
    });
    
    // Vendor
    Object.defineProperty(navigator, 'vendor', {
        get: () => 'Google Inc.'
    });
    
    // Удаляем следы Selenium
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;
    
    // Battery API (отсутствует в headless)
    if (!navigator.getBattery) {
        navigator.getBattery = () => Promise.resolve({
            charging: true,
            chargingTime: 0,
            dischargingTime: Infinity,
            level: 1
        });
    }
`;

Удаление WebDriver-свойств

ChromeDriver и другие WebDriver-реализации добавляют специфичные переменные в глобальную область видимости. Эти переменные начинаются с префикса cdc_ и легко обнаруживаются защитными системами.

Обнаружение cdc-переменных

Проверить наличие этих переменных можно простым скриптом:

// Поиск всех cdc-переменных
for (let key in window) {
    if (key.includes('cdc_')) {
        console.log('Обнаружена переменная WebDriver:', key);
    }
}

// Типичные переменные ChromeDriver:
// cdc_adoQpoasnfa76pfcZLmcfl_Array
// cdc_adoQpoasnfa76pfcZLmcfl_Promise
// cdc_adoQpoasnfa76pfcZLmcfl_Symbol
// $cdc_asdjflasutopfhvcZLmcfl_

Метод 1: Удаление через CDP

Самый надёжный способ — удалить переменные до загрузки страницы через Chrome DevTools Protocol:

from selenium import webdriver

driver = webdriver.Chrome()

# Удаляем все cdc-переменные
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        // Удаляем известные cdc-переменные
        const cdcProps = [
            'cdc_adoQpoasnfa76pfcZLmcfl_Array',
            'cdc_adoQpoasnfa76pfcZLmcfl_Promise',
            'cdc_adoQpoasnfa76pfcZLmcfl_Symbol',
            '$cdc_asdjflasutopfhvcZLmcfl_'
        ];
        
        cdcProps.forEach(prop => {
            delete window[prop];
        });
        
        // Удаляем все переменные содержащие 'cdc_'
        Object.keys(window).forEach(key => {
            if (key.includes('cdc_') || key.includes('$cdc_')) {
                delete window[key];
            }
        });
    '''
})

Метод 2: Модификация ChromeDriver

Более радикальный подход — изменить бинарный файл ChromeDriver, заменив строку cdc_ на другую последовательность символов. Это предотвращает создание этих переменных:

import re

def patch_chromedriver(driver_path):
    """
    Патчит ChromeDriver, заменяя 'cdc_' на случайную строку
    """
    with open(driver_path, 'rb') as f:
        content = f.read()
    
    # Заменяем все вхождения 'cdc_' на 'dog_' (или любую другую строку той же длины)
    patched = content.replace(b'cdc_', b'dog_')
    
    with open(driver_path, 'wb') as f:
        f.write(patched)
    
    print(f'ChromeDriver патчен: {driver_path}')

# Использование
patch_chromedriver('/path/to/chromedriver')

Внимание: Модификация бинарного файла ChromeDriver может нарушить его работу. Всегда делайте резервную копию перед патчингом. Этот метод работает не со всеми версиями ChromeDriver.

Метод 3: Использование undetected-chromedriver

Библиотека undetected-chromedriver автоматически патчит ChromeDriver при запуске:

pip install undetected-chromedriver
import undetected_chromedriver as uc

# Создание драйвера с автоматическим патчингом
driver = uc.Chrome()

driver.get('https://nowsecure.nl/')  # Сайт для проверки детекции
input('Нажмите Enter для закрытия...')
driver.quit()

Маскировка Canvas, WebGL и Audio API

Canvas, WebGL и Audio Fingerprinting — это методы создания уникального отпечатка на основе особенностей рендеринга графики и обработки звука. Каждая комбинация браузера, ОС и железа даёт уникальный результат.

Canvas Fingerprinting

Системы рисуют скрытое изображение на Canvas и анализируют получившиеся пиксели. Headless-браузеры часто дают нетипичные результаты из-за отсутствия GPU-ускорения.

// Типичный код Canvas Fingerprinting
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillText('Browser fingerprint', 2, 2);
const fingerprint = canvas.toDataURL();

Для защиты можно добавить случайный шум к Canvas API:

const canvasNoiseScript = `
    // Добавляем случайный шум к Canvas
    const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
    const originalToBlob = HTMLCanvasElement.prototype.toBlob;
    const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
    
    // Функция добавления шума
    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) {
            // Добавляем минимальный шум к RGB (не заметен глазу)
            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);
    };
    
    // Переопределяем 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

WebGL предоставляет информацию о видеокарте и драйверах. Headless-браузеры часто показывают SwiftShader (программный рендерер) вместо реальной GPU:

const webglMaskScript = `
    // Маскируем 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);
    };
    
    // Также для 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);
        };
    }
`;

Audio Context Fingerprinting

Audio API также даёт уникальный отпечаток. Добавляем шум к аудио-обработке:

const audioMaskScript = `
    // Добавляем шум к 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);
                // Добавляем минимальный шум
                for (let i = 0; i < array.length; i++) {
                    array[i] += Math.random() * 0.0001;
                }
            };
            return analyser;
        };
    }
`;

Имитация человеческого поведения

Даже с идеальной технической маскировкой боты выдают себя поведением. Системы машинного обучения анализируют паттерны движений мыши, скорость действий и последовательность событий.

Случайные задержки между действиями

Никогда не используйте фиксированные задержки. Реальные пользователи делают паузы разной длительности:

import random
import time

def human_delay(min_seconds=1, max_seconds=3):
    """Случайная задержка имитирующая человека"""
    delay = random.uniform(min_seconds, max_seconds)
    time.sleep(delay)

# Использование
driver.get('https://example.com')
human_delay(2, 4)  # Пауза 2-4 секунды

element = driver.find_element(By.ID, 'search')
human_delay(0.5, 1.5)  # Короткая пауза перед вводом

element.send_keys('search query')
human_delay(1, 2)

Плавное движение мыши

Боты двигают мышь по прямым линиям или телепортируют курсор. Реальные пользователи создают кривые траектории с ускорением и замедлением:

// Puppeteer: плавное движение мыши
async function humanMouseMove(page, targetX, targetY) {
    const steps = 25; // Количество промежуточных точек
    const currentPos = await page.evaluate(() => ({
        x: window.mouseX || 0,
        y: window.mouseY || 0
    }));
    
    for (let i = 0; i <= steps; i++) {
        const t = i / steps;
        // Используем easing для плавности
        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);
    }
    
    // Сохраняем позицию
    await page.evaluate((x, y) => {
        window.mouseX = x;
        window.mouseY = y;
    }, targetX, targetY);
}

// Использование
await humanMouseMove(page, 500, 300);
await page.mouse.click(500, 300);

Естественный скроллинг

Реальные пользователи скроллят плавно, с остановками для чтения контента:

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) {
        // Случайный шаг скролла (200-500px)
        const scrollStep = Math.floor(Math.random() * 300) + 200;
        currentPosition += scrollStep;
        
        // Плавный скролл
        await page.evaluate((pos) => {
            window.scrollTo({
                top: pos,
                behavior: 'smooth'
            });
        }, currentPosition);
        
        // Пауза для "чтения" контента (1-3 секунды)
        await page.waitForTimeout(Math.random() * 2000 + 1000);
    }
}

// Использование
await page.goto('https://example.com');
await humanScroll(page);

Естественный ввод текста

Люди печатают с разной скоростью, делают опечатки и исправляют их:

async function humanTypeText(page, selector, text) {
    await page.click(selector);
    
    for (let char of text) {
        // Случайная задержка между нажатиями (50-200ms)
        const delay = Math.random() * 150 + 50;
        await page.waitForTimeout(delay);
        
        // 5% шанс опечатки
        if (Math.random() < 0.05) {
            // Печатаем случайный символ
            const wrongChar = String.fromCharCode(97 + Math.floor(Math.random() * 26));
            await page.keyboard.type(wrongChar);
            await page.waitForTimeout(100 + Math.random() * 100);
            // Удаляем (Backspace)
            await page.keyboard.press('Backspace');
            await page.waitForTimeout(50 + Math.random() * 50);
        }
        
        await page.keyboard.type(char);
    }
}

// Использование
await humanTypeText(page, '#search-input', 'example search query');

Интеграция прокси для полной анонимности

Маскировка браузера бесполезна, если все запросы идут с одного IP-адреса. Системы антибот-защиты отслеживают количество запросов с каждого IP и блокируют подозрительную активность. Прокси — обязательный компонент любой серьёзной автоматизации.

Выбор типа прокси

Разные задачи требуют разных типов прокси:

Тип прокси Преимущества Применение