Playwright 和 Puppeteer 配代理

发布:2026 年 7 月 23 日 · 阅读约 6 分钟

一句话总结: Playwright 里把 proxy dict 传给 launch(),更好的是传给 new_context(),让每个 context 拿各自的 IP。Puppeteer 里把 --proxy-server 放进 args,凭据用 page.authenticate()。用住宅代理让浏览器从真实家庭 IP 出去;同时跑多个身份时,每个 context/浏览器用各自的粘性会话。

Playwright

Playwright 接收一个 proxy 字典,含纯 server URL 和独立的凭据字段。最简单的形式设在 launch() 上,作用于整个浏览器:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server": "http://gw.roamproxy.com:41080",
            "username": "YOUR_USERNAME",
            "password": "YOUR_PASSWORD",
        }
    )
    page = browser.new_page()
    page.goto("https://ip.sb")
    print(page.inner_text("body"))
    browser.close()

per-context 代理——一身份一 IP

更有用的写法是把代理设在 new_context() 上。每个 context 是隔离的浏览器会话——各自的 cookie、存储,现在还有各自的 IP——所以一个浏览器进程能跑多个不共用出口的身份:

ctx_a = browser.new_context(proxy={
    "server": "http://gw.roamproxy.com:41080",
    "username": "USERNAME_session_a",
    "password": "YOUR_PASSWORD",
})
ctx_b = browser.new_context(proxy={
    "server": "http://gw.roamproxy.com:41080",
    "username": "USERNAME_session_b",
    "password": "YOUR_PASSWORD",
})

给每个 context 在用户名里用不同的粘性会话,每个就拿到稳定、独立的住宅 IP——会话串怎么用见 什么是轮换代理

Puppeteer

Puppeteer 把代理作为 Chromium 启动参数,认证在页面上处理。凭据放进参数:

const puppeteer = require('puppeteer');

const browser = await puppeteer.launch({
  args: ['--proxy-server=http://gw.roamproxy.com:41080'],
});
const page = await browser.newPage();
await page.authenticate({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' });
await page.goto('https://ip.sb');
console.log(await page.evaluate(() => document.body.innerText));
await browser.close();

Puppeteer 把代理作用于整个浏览器,所以要同时跑多个 IP,就启动多个浏览器(各带自己的 --proxy-server 和粘性会话),或在前面放代理路由。

验证出口

上面两段都会导航到 IP 检测接口并打印结果。它应显示 Roam 住宅出口 IP 和你选的国家,而不是你机器的真实地址。若显示真实 IP,说明代理没挂上——回看 常见问题

不需要浏览器的时候

目标站需要 JavaScript 或交互式挑战时,Playwright 和 Puppeteer 是对的工具。不需要时——纯 JSON API 或静态 HTML——完整浏览器就太慢太重了。要给脚本式 HTTP 请求配浏览器级指纹,改用 curl_cffi;按防护层级在两者间怎么选,见 网页采集如何过 Cloudflare。用 LLM 驱动 Playwright,见 browser-use 配住宅代理

常见问题

代理该设在 launch 还是 context 上?

Playwright 里优先设在 context。设在 launch() 上是整个浏览器用一个代理;设在 new_context() 上让每个 context 有各自的代理——一个脚本跑多个身份时正需要这个,每个 context 成为独立浏览器会话、独立 IP。Puppeteer 没有一等的 per-context 代理,要多 IP 就启动多个浏览器,或在前面放一个代理路由。

用户名密码怎么传?

Playwright 里把它们作为 usernamepassword 放进 proxy dict,和 server 并列——绝不要塞进 server URL。Puppeteer 里凭据不放 args;在 args 里设 --proxy-server=主机:端口,然后在第一次导航前调 await page.authenticate({username, password})

已经用真实浏览器了,还需要 curl_cffi 吗?

不需要——用浏览器的意义就在这。Playwright 和 Puppeteer 驱动真实 Chromium,TLS/JS 指纹本来就是真的。curl_cffi 是给不用浏览器的脚本式 HTTP 请求补回那个指纹的。用 Playwright/Puppeteer 你只需修网络层,那正是代理的活。

浏览器起来了却还是显示真实 IP,为什么?

通常是代理设在了错的对象上,或凭据被塞进了 server URL。确认 server 是纯 http://主机:端口,username/password 是独立键(Playwright)或通过 page.authenticate() 设(Puppeteer),并且代理挂在了你实际导航用的 context/浏览器上。然后重跑下面的 IP 检测。

两个框架都要一个纯 主机:端口 代理加凭据——正是 Roam 给你的。轮换住宅 $2/GB、静态住宅 $4/IP/月,HTTP 与 SOCKS5 都支持。注册账号即送 300MB 试用流量,让你第一个浏览器从住宅出口跑起来。