Browser-Automatisierungs-Frameworks akzeptieren alle einen Proxy als Startoption, aber authentifizierte Proxys erfordern eine spezielle Behandlung, da Chromium user:pass@ in einer Proxy-URL nicht akzeptiert: Playwright nimmt Anmeldedaten als separate Felder entgegen (und kann pro Browser-Kontext einen anderen Proxy setzen), Puppeteer benötigt page.authenticate(), und Selenium benötigt eine Erweiterung oder einen lokalen Weiterleitungs-Proxy. Dieser Leitfaden liefert funktionierenden Code für jedes Framework und behandelt dann den Teil, der wichtiger ist als die Syntax: Ein Headless-Browser hinter einer Residential-IP ist weiterhin identifizierbar, es sei denn, der Rest seiner Geschichte passt.
Die eine Tatsache, die alles prägt: Chromium ignoriert Proxy-Anmeldedaten in der URL
Kommandozeilen-Tools und Python-Bibliotheken akzeptieren problemlos http://user:pass@host:port. Chromiums --proxy-server-Flag akzeptiert nur host:port (mit optionalem Schema); darin enthaltene Anmeldedaten werden stillschweigend verworfen. Wenn der Proxy mit 407 antwortet, zeigt der Browser einen Authentifizierungsdialog an – den kein Automatisierungsskript beobachtet. Daher hat jedes Framework seine eigene Methode, um Benutzername und Passwort bereitzustellen, und hierher kommen die meisten Probleme mit „Proxy funktioniert in curl, aber nicht in meinem Browser-Skript“. Firefox ist in einigen Pfaden nachsichtiger, aber die frameworkspezifischen Mechanismen unten funktionieren über alle Engines hinweg.
Playwright
Playwright bietet erstklassige Proxy-Unterstützung mit separaten Anmeldefeldern und – die Funktion, die es zur besten Wahl für Multi-Identitäts-Arbeit macht – der Proxy kann pro Browser-Kontext festgelegt werden, sodass ein Browser-Prozess mehrere isolierte Sitzungen hosten kann, die jeweils über eine andere IP ausgehen.
Python
from playwright.sync_api import sync_playwright
PROXY = {"server": "http://proxy.example.com:8080",
"username": "user", "password": "pass"}
with sync_playwright() as p:
# Option A: ein Proxy für den gesamten Browser
browser = p.chromium.launch(proxy=PROXY)
page = browser.new_page()
page.goto("https://api.ipify.org?format=json")
print(page.text_content("body"))
browser.close()
# Option B: unterschiedlicher Proxy pro Kontext (ein Browser, viele Identitäten)
browser = p.chromium.launch(proxy={"server": "per-context"}) # Platzhalter; echte Proxys kommen aus Kontexten
ctx_de = browser.new_context(proxy={"server": "http://gate.provider.com:7777",
"username": "customer-country-de-session-a1", "password": "pass"},
locale="de-DE", timezone_id="Europe/Berlin")
ctx_us = browser.new_context(proxy={"server": "http://gate.provider.com:7777",
"username": "customer-country-us-session-b2", "password": "pass"},
locale="en-US", timezone_id="America/New_York")
for ctx in (ctx_de, ctx_us):
pg = ctx.new_page(); pg.goto("https://api.ipify.org?format=json"); print(pg.text_content("body"))
browser.close()
Zwei Details. Pro-Kontext-Proxys in Chromium erfordern, dass der Browser mit einer Proxy-Option gestartet wurde (beliebiger Wert – der dokumentierte Platzhalter ist {"server": "per-context"}); ohne diese können Kontexte keine Überschreibung vornehmen. Beachten Sie auch locale und timezone_id, die zusammen mit dem Proxy gesetzt werden: Eine deutsche IP mit einer amerikanischen Zeitzone ist ein Widerspruch, den Anti-Bot-Systeme gewichten, wie in Wie Anti-Bot-Systeme funktionieren erklärt wird. SOCKS5-Proxys werden unterstützt ("server": "socks5://host:1080"), aber Chromium sendet keine Anmeldedaten an SOCKS-Proxys, verwenden Sie daher IP-Whitelist-Authentifizierung mit SOCKS.
Node.js
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ proxy: { server: 'per-context' } });
const context = await browser.newContext({
proxy: { server: 'http://gate.provider.com:7777',
username: 'customer-country-de-session-a1', password: 'pass' },
locale: 'de-DE', timezoneId: 'Europe/Berlin',
});
const page = await context.newPage();
await page.goto('https://api.ipify.org?format=json');
console.log(await page.textContent('body'));
await browser.close();
})();
Playwrights bypass-Feld ("bypass": "localhost,*.internal") schließt Hosts vom Proxy aus, und launch_persistent_context() akzeptiert dieselbe proxy-Option, wenn Sie ein persistentes Profilverzeichnis benötigen.
Puppeteer
Puppeteer übergibt den Proxy als Chromium-Flag und authentifiziert sich pro Seite:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
args: ['--proxy-server=http://proxy.example.com:8080'],
});
const page = await browser.newPage();
await page.authenticate({ username: 'user', password: 'pass' }); // beantwortet die 407 für diese Seite
await page.goto('https://api.ipify.org?format=json');
console.log(await page.evaluate(() => document.body.innerText));
await browser.close();
})();
page.authenticate() muss vor der Navigation und auf jeder Seite (Tab) aufgerufen werden, die den Proxy verwenden wird. Der Proxy ist browserweit – Puppeteer hat keine Pro-Kontext-Proxy-Einstellung wie Playwright. Für mehrere Identitäten haben Sie drei Optionen: mehrere Browser-Prozesse starten (je ein Proxy; schwergewichtig, aber einfach), --proxy-server auf einen lokalen Umschalt-Proxy zeigen lassen, der nach einem Marker routet, oder zu Playwright wechseln. Ebenfalls nützlich: --proxy-bypass-list=<-loopback>, wenn auch localhost über den Proxy laufen soll, und puppeteer-extra mit seinem Proxy-Plugin, das die Authentifizierung übernimmt und pro Seite rotieren kann.
Selenium
Selenium setzt den Proxy über Browser-Optionen. Nicht authentifizierte (IP-Whitelist-)Proxys sind eine Zeile; authentifizierte sind der schwierige Fall.
Chrome, Whitelist-Auth
from selenium import webdriver
opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://proxy.example.com:8080")
driver = webdriver.Chrome(options=opts)
driver.get("https://api.ipify.org?format=json")
print(driver.find_element("tag name", "body").text)
driver.quit()
Chrome, Benutzername/Passwort
Das WebDriver-Protokoll von Selenium bietet keinen Hook, um auf die 407 des Proxys zu antworten. Die üblichen Workarounds:
- Selenium Wire (Python): eine Selenium-Erweiterung, die den Datenverkehr über einen eigenen lokalen Proxy leitet und authentifizierte Upstreams unterstützt:
Beachten Sie, dass Selenium Wire nicht mehr aktiv gepflegt wird; es funktioniert für viele weiterhin mit aktuellem Chrome, aber behandeln Sie es als Übergangslösung.from seleniumwire import webdriver # pip install selenium-wire opts = {"proxy": {"http": "http://user:pass@proxy.example.com:8080", "https": "http://user:pass@proxy.example.com:8080"}} driver = webdriver.Chrome(seleniumwire_options=opts) - Eine generierte Chrome-Erweiterung, die den Proxy über
chrome.proxysetzt undonAuthRequiredmit den Anmeldedaten beantwortet – ein bekanntes Muster; die Erweiterung besteht aus einem Manifest und ein paar Zeilen Hintergrundskript, geladen mitopts.add_extension(...). Funktioniert im Headless-Modus mit älterem Chrome nicht (Erweiterungen wurden dort nicht unterstützt); funktioniert im aktuellen headless=new. - Ein lokaler Weiterleitungs-Proxy auf
127.0.0.1, der die Anmeldedaten hält und an den Upstream weiterleitet; richten Sie Chrome ohne Authentifizierung darauf aus. Framework-agnostisch und robust. - Whitelist-Authentifizierung vom Anbieter, wenn Ihr Rechner eine statische IP hat – umgeht das Problem vollständig.
Firefox
opts = webdriver.FirefoxOptions()
opts.set_preference("network.proxy.type", 1)
opts.set_preference("network.proxy.http", "proxy.example.com"); opts.set_preference("network.proxy.http_port", 8080)
opts.set_preference("network.proxy.ssl", "proxy.example.com"); opts.set_preference("network.proxy.ssl_port", 8080)
opts.set_preference("network.proxy.socks_remote_dns", True) # Remote-DNS, wenn SOCKS verwendet wird
driver = webdriver.Firefox(options=opts)
Firefox zeigt bei Benutzername/Passwort-Proxys weiterhin einen Auth-Dialog; die Ansätze mit lokalem Weiterleitungs-Proxy oder Whitelist gelten.
Was der Proxy in einem Headless-Browser nicht behebt
Ein echter Browser bringt Sie an TLS- und HTTP/2-Fingerprinting vorbei – der Handshake ist wirklich der von Chrome (siehe TLS-Fingerprinting). Er bringt Sie jedoch nicht von selbst an der JavaScript-Ebene vorbei:
navigator.webdriverist unter Automatisierungtrue; Websites prüfen dies zuerst.- Der Headless-Modus weist Rendering- und API-Unterschiede auf (fehlende Plugins, spezifische WebGL-Renderer-Strings, Fenstergrößen), die Fingerprinting-Skripte testen. Das neuere Headless von Chrome (
headless=new) ist dem beheaded Modus viel ähnlicher, aber nicht identisch. - WebRTC kann weiterhin die echte IP des Rechners preisgeben, sofern nicht deaktiviert oder gespooft; ein Proxy berührt dies nicht. Testen Sie es – So testen Sie einen Proxy.
- Zeitzone, Locale und Geolokalisierung stammen vom Rechner, sofern Sie sie nicht setzen (Playwright:
timezone_id,locale,geolocation); eine Diskrepanz zum Land des Proxys ist ein klassisches Erkennungsmerkmal. - Verhalten: sofortige Navigationen, keine Mausbewegungen, identisches Timing bei jedem Lauf.
Stealth-Plugins (puppeteer-extra-plugin-stealth, playwright-stealth) patchen die offensichtlichsten Artefakte; Antidetect-Browser gehen weiter, indem sie ein kohärentes Fingerprinting pro Profil bereitstellen und einen Debugging-Port freigeben, an den sich Ihr Playwright-/Puppeteer-Skript anhängt – das ist die Produktionsantwort für Kontenarbeit. Siehe Was ist ein Antidetect-Browser und, für die Wahl des IP-Typs hinter jedem Profil, unser Antidetect-Proxy-Ranking.
Framework-Wahl für Proxy-Arbeit
| Playwright | Puppeteer | Selenium | |
|---|---|---|---|
| Authentifizierter Proxy | Nativ (username/password-Felder) | page.authenticate() pro Seite | Workaround erforderlich (Wire, Erweiterung, lokaler Weiterleitungs-Proxy) |
| Unterschiedlicher Proxy pro Sitzung | Pro Kontext, ein Browser | Ein Browser pro Proxy | Ein Treiber pro Proxy |
| SOCKS5 | Ja (keine Anmeldedaten → Whitelist) | Über Flag (keine Anmeldedaten) | Über Optionen/Präferenzen |
| Locale / Zeitzone pro Sitzung | Native Kontextoptionen | Emulations-APIs / Flags | Präferenzen / CDP |
| Am besten geeignet für | Multi-Identitäts-Scraping und Tests | Node-zentrierte Chrome-Automatisierung | Legacy-Suiten, Cross-Browser-Grids |
Häufig gestellte Fragen
Wie verwende ich einen authentifizierten Proxy in Playwright?
Übergeben Sie proxy={"server": "http://host:port", "username": "…", "password": "…"} an launch() oder, pro Kontext, an new_context() (starten Sie zuerst mit proxy={"server": "per-context"}).
Wie verwende ich einen Proxy mit Authentifizierung in Puppeteer?
Starten Sie mit args: ['--proxy-server=host:port'] und rufen Sie await page.authenticate({username, password}) vor page.goto() auf jeder Seite auf.
Warum ignoriert Chrome user:pass@ in --proxy-server?
Das Flag von Chromium akzeptiert nur schema://host:port; Anmeldedaten werden nicht geparst. Es antwortet auf die 407 des Proxys mit einem interaktiven Dialog, daher muss die Automatisierung die Anmeldedaten über den Mechanismus des Frameworks bereitstellen.
Kann ich für jeden Tab einen anderen Proxy verwenden?
Nicht pro Tab. Playwright macht es pro Browser-Kontext (jeder Kontext ist eine isolierte Sitzung); Puppeteer und Selenium benötigen eine Browser-Instanz pro Proxy oder einen lokalen Umschalt-Proxy.
Macht ein Proxy Headless-Chrome unerkennbar?
Nein. Er behebt die IP-Ebene und, da es ein echter Browser ist, die TLS-Ebene. Automatisierungs-Flags, Headless-Artefakte, WebRTC, Zeitzonen-Diskrepanz und Verhalten sind separate Signale, die separat behandelt werden müssen.
Sollte der Proxy für Browser-Automatisierung Residential oder Datacenter sein?
Was auch immer die IP-Richtlinie des Ziels erfordert – der Browser ändert diese Rechnung nicht. Datacenter, wo toleriert; Residential oder Mobile auf geschützten Websites; statisch (ISP) für persistente eingeloggte Profile. Siehe den Vergleich der Proxy-Typen.