Прокси в Playwright и Puppeteer: настройка, авторизация и разные IP на контекст
У браузерной автоматизации две особенности, на которых спотыкаются все: Chromium не принимает пароль в аргументе запуска, а прокси можно задать не только браузеру, но и каждому контексту отдельно. Второе позволяет работать с несколькими адресами из одного процесса.
Два уровня, на которых задаётся прокси
Прокси можно указать при запуске браузера — тогда он действует на всё, — либо при создании контекста. Контекст в этих библиотеках — это изолированная сессия со своими cookie и хранилищем, и у каждого может быть свой адрес. Для сбора данных это удобнее одного общего прокси: профили не пересекаются ни по состоянию, ни по адресу.
Playwright: креды прямо в опции
Здесь всё просто: логин и пароль передаются в той же настройке, что и адрес, и это работает и на запуске, и на контексте.
import { chromium } from 'playwright'
// Playwright принимает логин и пароль прямо в опции — и на запуске браузера,
// и на отдельном контексте.
const browser = await chromium.launch({
proxy: { server: 'http://ШЛЮЗ:ПОРТ', username: 'ЛОГИН', password: 'ПАРОЛЬ' },
})
// Свой адрес на каждый контекст: так один браузер работает
// с несколькими IP одновременно.
const ctx = await browser.newContext({
proxy: { server: 'http://ШЛЮЗ:ПОРТ', username: 'ЛОГИН', password: 'ПАРОЛЬ' },
})
const page = await ctx.newPage()
await page.goto('https://example.com')Puppeteer: пароль отдельным вызовом
Chromium игнорирует учётные данные, переданные в аргументе запуска, и показывает вместо этого системное окно авторизации — драйвер его не заполнит, и страница просто не загрузится. Поэтому креды передаются отдельным вызовом, и обязательно до перехода на страницу.
import puppeteer from 'puppeteer'
// Логин и пароль в --proxy-server Chromium игнорирует: он покажет системное
// окно авторизации, которое драйвер не заполнит. Креды идут отдельным вызовом.
const browser = await puppeteer.launch({
args: ['--proxy-server=http://ШЛЮЗ:ПОРТ'],
})
const page = await browser.newPage()
await page.authenticate({ username: 'ЛОГИН', password: 'ПАРОЛЬ' }) // до goto
await page.goto('https://example.com')
// Отдельный контекст со своим прокси; креды всё равно через page.authenticate
const ctx = await browser.createBrowserContext({
proxyServer: 'http://ШЛЮЗ:ПОРТ',
proxyBypassList: ['127.0.0.1'],
})Почему авторизация по IP здесь удобнее
Оба фреймворка требуют дополнительных действий для передачи пароля, а в случае SOCKS5 он может не сработать вовсе. Авторизация по whitelist снимает вопрос целиком: адрес машины добавляется один раз, и браузер подключается без учётных данных, независимо от фреймворка и протокола.
У нас обе схемы активны одновременно, поэтому это не размен: браузерные задачи на сервере ходят по whitelist, а скрипты с других машин продолжают работать по логину.
Сколько контекстов открывать
Здесь легко переоценить возможности. Один контекст с открытой страницей держит не одно соединение, а несколько: сама страница, изображения, скрипты, запросы к API. Поэтому число контекстов не равно числу потоков в тарифе — оно заметно меньше.
- Ориентируйтесь на 5–10 одновременных подключений на один активный контекст с полной загрузкой страницы.
- Тариф на 50 потоков комфортно держит 5–8 контекстов, а не пятьдесят.
- Блокировка ненужных ресурсов — изображений, шрифтов, аналитики — снижает расход подключений в разы.
Последний пункт стоит сделать первым делом: для сбора цен или текста картинки и шрифты не нужны, а на них уходит большая часть соединений и трафика.
Если браузер не нужен
Прежде чем поднимать Chromium, стоит проверить, нужен ли он: браузер расходует в разы больше подключений и памяти, чем обычный запрос. Для страниц, где данные приходят отдельным ответом в формате JSON, браузер не нужен вовсе.
// Прокси из переменных окружения, без библиотек.
// Флаг и переменная появились в свежих версиях Node и помечены как
// активно развивающиеся — проверьте, что ваша версия их поддерживает.
// node --use-env-proxy script.js
// NODE_USE_ENV_PROXY=1 node script.js
// Действует на fetch(), http.request() и https.request().
// Явный адрес в коде требует установки undici:
import { fetch, ProxyAgent } from 'undici'
const agent = new ProxyAgent({ uri: 'http://ШЛЮЗ:ПОРТ' })
await fetch('https://example.com', { dispatcher: agent })
// axios: опция proxy работает ТОЛЬКО в Node, и её перебивает
// кастомный httpAgent или httpsAgent — если задали агента, опция игнорируется.
// proxy: false отключает прокси и заодно игнорирует переменные окружения.Две ловушки из этого фрагмента стоят внимания. Опция прокси в axios работает только на сервере — в браузерной сборке она молча ничего не делает. И она же перестаёт действовать, если вы задали собственного агента: агент перебивает опцию, причём без предупреждения.
Что отключить, чтобы браузер не съедал лимит
Это самая действенная правка из всех: для сбора цен или текста изображения, шрифты и аналитика не нужны, а на них уходит большая часть подключений и трафика. Блокировка ненужных типов ресурсов снижает расход в разы, а не на проценты.
- Изображения и шрифты — почти всегда лишние для сбора данных.
- Скрипты аналитики и рекламы — открывают соединения к сторонним хостам, которых нет в вашем расчёте.
- Медиа и шрифтовые подгрузки — самый тяжёлый по трафику класс.
Пул для браузерной автоматизации
HTTP и SOCKS5, авторизация по whitelist для headless-браузеров. IPv6 от 650 ₽ за 50 потоков.
Смотреть тарифыПрокси под эту задачу
Проверить нашими инструментами
Читайте также
- Автоматизация прокси через API: whitelist, покупка и продление из скриптаPUT на whitelist заменяет список целиком, а не дополняет его — на этом теряют доступ. Разбор нашего API: ключ и лимиты, обновление адреса по cron, покупка и продление, коды ошибок.
- Прокси с логином и паролем в Selenium: почему сломались все старые рецептыЗа 2025 год Chrome убрал четыре разные вещи, и каждая ломает свою строчку десятилетнего туториала. Что именно перестало работать, чего в MV3 не потеряли и четыре пути, которые работают сейчас.
- Прокси в Key Collector: почему аккаунтным модулям нужна статика, а не ротацияПрограмма делится на модули, и правильный прокси у них разный. Аккаунт закрепляет за собой один адрес до перезапуска, Google.Ads не принимает IPv6 и SOCKS, а браузерный обработчик теряет SOCKS целиком.
