Автоматизация браузера с Puppeteer и профилями отпечатков
Полное руководство по интеграции Puppeteer с профилями отпечатков, поддержкой прокси и продакшен-развёртыванием.
Нужна поддерживаемая продуктовая документация?
У этой статьи есть соответствующая страница в центре документации. Используйте docs для каноничного сценария настройки, актуальных флагов и долгосрочной справки.
Введение
Puppeteer - это библиотека Node.js от Google для управления Chrome через Chrome DevTools Protocol (CDP). Она предоставляет высокоуровневый API для навигации, создания скриншотов, взаимодействия с формами, перехвата сети и многого другого. BotBrowser заменяет стандартный бинарный файл Chromium на тот, который обеспечивает согласованный вывод отпечатков, управляемый файлами профилей. Puppeteer отвечает за автоматизацию, BotBrowser - за идентичность.
Это руководство охватывает полную интеграцию: установку, конфигурацию запуска, управление viewport, настройку прокси, доступ к CDP, продакшен-развёртывание на Linux-серверах и типичное устранение неполадок. К концу у вас будет рабочая настройка Puppeteer + BotBrowser, готовая для разработки и продакшен-использования.
Влияние на приватность: почему Puppeteer + BotBrowser
Стандартный Puppeteer запускает штатный бинарный файл Chromium, который раскрывает реальный отпечаток хост-машины. Каждый экземпляр браузера имеет одинаковый GPU, шрифты, разрешение экрана и характеристики платформы. Также присутствуют индикаторы автоматизации, такие как navigator.webdriver, что явно указывает на программное управление браузером.
С BotBrowser каждый экземпляр Puppeteer может загружать свой профиль отпечатков, обеспечивая уникальную идентичность браузера. Отпечаток применяется на уровне движка, до загрузки страницы и до выполнения любого JavaScript. Ваш код автоматизации Puppeteer не нужно менять вообще. Контроль идентичности происходит на уровне конфигурации запуска.
Это позволяет запускать несколько параллельных экземпляров Puppeteer, каждый с отдельным профилем отпечатков, прокси, часовым поясом и локалью, и всё это с одной хост-машины. Разделение чёткое: Puppeteer управляет тем, что браузер делает, BotBrowser управляет тем, чем браузер является.
Техническая база
Почему puppeteer-core, а не puppeteer
Стандартный npm-пакет puppeteer включает собственный бинарный файл Chromium. При установке он скачивает определённую версию Chromium, управляемую командой Puppeteer. Этот бинарный файл не включает возможности контроля отпечатков BotBrowser.
Пакет puppeteer-core предоставляет тот же API без встроенных браузеров. Он требует указания executablePath при запуске, что позволяет направить Puppeteer на бинарный файл BotBrowser.
# Устанавливайте puppeteer-core, а не puppeteer
npm install puppeteer-core
Настройка defaultViewport
У Puppeteer есть критически важное поведение по умолчанию: он устанавливает defaultViewport 800x600 пикселей для каждой новой страницы. Это переопределяет любые размеры viewport, заданные в профиле отпечатков BotBrowser, вызывая несоответствие между сообщаемым размером экрана (из профиля) и фактическим размером viewport (800x600 от Puppeteer).
Всегда устанавливайте defaultViewport: null для предотвращения этого переопределения и чтобы профиль BotBrowser управлял размерами viewport.
Доступ к CDP
Puppeteer предоставляет прямой доступ к CDP через объекты CDPSession. Это важно для BotBrowser, поскольку некоторые продвинутые функции управляются через пользовательские CDP-команды:
// CDP-сессия на уровне браузера
const cdpSession = await browser.target().createCDPSession();
// CDP-команды BotBrowser
await cdpSession.send('BotBrowser.setCustomHeaders', {
headers: { 'X-Custom': 'value' }
});
Обратите внимание, что CDP-команды BotBrowser должны отправляться в сессию уровня браузера, а не уровня страницы. Использование page.createCDPSession() приведёт к ошибке «method not found» для BotBrowser-специфичных команд.
Распространённые подходы и их ограничения
Использование встроенного браузера Puppeteer
Встроенный Chromium Puppeteer подходит для базовой автоматизации, но не предоставляет контроля отпечатков. Каждый экземпляр имеет одинаковый отпечаток, и сигналы автоматизации обнаруживаемы.
Stealth-плагины
Пакет puppeteer-extra-plugin-stealth патчит некоторые индикаторы автоматизации через JavaScript-инъекцию. Однако он работает на неправильном уровне. JavaScript-инъекция происходит после создания страницы и может быть обнаружена через анализ тайминга, инспекцию цепочки прототипов и другие техники. Она также не контролирует сигналы на уровне рендеринга, такие как вывод canvas, строки рендерера WebGL или доступность шрифтов.
Ручная установка User-Agent
Puppeteer позволяет устанавливать пользовательский User-Agent через page.setUserAgent(). Это меняет один сигнал, но оставляет все остальные (платформа, шрифты, GPU, метрики экрана) на реальных значениях. Несоответствие между User-Agent и другими сигналами само по себе является обнаруживаемым сигналом.
Подход BotBrowser
BotBrowser интегрируется с Puppeteer через стандартный параметр executablePath в puppeteer.launch(). Никаких плагинов, патчей или промежуточного ПО не требуется.
Интеграция без изменения кода
Добавление BotBrowser в существующий проект Puppeteer требует изменения только конфигурации запуска. Весь код на уровне страницы (селекторы, навигация, извлечение данных) остаётся точно таким же.
Сигналы на уровне движка
Профиль отпечатков загружается при инициализации браузера. К моменту подключения Puppeteer через CDP все сигналы уже на месте. Нет состояния гонки, нет фазы настройки и нет риска раскрытия реального отпечатка при запуске.
Полная совместимость с CDP
BotBrowser расширяет стандартный CDP пользовательскими командами для продвинутых функций, таких как пользовательские заголовки и поконтекстная конфигурация. Все стандартные CDP-команды продолжают работать как задокументировано.
Настройка и использование
Необходимые условия
- Бинарный файл BotBrowser (скачать с GitHub)
- Файл профиля отпечатков (формат
.enc) - Node.js 18+
npm install puppeteer-core
Убедитесь, что бинарный файл BotBrowser имеет разрешения на выполнение:
chmod +x /path/to/botbrowser/chrome
Базовый запуск
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
],
headless: true,
defaultViewport: null, // Критически важно: пусть профиль управляет viewport
});
const page = await browser.newPage();
await page.goto('https://example.com');
const title = await page.title();
console.log('Page title:', title);
await browser.close();
})();
Профиль + прокси + локаль
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
'--proxy-server=socks5://user:pass@proxy:1080',
'--bot-config-timezone=Europe/London',
'--bot-config-locale=en-GB',
'--bot-config-languages=en-GB,en',
],
headless: true,
defaultViewport: null,
});
Полная настройка идентичности
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
'--proxy-server=socks5://user:pass@us-proxy:1080',
'--bot-config-timezone=America/New_York',
'--bot-config-locale=en-US',
'--bot-config-languages=en-US,en',
'--bot-inject-random-history',
'--bot-bookmarks=[{"title":"Google","type":"url","url":"https://www.google.com"}]',
'--bot-cookies=@/path/to/cookies.json',
'--bot-always-active',
],
headless: true,
defaultViewport: null,
});
Несколько идентичностей
async function createSession(profilePath, proxyUrl, timezone) {
const args = [
`--bot-profile=${profilePath}`,
];
if (proxyUrl) args.push(`--proxy-server=${proxyUrl}`);
if (timezone) args.push(`--bot-config-timezone=${timezone}`);
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args,
headless: true,
defaultViewport: null,
});
return browser;
}
// Запуск нескольких уникальных идентичностей
const sessions = await Promise.all([
createSession('/profiles/win11-us.enc', 'socks5://u:p@us:1080', 'America/New_York'),
createSession('/profiles/win11-de.enc', 'socks5://u:p@de:1080', 'Europe/Berlin'),
createSession('/profiles/android-jp.enc', 'socks5://u:p@jp:1080', 'Asia/Tokyo'),
]);
Перехват сети
const page = await browser.newPage();
// Включение перехвата запросов
await page.setRequestInterception(true);
page.on('request', request => {
if (request.resourceType() === 'image') {
request.abort();
} else {
request.continue();
}
});
await page.goto('https://example.com');
Скриншот и PDF
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle0' });
// Скриншот
await page.screenshot({ path: 'screenshot.png', fullPage: true });
// PDF
await page.pdf({ path: 'page.pdf', format: 'A4' });
Headless на Ubuntu
Для Linux-серверов установите переменную окружения DISPLAY:
const puppeteer = require('puppeteer-core');
// Установите DISPLAY перед запуском
process.env.DISPLAY = ':10.0';
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
],
headless: true,
defaultViewport: null,
});
Или установите в оболочке перед запуском скрипта:
DISPLAY=:10.0 node script.js
Проверка
Проверьте интеграцию, проверив сигналы отпечатков:
const page = await browser.newPage();
await page.goto('https://example.com');
const fingerprint = await page.evaluate(() => ({
userAgent: navigator.userAgent,
platform: navigator.platform,
languages: navigator.languages,
hardwareConcurrency: navigator.hardwareConcurrency,
deviceMemory: navigator.deviceMemory,
webdriver: navigator.webdriver,
screenWidth: screen.width,
screenHeight: screen.height,
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
dpr: devicePixelRatio,
touchPoints: navigator.maxTouchPoints,
}));
console.log('Fingerprint:', JSON.stringify(fingerprint, null, 2));
Лучшие практики
- Всегда устанавливайте
defaultViewport: null. Это самая важная настройка. Без неё Puppeteer переопределит viewport профиля на 800x600. - Используйте
puppeteer-core, а не полный пакетpuppeteer. Полный пакет скачивает ненужный бинарный файл Chromium. - Используйте абсолютные пути для
--bot-profileи других флагов на основе файлов. Относительные пути могут разрешаться некорректно. - Закрывайте экземпляры браузера по завершении. Каждый экземпляр - это процесс Chrome. Незакрытые экземпляры приводят к утечке памяти и CPU.
- Установите
DISPLAY=:10.0на Linux-серверах, даже для headless-режима. - Корректно обрабатывайте ошибки. Оберните запуск и навигацию в блоки try/catch. Запуск браузера может не удаться из-за отсутствующих зависимостей или некорректных путей.
Часто задаваемые вопросы
Можно ли использовать полный пакет puppeteer вместо puppeteer-core?
Технически да, но он скачает ненужный бинарный файл Chromium при npm install. Используйте puppeteer-core, чтобы сэкономить место на диске и явно указать на использование пользовательского бинарного файла.
Нужен ли puppeteer-extra или stealth-плагины?
Нет. BotBrowser обрабатывает контроль отпечатков на уровне движка. Stealth-плагины добавляют JavaScript-патчи, которые не нужны с BotBrowser и могут помешать его работе.
Почему мой viewport показывает 800x600?
Вы забыли установить defaultViewport: null в параметрах запуска. Это поведение Puppeteer по умолчанию. Добавьте defaultViewport: null, чтобы профиль BotBrowser управлял viewport.
Как работает аутентификация прокси?
BotBrowser расширяет --proxy-server для поддержки встроенных учётных данных: --proxy-server=socks5://user:pass@host:port. Не используйте page.authenticate() Puppeteer для авторизации прокси, так как это может отключить автоматическое геоопределение BotBrowser.
Можно ли использовать browser.createBrowserContext() Puppeteer для попрокси-контекстного прокси?
BotBrowser поддерживает попрокси-контекстный прокси через собственный механизм (ENT Tier1). Использование createBrowserContext({ proxyServer }) с синтаксисом, совместимым с Playwright, зависит от вашей версии Puppeteer и уровня BotBrowser.
Как отладить, если профиль не загружается?
Проверьте следующие распространённые проблемы:
- Путь к профилю абсолютный и файл существует
- Бинарный файл BotBrowser имеет разрешения на выполнение
- Используйте флаги
--bot-internal --v=1для включения отладочного логирования - Проверьте вывод консоли браузера на ошибки загрузки профиля
Какая версия Node.js необходима?
Рекомендуется Node.js 18 или выше. Puppeteer-core требует минимум Node.js 16.
Можно ли использовать TypeScript?
Да. puppeteer-core включает определения типов TypeScript:
import puppeteer, { Browser, Page } from 'puppeteer-core';
Итоги
Интеграция BotBrowser с Puppeteer требует установки puppeteer-core, указания executablePath на бинарный файл BotBrowser, добавления --bot-profile в аргументы запуска и установки defaultViewport: null. Все стандартные функции Puppeteer работают без модификации.
По смежным темам смотрите Начало работы с Playwright для эквивалента Playwright, Рецепты CLI для комбинаций флагов, Настройка headless-сервера для продакшен-развёртывания и Управление профилями для организации профилей.
Похожие статьи
Переведите BotBrowser из исследований в продакшн
Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.