Konfiguracja proxy w Puppeteer: Flagi, autoryzacja, rotacja i rzeczywistość
Flaga uruchomienia jest prosta; 407, które następuje potem, to miejsce, gdzie większość konfiguracji proxy w Puppeteer upada. Oto pełny wzorzec — page.authenticate, rotacja kontekstów, proxy-chain — i prawda o proxy na stronę oraz wykrywaniu trybu headless.
Konfiguracja proxy w Puppeteer zaczyna się od jednej flagi uruchomienia i dla większości osób kończy się krok później na ścianie: proxy odpowiada 407 Proxy Authentication Required, ponieważ --proxy-server nie ma sposobu na przekazanie poświadczeń. Rozwiązanie jest wbudowane — page.authenticate() — ale wokół niego znajduje się pole minowe z półdziałającymi poradami: pakiety npm, które cicho przekierowują twój ruch przez Node.js, schematy SOCKS, których Chromium nie autoryzuje, oraz obejście localhost, które sprawia, że działające proxy wyglądają na martwe. Ten przewodnik przeprowadza przez konfigurację, która sprawdza się w produkcji: flagi, autoryzacja, rotacja z kontekstami przeglądarki, proxy-chain dla niezręcznych przypadków i uczciwa sekcja o wykrywaniu trybu headless.
Konfiguracja proxy w Puppeteer: podstawowy wzorzec
Proxy to argument uruchomienia Chromium, więc dotyczy całej przeglądarki. Poświadczenia przechodzą przez page.authenticate(), które odpowiada na wyzwanie 407 proxy za pomocą protokołu DevTools — wywołaj to przed jakąkolwiek nawigacją:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
args: ['--proxy-server=http://gate.quantumproxies.io:PORT'],
});
const page = await browser.newPage();
await page.authenticate({ username: 'USER', password: 'PASS' });
await page.goto('https://httpbin.org/ip', { waitUntil: 'domcontentloaded' });
console.log(await page.evaluate(() => document.body.innerText)); // exit IP
await browser.close();
})();
Cztery szczegóły oszczędzają godziny debugowania:
- Twórz flagę za pomocą szablonu literału lub konkatenacji, a nie zwykłych cudzysłowów. Klasyczny błąd z Stack Overflow:
"--proxy-server =..."w podwójnych cudzysłowach z miejscem na interpolację nigdy nie zastępuje zmiennej — a zbędna spacja również psuje parsowanie. - Uwzględnij schemat.
--proxy-server=socks5://host:portdla SOCKS, w przeciwnym razie Chromium zakłada HTTP. - Nie osadzaj
user:pass@w fladze. Chromium to ignoruje; tylkopage.authenticate()(lub biała lista IP) autoryzuje. - Localhost omija proxy. Chromium pomija proxy dla adresów loopback — zagadka udokumentowana w problemie Puppeteer #3711. Dodaj
--proxy-bypass-list=<-loopback>, jeśli naprawdę musisz proxyfikować lokalny ruch; w przeciwnym razie po prostu testuj na zewnętrznym URL.

Rotacja proxy z kontekstami przeglądarki
Ponowne uruchamianie Chrome dla każdego IP kosztuje sekundy i setki MB za każdym razem. Konteksty przeglądarki to naprawiają: od wersji Puppeteer v22 API to browser.createBrowserContext() (zastępując stary wariant incognito), akceptuje opcję proxyServer, a kontekst tworzony jest w milisekundach z własnymi ciasteczkami i pamięcią:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const jobs = ['https://example.com/a', 'https://example.com/b'];
for (const url of jobs) {
const context = await browser.createBrowserContext({
proxyServer: 'http://gate.quantumproxies.io:PORT',
});
const page = await context.newPage();
await page.authenticate({ username: 'USER', password: 'PASS' });
try {
await page.goto(url, { timeout: 30000 });
// ...extract...
} finally {
await context.close();
}
}
await browser.close();
})();
Przeciwko rotującej bramie, każdy kontekst naturalnie wychodzi z innego adresu w puli — z rotującymi proxy rezydencjalnymi to 90M+ IP w ponad 200 krajach za jednym nazwą hosta, a parametr nazwy użytkownika sesji przyklejonej przypina wyjście, gdy przepływ wielostronicowy potrzebuje ciągłości. To ta sama architektura kontekstu na zadanie, którą polecamy dla Playwright; Puppeteer po prostu wyraźnie określa krok autoryzacji.
Dwa nawyki utrzymują rotację uczciwą. Loguj wyjściowy IP na kontekst podczas rozwoju — uderz w punkt końcowy IP-echo na początku kontekstu i przechowuj go z twoimi zeskrobanymi wierszami, więc gdy cel zaczyna cię miękko blokować, możesz powiedzieć, czy winny jest jeden wyjście czy jeden odcisk palca. I ograniczaj swoją współbieżność: każdy kontekst jest tani, ale każda otwarta strona nadal trzyma pamięć renderera, więc semafor wokół tworzenia kontekstu bije nieograniczoną pętlę, gdy lista zadań rośnie do tysięcy URL.
proxy-chain: lokalny most dla niezręcznej autoryzacji
Dwa przypadki łamią wzorzec flaga-plus-authenticate: autoryzowane SOCKS5 (Chromium nie ma w ogóle wsparcia dla poświadczeń SOCKS) i narzędzia, które akceptują tylko goły URL proxy bez kroku autoryzacji. Pakiet npm proxy-chain rozwiązuje oba, uruchamiając lokalne, bezpoświadczeniowe proxy, które przekazuje do twojego autoryzowanego upstream:
const puppeteer = require('puppeteer');
const proxyChain = require('proxy-chain');
(async () => {
const upstream = 'http://USER:PASS@gate.quantumproxies.io:PORT';
const localUrl = await proxyChain.anonymizeProxy(upstream);
// localUrl is something like http://127.0.0.1:54321 — no credentials needed
const browser = await puppeteer.launch({
args: ['--proxy-server=' + localUrl],
});
const page = await browser.newPage();
await page.goto('https://httpbin.org/ip');
await browser.close();
await proxyChain.closeAnonymizedProxy(localUrl, true);
})();
Co najważniejsze, żądania strony nadal wychodzą z samego Chrome — proxy-chain tylko przekazuje bajty, więc twój odcisk palca TLS pozostaje prawdziwym przeglądarki. To rozróżnienie to następna sekcja.
Proxy na stronę: uczciwa odpowiedź
Puppeteer nie ma natywnego proxy na stronę, a popularne obejścia — puppeteer-page-proxy, puppeteer-proxy — przechwytują każde żądanie i ponownie je wydają z Node.js za pomocą biblioteki HTTP, a następnie przekazują odpowiedź z powrotem do przeglądarki. Trzy konsekwencje: cel teraz widzi handshake TLS Node zamiast Chrome, co JA3/JA4 fingerprinting natychmiast oznacza na chronionych stronach; każde żądanie płaci podróż w obie strony przez Node; a oba pakiety są w praktyce nieutrzymywane, z instalacją zepsutą od razu zgodnie z ich własnymi śledzeniami problemów. Jeśli potrzebujesz różnych IP dla różnych stron, użyj jednego kontekstu na proxy jak powyżej — ten sam efekt, prawdziwy ruch Chrome, wspierane API.

Rzeczywistość wykrywania trybu headless
Proxy naprawia warstwę sieciową; nie może sprawić, by headless Chrome stał się niewidzialny. Stary tryb headless ogłaszał się tokenem User-Agent HeadlessChrome; nowy tryb headless (domyślny w Puppeteer od wersji v22) dzieli architekturę prawdziwej przeglądarki i zamyka wiele z tej luki, ale detektory nadal badają navigator.webdriver, efekty uboczne CDP i dziwactwa renderowania — a wtyczki stealth łatają wczorajsze kontrole, nie jutrzejsze. Uporządkuj swoje poprawki według zwrotu z wysiłku: czysty rezydencjalny IP najpierw, ponieważ reputacja to najtańszy filtr dla stron do uruchomienia i ten, którego twój kod nie może sfałszować; rozsądne nagłówki i tempo jako drugie (nasz przewodnik o unikanie CAPTCHA obejmuje sygnały wyzwalające); a gdy wzmocniony cel nadal wygrywa, przekieruj tę domenę przez Scraper API, które obsługuje renderowanie, odciski palców i ponowne próby i zwraca czysty HTML, markdown lub JSON — jedno wywołanie HTTP zamiast floty załatanych przeglądarek.
Często zadawane pytania
Jak autoryzować proxy w Puppeteer?
Ustaw adres za pomocą args: ['--proxy-server=http://host:port'] przy uruchomieniu, a następnie wywołaj await page.authenticate({ username, password }) na każdej stronie przed nawigacją. Poświadczenia osadzone w URL flagi są ignorowane przez Chromium. Dla SOCKS5 z autoryzacją, mostkuj przez proxy-chain, ponieważ Chromium nie może wysyłać poświadczeń SOCKS.
Czy Puppeteer może używać innego proxy na stronę?
Nie natywnie — flaga uruchomienia dotyczy całej przeglądarki. Wspierany odpowiednik to jeden kontekst przeglądarki na proxy za pomocą browser.createBrowserContext({ proxyServer }), z stronami wewnątrz każdego kontekstu. Pakiety, które obiecują prawdziwe proxy na stronę, przekierowują żądania przez Node.js, zmieniając twój odcisk palca TLS i zostając oznaczonym przez poważne systemy anty-botowe.
Czy Puppeteer obsługuje proxy SOCKS5?
Tak dla nieautoryzowanych punktów końcowych: przekaż --proxy-server=socks5://host:port. Autoryzowane SOCKS5 nie działa, ponieważ Chromium nie ma mechanizmu poświadczeń SOCKS, a page.authenticate() odpowiada tylko na wyzwania HTTP 407. Obejścia: użyj portu HTTP bramy z autoryzacją, dodaj swoją IP do białej listy, lub uruchom proxy-chain jako lokalny most.
Jak rotować proxy w Puppeteer?
Utwórz nowy kontekst przeglądarki na zadanie za pomocą createBrowserContext({ proxyServer }) i skieruj go na rotującą bramę — każdy kontekst wtedy wychodzi z nowego IP automatycznie, bez potrzeby zarządzania listą proxy. Ponowne uruchamianie całej przeglądarki dla każdego IP również działa, ale kosztuje sekundy i setki MB RAM na rotację.
Dlaczego moje proxy w Puppeteer nie działa dla localhost?
Chromium omija proxy dla adresów loopback z założenia, więc żądania do localhost lub 127.0.0.1 idą bezpośrednio — zachowanie, które zaskoczyło wystarczająco wiele osób, by stać się numerowanym problemem Puppeteer. Dodaj --proxy-bypass-list=<-loopback>, aby wymusić proxyfikację, lub po prostu zweryfikuj swoje proxy na zewnętrznym punkcie końcowym IP-echo.
Trwały wzorzec jest mały: flaga dla adresu, page.authenticate() dla poświadczeń, konteksty dla rotacji, proxy-chain dla przypadków brzegowych — i sceptycyzm dla każdego pakietu, który przenosi twoje żądania poza przeglądarkę. Daj tej stosowi czyste wyjścia rezydencjalne, a Puppeteer pozostaje nudny, co jest najwyższym komplementem, jaki infrastruktura może otrzymać.