TrueSocks

Гайды · 6 мин

Прокси в Selenium, Playwright и Puppeteer: авторизация и ротация

  • Редакция TrueSocks
  • 6 мин чтения

Браузерная автоматизация и прокси - связка, на которой спотыкаются чаще всего. Адрес прокси задаётся в одну строку, а вот логин и пароль Chrome через ключ запуска не принимает, SOCKS5 с авторизацией работает не везде, а ротация в браузере ведёт себя иначе, чем в HTTP-клиенте. Ниже проверенные схемы для трёх инструментов: как передать авторизацию, как дать каждому контексту свой IP и как не раскрыть настоящий адрес.

Коротко

5 пунктов
  • Playwright принимает логин и пароль прокси отдельными полями при запуске браузера или создании контекста.
  • В Puppeteer адрес задаётся ключом --proxy-server, а авторизация вызовом page.authenticate().
  • Selenium с Chrome не умеет авторизацию прокси из коробки: используйте привязку по IP или локальный пересыльщик без пароля.
  • SOCKS5 с логином и паролем Chromium не поддерживает, для браузерной автоматизации берите HTTP(S)-прокси.
  • Для браузера нужна липкая сессия или статический адрес: смена IP посреди загрузки страницы ломает сессии на сайтах.

Как три инструмента работают с прокси

#
PlaywrightPuppeteerSelenium
Где задаётся проксиПараметр proxy при запуске или в контекстеКлюч --proxy-server или опция контекстаКлюч Chrome или настройки Firefox
Логин и парольПоля username и passwordpage.authenticate()Нет встроенного способа
Свой прокси на контекстДаДа, createBrowserContextНет, один браузер - один прокси
SOCKS5 с авторизацией в ChromiumНетНетНет
ЯзыкиPython, Node.js, Java, .NETNode.jsPython, Java, C#, JS, Ruby

Ограничение с SOCKS5 идёт от самого Chromium: браузер не поддерживает авторизацию на SOCKS-прокси. Поэтому для браузерной автоматизации проще всего заказать прокси с протоколом HTTP(S), он выбирается при оформлении заказа. Если без SOCKS5 не обойтись, используйте привязку по IP или локальный пересыльщик, о нём ниже.

Playwright

#

Playwright принимает прокси как объект с адресом и данными авторизации. Логин и пароль нужно передавать отдельными полями: учётные данные внутри строки server браузер не использует.

Python: прокси на весь браузер
from playwright.sync_api import sync_playwright

PROXY = {
    "server": "http://203.0.113.10:8000",
    "username": "login",
    "password": "password",
}

with sync_playwright() as p:
    browser = p.chromium.launch(proxy=PROXY)
    page = browser.new_page()
    page.goto("https://api.ipify.org")
    print(page.inner_text("body"))
    browser.close()

Свой прокси для каждого контекста

Контекст в Playwright - изолированная сессия со своими cookies и хранилищем, аналог отдельного профиля. Если задать прокси в контексте, в одном процессе браузера можно держать несколько независимых сессий с разными адресами. Заодно выставьте язык и часовой пояс под страну прокси.

Node.js: контекст на каждый адрес
const { chromium } = require("playwright");

const proxies = [
  { server: "http://203.0.113.10:8000", username: "login", password: "password" },
  { server: "http://203.0.113.11:8000", username: "login", password: "password" },
];

(async () => {
  const browser = await chromium.launch();
  for (const proxy of proxies) {
    const context = await browser.newContext({
      proxy,
      locale: "de-DE",
      timezoneId: "Europe/Berlin",
    });
    const page = await context.newPage();
    await page.goto("https://api.ipify.org");
    console.log(await page.textContent("body"));
    await context.close();
  }
  await browser.close();
})();

В объекте прокси есть ещё поле bypass: список доменов через запятую, к которым браузер пойдёт напрямую, например localhost,.internal.example. В старых версиях Playwright на Windows для прокси в контексте требовалось задать глобальный прокси при запуске браузера. Если видите такую ошибку, обновите Playwright или передайте в launch прокси-заглушку { server: "http://per-context" }.

Puppeteer

#

Puppeteer управляет Chrome напрямую, поэтому прокси задаётся ключом запуска браузера, а логин и пароль передаются отдельно на каждой вкладке.

Node.js: прокси с авторизацией
const puppeteer = require("puppeteer");

(async () => {
  const browser = await puppeteer.launch({
    args: ["--proxy-server=http://203.0.113.10:8000"],
  });
  const page = await browser.newPage();
  await page.authenticate({ username: "login", password: "password" });
  await page.goto("https://api.ipify.org");
  console.log(await page.evaluate(() => document.body.innerText));
  await browser.close();
})();

Вызывайте page.authenticate() до первого перехода и для каждой новой вкладки. Чтобы в одном браузере работать с разными адресами, создайте контекст с собственным прокси: browser.createBrowserContext({ proxyServer: "http://203.0.113.11:8000" }). В версиях Puppeteer до 22 этот метод назывался createIncognitoBrowserContext.

Пакет proxy-chain

Если авторизация через authenticate неудобна, например страницы открываются сторонним кодом, используйте пакет proxy-chain. Он поднимает локальный прокси без пароля, который пересылает трафик на ваш прокси с авторизацией.

npm install proxy-chain
const puppeteer = require("puppeteer");
const proxyChain = require("proxy-chain");

(async () => {
  const localUrl = await proxyChain.anonymizeProxy("http://login:[email protected]:8000");
  // localUrl вида http://127.0.0.1:45678, без логина и пароля
  const browser = await puppeteer.launch({ args: ["--proxy-server=" + localUrl] });
  const page = await browser.newPage();
  await page.goto("https://api.ipify.org");
  await browser.close();
  await proxyChain.closeAnonymizedProxy(localUrl, true);
})();

Selenium

#

В Selenium прокси задаётся при создании драйвера и действует на весь браузер. Адрес без авторизации передаётся просто:

Python: Chrome
from selenium import webdriver
from selenium.webdriver.common.by import By

options = webdriver.ChromeOptions()
options.add_argument("--proxy-server=http://203.0.113.10:8000")

driver = webdriver.Chrome(options=options)
driver.get("https://api.ipify.org")
print(driver.find_element(By.TAG_NAME, "body").text)
driver.quit()
Python: Firefox с SOCKS5 и DNS через прокси
options = webdriver.FirefoxOptions()
options.set_preference("network.proxy.type", 1)
options.set_preference("network.proxy.socks", "203.0.113.10")
options.set_preference("network.proxy.socks_port", 1080)
options.set_preference("network.proxy.socks_version", 5)
options.set_preference("network.proxy.socks_remote_dns", True)
driver = webdriver.Firefox(options=options)

Логин и пароль в ключе --proxy-server Chrome игнорирует, а окно авторизации прокси Selenium заполнить не может. Рабочие варианты:

  • Привязка по IP. Разрешите доступ к прокси с адреса машины, где работает Selenium, и подключайтесь без пароля. Самый простой и надёжный путь для сервера с постоянным IP. Подробнее в статье логин или привязка по IP.
  • Локальный пересыльщик. Утилита вроде gost слушает порт на 127.0.0.1 без пароля и передаёт трафик на прокси с авторизацией. Работает и для SOCKS5.
  • selenium-wire. Популярная библиотека с поддержкой авторизации, но проект больше не развивается, поэтому для новых проектов лучше первые два варианта.
gost: локальный прокси без пароля
gost -L http://127.0.0.1:8080 -F http://login:[email protected]:8000

# в Selenium
options.add_argument("--proxy-server=http://127.0.0.1:8080")

Ротация адресов в браузерной автоматизации

#

В HTTP-клиенте каждый запрос можно отправить через свой прокси. В браузере так не получится: страница грузит десятки ресурсов, держит соединения открытыми, и сайт ожидает, что вся сессия идёт с одного адреса. Поэтому единица ротации в браузере - контекст или экземпляр браузера, а не запрос.

Утечки и согласованность профиля

#

Управляемый браузер - всё тот же браузер, и у него те же утечки. Проверьте три вещи при первом запуске:

  • WebRTC. Chrome может отправить UDP-запрос к STUN-серверу мимо прокси. Ключ запуска --force-webrtc-ip-handling-policy=disable_non_proxied_udp запрещает такой трафик.
  • Часовой пояс и язык. В Playwright это timezoneId и locale контекста, в Puppeteer page.emulateTimezone("Europe/Berlin"), в Selenium с Chrome команда CDP Emulation.setTimezoneOverride.
  • DNS при SOCKS5. Chromium разрешает имена через SOCKS5-прокси сам, а в Firefox нужна настройка network.proxy.socks_remote_dns, как в примере выше.

Как найти утечку за пять минут, рассказано в статье утечки WebRTC и DNS.

Ошибки и практические советы

#
СимптомПричинаРешение
ERR_PROXY_CONNECTION_FAILEDНеверный адрес или порт, прокси не активенСверьте данные с выдачей, проверьте прокси через curl
ERR_TUNNEL_CONNECTION_FAILEDПрокси отказал в туннеле, чаще всего из-за авторизацииПроверьте логин и пароль или привязку по IP
Окно ввода пароля в браузереАвторизация не переданаPlaywright: поля username и password; Puppeteer: authenticate
Browser does not support socks5 proxy authenticationSOCKS5 с паролем в ChromiumHTTP(S)-прокси, привязка по IP или пересыльщик
Таймаут на gotoМедленный прокси или тяжёлая страницаУвеличьте таймаут перехода, ждите domcontentloaded, а не полной загрузки
  • Проверяйте адреса до запуска. Короткий скрипт, который открывает api.ipify.org через каждый прокси, экономит часы отладки. Подробнее в статье как проверить прокси.
  • Блокируйте лишнее. Картинки, шрифты и видео расходуют трафик резидентских прокси. В Playwright их можно отсечь через page.route, в Puppeteer через перехват запросов.
  • Не храните пароли в коде. Читайте данные прокси из переменных окружения или файла, исключённого из репозитория.
  • Соблюдайте правила сайтов. Умеренный темп и паузы между действиями нужны не только для стабильности, но и чтобы не создавать лишнюю нагрузку.

Для HTTP-запросов без браузера примеры собраны в статьях прокси в Python и прокси в curl, wget и Node.js. Сценарии сбора данных описаны на странице прокси для парсинга, а все типы адресов в каталоге.

Вопросы и ответы

Как передать логин и пароль прокси в Selenium?

Встроенного способа для Chrome нет. Используйте привязку прокси по IP, локальный пересыльщик без пароля, например gost, или библиотеку selenium-wire, учитывая, что она больше не развивается.

Можно ли в Playwright использовать разные прокси в одном браузере?

Да. Передайте параметр proxy в browser.new_context (в Node.js browser.newContext): у каждого контекста будут свои адрес, cookies и хранилище.

Почему SOCKS5 с паролем не работает в Puppeteer и Playwright?

Chromium не поддерживает авторизацию на SOCKS-прокси. Возьмите HTTP(S)-прокси, настройте привязку по IP или поднимите локальный пересыльщик без пароля.

Какие прокси лучше для браузерной автоматизации?

Статические IPv4 или ISP, если важна постоянная сессия, и резидентские в режиме липкой сессии, если нужно много разных адресов. Ротация на каждый запрос для браузера не подходит.

Редакция TrueSocks

Гайды и разборы о прокси

Статьи пишет команда TrueSocks: те, кто собирает каталог прокси и отвечает в поддержке. Нашли неточность или устаревший шаг? Напишите нам в Telegram, поправим.

На посадку

Прокси для этой задачи

Цена «от» за единицу на базовый срок, страны и скидка за объём видны на странице товара.

  • #Selenium
  • #Playwright
  • #Puppeteer
  • #автоматизация
  • #парсинг
Поделиться

Прокси предоставляются для законных задач. Спам, мошенничество и взлом запрещены, соблюдайте правила площадок. Правила сервиса

Все статьи