Skip to content

Instantly share code, notes, and snippets.

@quantumproxies
Created August 21, 2026 12:42
Show Gist options
  • Select an option

  • Save quantumproxies/855f94d35dd438e20d0084827cbfad77 to your computer and use it in GitHub Desktop.

Select an option

Save quantumproxies/855f94d35dd438e20d0084827cbfad77 to your computer and use it in GitHub Desktop.
Playwright per-context proxies in Python — one browser, many countries https://quanticdata.io/blog/how-to-use-playwright-for-scraping/
"""One Playwright browser, a different country per context.
pip install playwright && playwright install chromium
export QD_PROXY_USER=... QD_PROXY_PASS=...
python3 qd_playwright_proxy.py
Two things worth knowing:
1. Setting the proxy on the CONTEXT rather than the browser means one browser process
can hold several exits at once. Launching a browser per country is the expensive
mistake people make here.
2. A proxy hides the exit IP, not the browser. WebRTC can still leak the real local
address, so the args below disable it.
https://quanticdata.io/residential-proxies/
Guides: https://quanticdata.io/blog/how-to-use-playwright-for-scraping/
https://quanticdata.io/blog/playwright-stealth-in-python/
"""
import os
from playwright.sync_api import sync_playwright
GATEWAY = "http://pr.quanticdata.io:7777"
USER = os.environ["QD_PROXY_USER"]
PASS = os.environ["QD_PROXY_PASS"]
COUNTRIES = ["us", "gb", "de", "jp"]
with sync_playwright() as p:
browser = p.chromium.launch(args=[
"--disable-features=WebRtcHideLocalIpsWithMdns",
"--force-webrtc-ip-handling-policy=disable_non_proxied_udp",
])
for country in COUNTRIES:
context = browser.new_context(
proxy={
"server": GATEWAY,
# Targeting goes in the username, exactly as with curl or requests.
"username": f"{USER}-country-{country}",
"password": PASS,
},
locale={"us": "en-US", "gb": "en-GB", "de": "de-DE", "jp": "ja-JP"}[country],
)
page = context.new_page()
page.goto("https://ipinfo.io/json", wait_until="domcontentloaded")
print(f"{country}: {page.inner_text('body')[:120]}")
context.close()
browser.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment