Proxies + AI

Mobile Proxy Setup in Playwright (Python and Node)

October 2026·7 min read·Playwright, Python, Node.js

Playwright has first-class proxy support, so a dedicated 4G/5G mobile proxy is a one-object change. The details that trip people up are which port to use, how authentication works, and how to tell that a page really loaded through the proxy. This guide covers all three, in Python and Node.

In this guide

  1. Your proxy details
  2. Proxy for the whole browser
  3. A different proxy per context
  4. HTTP vs SOCKS5 in Chromium
  5. Verify every run
  6. Timeouts and retries for a mobile link
  7. Example: regional price check

1. Your proxy details

In the RelayKit dashboard, open a proxy card under My Proxies and click 🤖 Use with AI tools → Playwright. The snippets below appear with your host, port, username and password filled in, in both Python and Node, with a copy button. Here they're shown with placeholders:HOST, HTTP port 8000, SOCKS5 port 9000, USER, PASS.

2. Proxy for the whole browser

Pass proxy at launch and every page in that browser uses it.

Python
from playwright.sync_api import sync_playwright # pip install playwright && playwright install chromium with sync_playwright() as p: browser = p.chromium.launch( proxy={"server": "http://HOST:8000", "username": "USER", "password": "PASS"} ) page = browser.new_page() page.goto("https://api.ipify.org?format=json", timeout=45_000) print(page.inner_text("body")) # must show the proxy's IP browser.close()
Node
const { chromium } = require('playwright'); // npm i playwright && npx playwright install chromium (async () => { const browser = await chromium.launch({ proxy: { server: 'http://HOST:8000', username: 'USER', password: 'PASS' }, }); const page = await browser.newPage(); await page.goto('https://api.ipify.org?format=json', { timeout: 45_000 }); console.log(await page.textContent('body')); // must show the proxy's IP await browser.close(); })();

3. A different proxy per context

If you run several proxies in one script (say, one per city you bought a proxy in), launch once and set the proxy on each BrowserContext. Chromium needs a launch-level proxy for per-context proxies to work; a placeholder is fine.

Python — one context per proxy
PROXIES = [ {"server": "http://HOST_A:8000", "username": "USER_A", "password": "PASS_A"}, {"server": "http://HOST_B:8000", "username": "USER_B", "password": "PASS_B"}, ] with sync_playwright() as p: browser = p.chromium.launch(proxy={"server": "http://per-context"}) # placeholder, required by Chromium for proxy in PROXIES: ctx = browser.new_context(proxy=proxy) page = ctx.new_page() page.goto("https://api.ipify.org?format=json") print(proxy["server"], "->", page.inner_text("body")) ctx.close() browser.close()

Multi Location note: with a RelayKit Multi Location proxy you usually don't need several proxies to cover several cities. One proxy moves between cities from the dashboard. Run your script, switch the city, run it again. See the multi-city research agent guide.

4. HTTP vs SOCKS5 in Chromium

RelayKit proxies answer on both an HTTP port (8000) and a SOCKS5 port (9000). Chromium cannot send a username and password to a SOCKS5 proxy, so in Playwright:

The dashboard's snippet panel shows the SOCKS5 Playwright variant only when whitelisting is on, for this reason.

5. Verify every run

Make the IP check a function and call it before the real work. If the IP doesn't match the proxy card, stop.

Python
def assert_on_proxy(page, expected_ip: str): page.goto("https://api.ipify.org?format=json", timeout=45_000) seen = page.evaluate("() => JSON.parse(document.body.innerText).ip") if seen != expected_ip: raise RuntimeError(f"Not on the proxy: saw {seen}, expected {expected_ip}")

The expected IP is on the proxy card. If you use Reset IP or a rotation timer the IP changes, so for rotating setups compare the city instead, using a geolocation lookup such as https://ipapi.co/json/.

6. Timeouts and retries for a mobile link

Python — block heavy assets
ctx = browser.new_context(proxy=proxy) ctx.route("**/*", lambda route: route.abort() if route.request.resource_type in {"image", "font", "media"} else route.continue_())

7. Example: regional price check

A common research task: record the prices a site shows to visitors from a given city. Run this, then switch the Multi Location proxy to another city in the dashboard and run it again.

price_check.py
import json, time from playwright.sync_api import sync_playwright PROXY = {"server": "http://HOST:8000", "username": "USER", "password": "PASS"} TARGET = "https://example.com/pricing" # the page you're researching PRICE_SELECTOR = ".price" # adjust to the site with sync_playwright() as p: browser = p.chromium.launch(proxy=PROXY) page = browser.new_page() page.goto("https://ipapi.co/json/", timeout=45_000) where = json.loads(page.inner_text("body")) page.goto(TARGET, timeout=60_000, wait_until="domcontentloaded") page.wait_for_selector(PRICE_SELECTOR, timeout=30_000) prices = [el.inner_text() for el in page.query_selector_all(PRICE_SELECTOR)] print(json.dumps({"city": where.get("city"), "region": where.get("region"), "ip": where.get("ip"), "prices": prices, "at": time.time()})) browser.close()

Playwright on a dedicated US mobile IP

Real 4G/5G carrier IPs, unlimited data, HTTP and SOCKS5, and a Multi Location plan that switches cities from the dashboard. Pay with crypto; sign up with an email.

Related guides