How to Set Up a Proxy for Playwright & Selenium: Complete Guide With Working Code

AI agents are moving from “answering questions” to “actually doing things” — and the first step is almost always operating a browser: filling forms, clicking buttons, scrolling through lists, extracting page data into structured results. Playwright and Selenium are the two most widely used browser automation frameworks, and with AI-driven task orchestration they can already complete quite complex real-world workflows.

But automation has one unavoidable problem: its traffic pattern looks nothing like a human being’s. When the same exit IP fires hundreds of requests in a short window, risk systems easily flag it as machine behavior — captcha pop-ups, rate limiting, and eventually a blocked address. The fix is straightforward: route browser automation through a proxy, so requests leave from an appropriate exit IP and the “machine operation” carries a “human access” network identity.

This guide covers three things: how to configure proxies in Selenium and Playwright respectively (with runnable code), which proxy type fits which automation scenario, and why an IP alone is often not enough.

Sign Up for a Free Trial of kookeeyGlobal Proxy

How Do Risk Engines Judge Automation Traffic?

To choose the right proxy, it helps to know what the other side actually evaluates. Modern risk engines look at combined signals, and the network layer is just one of them:

  • IP attribution: country, ISP, and ASN of the exit address — does it match the natural pattern of the business?
  • Device fingerprint: browser UA, Canvas, WebGL, fonts, timezone, language — a consistent bundle that says “this is one real device.”
  • Behavior frequency: request intervals, operation rhythm, session dwell time.

When an automation script runs through a raw datacenter IP while everything else stays at default values, the mismatch itself becomes the anomaly. That is why “just set a proxy” often fails: the proxy solves the network layer, but edge cases in the other two layers still leak through.

👉 Claim Free Trial & Register Now at kookeey

Selenium: How to Set a Proxy (Runnable Code)

Selenium injects the proxy through browser launch arguments. Using Chrome as an example, the core call is add_argument with --proxy-server:

from selenium import webdriver

options = webdriver.ChromeOptions()
# No-auth proxy: pass the address and port directly
options.add_argument("--proxy-server=http://IP:port")
driver = webdriver.Chrome(options=options)
driver.get("https://example.com")
print(driver.current_url)
driver.quit()

If the proxy requires username and password authentication, --proxy-server cannot carry credentials directly — you need a proxy extension. The approach is to generate a Chrome extension that embeds the auth logic in manifest.json and background.js, then load it with add_extension.

manifest.json:

{
  "version": "1.0.0",
  "manifest_version": 2,
  "name": "proxy-auth",
  "permissions": ["proxy", "tabs", "unlimitedStorage", "storage", "<all_urls>"],
  "background": {"scripts": ["background.js"]}
}

background.js (replace IP, port, username and password with your real proxy info):

var config = {
  mode: "fixed_servers",
  rules: {
    singleProxy: {scheme: "http", host: "IP", port: 8080}
  }
};
chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});
function callbackFn(details) {
  return {authCredentials: {username: "your_username", password: "your_password"}};
}
chrome.webRequest.onAuthRequired.addListener(
  callbackFn,
  {urls: ["<all_urls>"]},
  ["blocking"]
);

Then load the extension:

options.add_extension("path/to/proxy_auth_extension")
driver = webdriver.Chrome(options=options)

Note: the webdriver.ChromeOptions() pattern in Selenium 4 is compatible with older versions, and Chrome’s parsing of --proxy-server is stable, so this code runs as-is.

Playwright: One Parameter Is All It Takes

Playwright handles proxies much more directly: pass a proxy argument at launch, with native support for authentication credentials:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server": "http://IP:port",        # or socks5://IP:port
            "username": "your_username",
            "password": "your_password",
        }
    )
    page = browser.new_page()
    page.goto("https://example.com")
    print(page.title())
    browser.close()

For finer control, you can attach the proxy at the browser context level, so different contexts use different exits:

context = browser.new_context(
    proxy={"server": "http://IP:port", "username": "your_username", "password": "your_password"},
    user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
)
page = context.new_page()

The server field in Playwright supports http, https, and socks5 protocols, covering most proxy types; credentials are native fields, no extension needed — one step fewer than Selenium.

👉 Claim Free Trial & Register Now at kookeey

Residential or Datacenter Proxy for Automation?

Before picking a proxy, pick the right *type*. Automation workloads split into two broad categories with completely different selection logic:

Category 1: low-risk, batchable data collection. Grabbing public product prices, industry news, or public directories. These tasks have controlled frequency and no login state, so long-term stability requirements are low — static datacenter proxies are the cost-effective choice: high volume, fast, cheap. With rate limiting and rotation in place, most collection tasks are covered.

Category 2: logged-in, long-term, identity-sensitive automation. Cross-border store operations, social account management, AI agent tasks that must hold a session. These need a “stable, trustworthy exit identity” — residential proxies (especially static residential / ISP) fit better: the exit comes from real home networks with higher platform trust; a dedicated port means only you use it, so you won’t get collateral-banned by someone else’s abuse.

One sentence summary: go datacenter for volume and speed; go residential for identity and stability.

If a task needs to change sources frequently (bulk market research, regional data comparison), consider dynamic residential proxies: each request rotates to a different exit, simulating multiple real users. But mind the rotation rhythm — switching on every request looks like a crawler itself; low-frequency rotation (per minute or per task) matches real human behavior far better.

Free Benefits for kookeey New Users 🎁

200MB Residential 100MB Mobile ¥288 Bonus Pack
•Exclusive Use •ISP •Dedicated Port / API

Why Just a Proxy Isn’t Enough: Three-Layer Consistency

This is the most common pitfall: people assume that once a proxy is set, they are “invisible” — and still get flagged. The reason is that modern risk engines judge *combined features*, and the network layer is only part of the story:

  • IP attribution: country, ISP, ASN — aligned with the business scenario or not;
  • Device fingerprint: browser UA, Canvas, WebGL, fonts, timezone, language as a bundle;
  • Behavior frequency: request intervals, operation rhythm, single-session dwell time.

If the proxy points to one country but the timezone is local, the language is default, and operations run at machine pace, the risk engine still marks the session as anomalous. A complete anti-ban configuration covers three layers:

  1. Network layer: residential proxy or a suitable exit IP whose attribution matches the business region;
  2. Fingerprint layer: pinned browser fingerprint, a suitable UA, and WebRTC leaks disabled (so the real IP never leaks);
  3. Behavior layer: randomized delays between requests (e.g., 2-6 second jitter), controlled concurrency, and scheduled rotation when needed.

A classic counter-example: exit IP on the US West Coast while the account timezone is set to GMT+8 — the platform instantly detects mismatched language, timezone, and network attribution. Align attribution, timezone, language, and operation hours to the same region, and the traffic record survives cross-checking.

Get all three layers aligned and the automation script starts to “smell human.” This is also why account operations and account-nurturing practices keep repeating “one account, one IP, one fingerprint” — a fully consistent environment is what a real user looks like.

Rotating IPs for Batch Tasks: Dynamic Residential + Rotation Rhythm

Collection and research tasks often need hundreds of requests. If everything goes through one exit IP, even a clean address will trigger risk on frequency alone; the right approach is to give the task an IP pool and rotate it slowly and steadily.

In Playwright, attach a different proxy per context to achieve “one task, one exit.” With kookeey dynamic residential proxies, for example, generate a dedicated dynamic port in the dashboard, and the exit addresses (server:port + account + password) can be filled straight into the list:

# Example with kookeey dynamic residential proxies:
# generate a dedicated dynamic port in the dashboard, then fill in the exit addresses
proxy_list = [
    "http://kookeey-account:kookeey-password@server-address:port",   # exit 1
    "http://kookeey-account:kookeey-password@server-address:port",   # exit 2
]
for i, url in enumerate(urls):
    ctx = browser.new_context(
        proxy={"server": proxy_list[i % len(proxy_list)]}
    )
    page = ctx.new_page()
    page.goto(url)
    # parse and store data...
    ctx.close()

The requests-layer logic is identical: bind a Session to one exit at a time, or keep a pool and take addresses round-robin. The key is the rotation rhythm — switch per task or per minute, not per request; per-request switching is itself a crawler signature. kookeey dynamic residential proxies support custom rotation intervals and ship with a full traffic dashboard — real-time line traffic, dedicated dynamic ports, and API access — suited to “different task, different exit” at scale.

Common Errors: 403 / 429 Troubleshooting

After wiring up the proxy, scripts can still fail. The two most common errors:

  • 403 Forbidden: access denied — usually the UA is identified as a script, or the exit IP is on the target’s watchlist. Change the UA first, then check IP purity (is it a datacenter range? is it blacklisted?), and switch to another line if needed.
  • 429 Too Many Requests: frequency limit exceeded. Lower concurrency, widen request intervals, and add exponential backoff — this works better than switching IPs. A new IP only dodges the current limit; unchanged frequency will trip it again.

Suggested order: verify proxy connectivity with curl and confirm the actual exit IP, then identify the error type, then adjust UA, frequency, and exit IP respectively. Most automation errors are located within these three steps.

Final Thoughts

“AI operating the web” and “proxy” are, at bottom, the same problem: automation doing human work needs a human network identity. One proxy parameter in Playwright, one launch argument in Selenium — attach the right exit IP, pair it with fingerprint and behavior rhythm, and script stability improves noticeably.

Two directions to remember when choosing a provider: volume → datacenter, identity → residential; and when evaluating a vendor, prioritize IP purity control — one-IP-one-use, a cooling-off/cleaning period, dedicated ports, and API support. These directly decide whether automation can run reliably long-term.

If your automation already lives in Python, kookeey also supports fetching dynamic IPs via API: the program pulls exits on demand and releases them when done, so at scale the code can orchestrate the whole proxy pool without maintaining address lists by hand. A business-grade IP pool with a 6-month cooling-off period means every IP is settled and cleaned before sale; combined with dedicated port usage, it noticeably reduces collateral bans from shared exits.

kookeey provides static residential (ISP), static datacenter, dynamic residential, and mobile proxies — all supporting HTTP(S) and SOCKS5 — with a managed dashboard and API to scale concurrency elastically from single scripts to large collection clusters.

Sign up for kookeey and get the new-user package: 200MB residential traffic + 100MB mobile proxy + ¥288 bonus pack. Test before you buy, then decide which plan fits your automation workload.

FAQ
›How do I set a proxy in Playwright? ▲
›Selenium proxy is set but I can’t connect — why? ▲
›Residential or datacenter proxy for automation? ▲
›I set a proxy but still get flagged by risk control — why? ▲
›Is it legal to use proxies for data collection? ▲

This article comes from online submissions and does not represent the analysis of kookeey. If you have any questions, please contact us

Like (0)
kookeeykookeey
Previous October 8, 2026 5:36 pm
Next 13 hours ago

Related recommendations