Настройка прокси в Puppeteer: подключение через --proxy-server и page.authenticate
Это руководство объясняет, как подключить HTTP-прокси Socks5Proxy через аргумент --proxy-server и аутентификацию page.authenticate в Puppeteer, подключение SOCKS5 и запуск браузеров с разными IP.
Как работает прокси в Puppeteer?
В Puppeteer прокси настраивается через аргументы при запуске Chrome. Адрес в --proxy-server применяется ко всем страницам браузера. Имя пользователя и пароль для HTTP-прокси нельзя передать через аргументы, поэтому они передаются через page.authenticate после открытия страницы. Тогда Puppeteer автоматически отвечает на запросы аутентификации прокси.
Пример использует IP 198.51.100.23, HTTP-порт 8000, SOCKS5-порт 1080, имя пользователя spx_user, пароль spx_pass.
npm install puppeteerКак подключиться к HTTP-прокси с аутентификацией?
Добавьте --proxy-server=198.51.100.23:8000 в args для launch, а сразу после создания страницы через newPage передайте логин и пароль в page.authenticate. Аутентификацию нужно выполнять для каждой новой страницы.
HTTPS-сайты открываются нормально. Браузер создает CONNECT-туннель для шифрованного обмена.
import puppeteer from "puppeteer";
const browser = await puppeteer.launch({
headless: true,
args: ["--proxy-server=http://198.51.100.23:8000"],
});
const page = await browser.newPage();
await page.authenticate({ username: "spx_user", password: "spx_pass" });
await page.goto("https://api.ipify.org", { waitUntil: "domcontentloaded" });
console.log(await page.evaluate(() => document.body.innerText)); // proxy IP
await browser.close();Как использовать прокси SOCKS5?
Вставьте адрес socks5:// в --proxy-server. Однако Chrome не поддерживает аутентификацию по логину и паролю для SOCKS-прокси, поэтому page.authenticate не применяется к SOCKS5. Для подключения через SOCKS5 используйте IP-авторизацию, зарегистрировав IPv4 сервера, где выполняется этот код, в консоли.
Если требуется подключение с именем пользователя и паролем, проще всего использовать HTTP-порт того же IP. Так как IP одинаковый, местоположение будет выглядеть одинаково для целевого сайта.
import puppeteer from "puppeteer";
const browser = await puppeteer.launch({
args: ["--proxy-server=socks5://198.51.100.23:1080"], // server IP is authorized in the dashboard
});
const page = await browser.newPage();
await page.goto("https://api.ipify.org");
console.log(await page.evaluate(() => document.body.innerText));
await browser.close();Как запустить браузеры с разными IP?
Chrome использует один прокси на запущенный браузер. Для работы с разными IP нужно запускать отдельные браузеры. Код ниже получает список ip:port:user:pass через API и открывает 3 браузера с разными IP, выводя IP каждой страницы.
Множество открытых браузеров потребляет много памяти. Рекомендуется использовать очередь задач и ограничивать количество одновременно запущенных браузеров.
import puppeteer from "puppeteer";
const KEY = "YOUR_API_KEY";
const res = await fetch("https://socks5proxy.io/api/v1/proxies/download?format=ip:port:user:pass&protocol=http", {
headers: { Authorization: "Bearer " + KEY },
});
const lines = (await res.text()).trim().split("\n").slice(0, 3);
await Promise.all(lines.map(async (line) => {
const [ip, port, user, pass] = line.trim().split(":");
const browser = await puppeteer.launch({ args: ["--proxy-server=http://" + ip + ":" + port] });
try {
const page = await browser.newPage();
await page.authenticate({ username: user, password: pass });
await page.goto("https://api.ipify.org", { timeout: 30000 });
console.log(ip, await page.evaluate(() => document.body.innerText));
} finally {
await browser.close();
}
}));Как открывать страницы быстрее?
Через прокси загружаются все ресурсы (изображения, шрифты, видео), что увеличивает трафик. Если нужны только тексты и данные, отключите загрузку медиа через page.setRequestInterception для экономии трафика в общих тарифах.
Параметр waitUntil тоже важен. networkidle0 ждёт завершения всех запросов, что может быть медленно. Лучше использовать page.waitForSelector, чтобы переходить к следующему шагу, как только появятся нужные элементы.
await page.setRequestInterception(true);
page.on("request", (req) => {
const type = req.resourceType();
if (type === "image" || type === "font" || type === "media") req.abort();
else req.continue();
});Можно ли использовать разные IP для каждой страницы в одном браузере?
Параметр --proxy-server в Chrome применяется ко всему браузеру, что затрудняет использование разных IP для разных страниц. Puppeteer 22+ позволяет задавать proxyServer для каждого browser.createBrowserContext, разделяя прокси по контекстам. Контексты также изолируют куки и хранилища, что удобно для работы с аккаунтами.
Страницы, созданные в контексте, также можно аутентифицировать с помощью page.authenticate, передав логин и пароль. Это потребляет меньше памяти, чем запуск нескольких браузеров.
import puppeteer from "puppeteer";
const browser = await puppeteer.launch();
const context = await browser.createBrowserContext({ proxyServer: "http://198.51.100.23:8000" });
const page = await context.newPage();
await page.authenticate({ username: "spx_user", password: "spx_pass" });
await page.goto("https://api.ipify.org");
console.log(await page.evaluate(() => document.body.innerText));
await context.close();
await browser.close();Что нужно настроить, чтобы выглядеть как пользователь из этой страны?
Установите Accept-Language через page.setExtraHTTPHeaders и временную зону через page.emulateTimezone согласно стране IP. Несоответствие может привести к неправильному языку или формату дат.
Размер экрана можно задать через page.setViewport, а для эмуляции мобильных устройств используйте настройки KnownDevices из Puppeteer в page.emulate.
await page.setExtraHTTPHeaders({ "Accept-Language": "ja-JP,ja;q=0.9" });
await page.emulateTimezone("Asia/Tokyo");
await page.setViewport({ width: 1366, height: 900 });Как поддерживать стабильность браузера в длительных задачах?
Для стабильной работы лучше перезапускать браузер после обработки определенного числа страниц, а не держать его открытым долго. Долгая работа увеличивает потребление памяти и риск ошибок.
Обязательно вызывайте page.close в блоке try и finally для каждой страницы, а также добавляйте timeout в goto, чтобы избежать зависания на страницах без ответа. Если задача не удалась, попробуйте снова с другим прокси, запустив новый браузер.
Фиксируйте время ответа и ошибки по каждому прокси, чтобы выявлять медленные IP и обращаться в поддержку или менять настройки задач.
Как исправить частые ошибки?
net::ERR_INVALID_AUTH_CREDENTIALS или 407 означает, что неверны данные в page.authenticate или вызов сделан не после newPage. Убедитесь, что вызываете его перед goto для каждой страницы.
net::ERR_PROXY_CONNECTION_FAILED означает, что неверен адрес или порт. Убедитесь, что используете HTTP-порт для HTTP-адресов и SOCKS5-порт для SOCKS5. Если SOCKS5 отклоняет соединение, проверьте, добавлен ли исходящий IP сервера в список разрешённых для IP-авторизации.