10% off ALL new Proxies – CODE: 10pro

Playwright Proxy Setup: Route via German Mobile IPs

Playwright Proxy Setup: Route via German Mobile IPs

The One Thing Most Playwright Proxy Guides Get Wrong

Guides written for Puppeteer teach a two-step dance: host and port in the launch args, credentials in a separate page.authenticate call. People carry that habit into Playwright — and either add an authenticate call that Playwright doesn't have, or embed user:pass in a URL that gets ignored.

Playwright is simpler. It takes the server, username, and password together in one proxy object:

chromium.launch({ proxy: { server: 'http://PROXY_HOST:PORT', username: 'USER', password: 'PASS' } });

That's the whole authentication step. No page.authenticate, no header injection, no credential parsing. Playwright reads the credentials from the object and hands them to the browser for you.

With a dedicated German mobile endpoint you also skip the per-request rotation middleware that pool-based guides bolt on — you point the browser at one endpoint and rotate on demand at the proxy when you choose to.


Before You Start

You need four values from your GermanProxy.io account:

  • Host and port of your endpoint
  • Username and password

The examples use PROXY_HOST, PORT, USER and PASS as placeholders — replace them with your own. You'll also need Playwright installed. For Node:

npm install playwright

For Python:

pip install playwright
python -m playwright install chromium

Step 1 — Launch Chromium Through the Proxy (Node)

This is the complete, runnable pattern. Server, username, and password all go in the proxy object:

const { chromium } = require("playwright");

// From your GermanProxy.io account
const PROXY_HOST = "PROXY_HOST";
const PORT = "PORT";
const USER = "USER";
const PASS = "PASS";

(async () => {
  const browser = await chromium.launch({
    proxy: {
      server: `http://${PROXY_HOST}:${PORT}`,
      username: USER,
      password: PASS,
    },
  });

  const page = await browser.newPage();
  await page.goto("https://www.example.de", { waitUntil: "domcontentloaded" });
  console.log("Title:", await page.title());

  await browser.close();
})();

Every request from page — HTML, XHR, fetch, images — now travels over your German mobile IP. No pool middleware, no extra dependency, no separate auth step.


Step 2 — The Same Setup in Python

The proxy object is identical; only the syntax around it changes:

from playwright.sync_api import sync_playwright

PROXY_HOST = "PROXY_HOST"
PORT = "PORT"
USER = "USER"
PASS = "PASS"

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server": f"http://{PROXY_HOST}:{PORT}",
            "username": USER,
            "password": PASS,
        }
    )
    page = browser.new_page()
    page.goto("https://www.example.de", wait_until="domcontentloaded")
    print("Title:", page.title())
    browser.close()

Same four values, same one-object auth. Playwright's proxy API is consistent across languages.


Step 3 — Per-Browser vs. Per-Context

You can set the proxy at two levels, and it's worth knowing which you want:

  • Per browser (launch): every context and page in that browser uses the proxy. This is the pattern above and the right default for a single dedicated endpoint.
  • Per context (newContext): scope the proxy to one context. Launch with proxy: { server: 'per-context' }, then give each context its own — useful when you run several isolated sessions in one browser.
const browser = await chromium.launch({ proxy: { server: "per-context" } });

const context = await browser.newContext({
  proxy: {
    server: `http://${PROXY_HOST}:${PORT}`,
    username: USER,
    password: PASS,
  },
});

const page = await context.newPage();

With one dedicated German endpoint the launch-level form is simplest. The per-context form matters when you keep several independent flows open at once.


Step 4 — Verify the IP Before You Scale

Confirm you're actually on a German mobile IP before you build anything on top of it. Point the same page at an IP-echo endpoint and read the result:

await page.goto("https://api.ipify.org?format=json", {
  waitUntil: "domcontentloaded",
});
const ip = await page.evaluate(() => document.body.innerText);
console.log("Egress IP:", ip);

If it returns your own address, re-check that the proxy object reached launch (or newContext) and that the server, username and password are all present. For a fuller checklist, see checking your proxy configuration. A persistent 407 Proxy Authentication Required points at the credentials — see how to fix 407 proxy authentication required.


Step 5 — Check for WebRTC and DNS Leaks

A proxy routes Chromium's HTTP traffic, but the browser has two side channels that can expose your real address:

  • WebRTC can surface your local IP via ICE candidates even with a proxy set — see what a WebRTC leak is.
  • DNS can resolve names outside the tunnel depending on configuration — see what a DNS leak is.

For data-collection work in headless mode WebRTC is usually inert, but verify it for any flow where IP consistency matters. A real German mobile IP only helps if nothing else leaks past it.


HTTP vs. SOCKS5 in Playwright

Both protocols come with your endpoint. Which to put in server depends on what you need:

Aspect HTTP endpoint SOCKS5 endpoint
Server value http://HOST:PORT socks5://HOST:PORT
Username/password auth in Chromium Yes, via the proxy object No — Chromium has no SOCKS5 user/pass auth
Best auth mode Credentials IP allowlist
Typical use Default for most scraping Lower-level / non-HTTP traffic

For most Playwright scraping, the HTTP endpoint with credentials in the proxy object is the simplest path. Playwright accepts socks5:// in server, but because the underlying Chromium can't authenticate a SOCKS5 proxy with a username and password, reach for SOCKS5 only when you specifically need it and can use IP-allowlist authentication. Background: SOCKS5 vs HTTP proxy.


Sticky Sessions vs. Rotation

With a dedicated German endpoint you control the IP at the proxy, not in your code:

  • Sticky session: keep one browser (or one newContext()) open across a multi-step flow — login, navigate, paginate — and the German mobile IP stays the same.
  • Rotation on demand: when you want a fresh IP, trigger rotation at the proxy and open a new context. There's no per-request IP pool to manage in Playwright.

This is why a dedicated endpoint keeps the code small: no rotation list, no health-checking, no retry-on-dead-IP loop. See sticky sessions and IP rotation explained and dedicated vs shared mobile proxy.


Why a Mobile IP for Playwright at All

Playwright is a common choice for JavaScript-heavy pages that a plain HTTP client can't render — product pages, SERPs, dashboards. The catch is the egress IP: datacenter ranges are widely distrusted, so even a perfectly behaved crawler can hit friction. A real German mobile IP rides on carrier-grade NAT (CGNAT), the same shared-IP space thousands of ordinary phone users sit behind, which is why it carries higher IP reputation on German platforms.

For the trade-offs against other IP types, see mobile vs residential vs datacenter proxy and what is a mobile proxy.


Scrape Responsibly

A mobile proxy improves reliability for legitimate data collection — it is not a tool to circumvent access controls or platform rules. Keep your Playwright crawl clean and defensible:

  1. Respect each site's terms and its robots.txt; collect only public data you're permitted to use.
  2. Throttle with realistic delays between navigations so you don't overload servers — headless browsers are heavier than a plain HTTP client.
  3. Collect only what you need, and handle any personal data in line with the GDPR. See the EU legal view on web scraping.
  4. Be honest about who you are — don't impersonate a service or misuse a target's security mechanisms.

Whether mobile proxies themselves are lawful to use: are mobile proxies legal.


FAQ

How do I set a proxy in Playwright?

Pass it in the launch (or context) options: chromium.launch({ proxy: { server: 'http://PROXY_HOST:PORT', username: 'USER', password: 'PASS' } }). Playwright reads the credentials from that object directly, so — unlike Puppeteer — you do not need a separate authenticate call.

Does Playwright need a separate authenticate call like Puppeteer?

No. Puppeteer splits host and port (launch args) from credentials (page.authenticate). Playwright takes server, username and password together in one proxy object, so a single launch or newContext call is enough for authenticated proxies. If you're coming from Puppeteer, compare the Puppeteer setup.

Can I set a different proxy per browser context in Playwright?

Yes. Pass proxy to browser.newContext({ proxy: { server, username, password } }) to scope it to one context. Launch the browser with proxy: { server: 'per-context' } if you want each context to define its own — one browser, isolated sessions.

Can Playwright use a SOCKS5 mobile proxy?

Yes, via server: 'socks5://PROXY_HOST:PORT'. But Chromium — which Playwright drives — cannot do SOCKS5 username/password auth, so SOCKS5 works best with IP-allowlist authentication. For credential auth, use the HTTP endpoint. See HTTP vs SOCKS5 proxies.

Should I check for WebRTC and DNS leaks with Playwright?

Yes. The proxy routes HTTP traffic, but WebRTC can expose your real IP and DNS can resolve outside the tunnel. Verify both before you rely on the setup — see what a WebRTC leak is and what a DNS leak is.

Playwright or Puppeteer for a mobile proxy?

Both work. Playwright takes credentials directly in its proxy option; Puppeteer splits host/port (launch args) from credentials (page.authenticate). If you're choosing, compare the Puppeteer setup and the Selenium setup.


CTA

Drive Playwright on real German mobile IPs. Start with a German mobile proxy — HTTP/SOCKS5/OpenVPN, sticky sessions, on-demand rotation, fair-use 20 GB/day, from a transparent EU provider.


Get a German mobile proxy: Real 4G/5G IPs from Germany, fair-use 20 GB/day — compare German mobile proxy plans or start with a dedicated 5G proxy.

Telegram Support
Nach oben scrollen