无需 KYC —— 无需身份证、自拍、文件证明。支持加密货币支付:BTC, USDT, USDC, ETH, SOL, LTC
语言: 简体中文
开始使用

文档 · Playwright · Chromium、Firefox、WebKit

Playwright 代理设置,旋转住宅 IP(Python 和 Node.js)

启动时为每个浏览器提供一个出口代理,或为每个上下文提供一个国家代理或一个固定会话代理。然后通过阻止不需要的流量来减少流量消耗。

最后更新:

快速回答

如何在 Playwright 中使用带认证的代理?

向 launch() 或 new_context() 传递包含 server、username 和 password 的 proxy 对象:server 是 http://gw.crawlrelay.com:7777,而凭据应单独放在对应字段,绝不放在服务器 URL 中。使用 CrawlRelay 住宅代理时,将国家和会话 ID 放入用户名,为每个上下文分配独立出口。流量费用 US$0.50/GB,起步 50 GB。支持加密货币支付,无需 KYC。

Playwright 快速设置

代理选项{"server": "http://gw.crawlrelay.com:7777", "username": ..., "password": ...}
位置整个浏览器使用 launch(proxy=...),或每个上下文使用 new_context(proxy=...)
端口HTTP 端口为 7777;HTTPS 网站通过 CONNECT 访问
SOCKS5Chromium 不支持 SOCKS5 认证:请使用 HTTP 端口
每个上下文一个 IP在上下文用户名中使用 -session-<id>-ttl-<minutes>
典型页面流量加载所有资源大约 2 MB;阻止图片、字体和媒体后只剩几百 KB

如何给每个浏览器上下文分配各自的国家或会话?

为每个国家或固定会话创建一个上下文。上下文比浏览器轻量,每个上下文独立保存 Cookie、存储和代理凭据。保证上下文的地区设置与出口国家匹配,使网站识别为同一访客。

Python(同步 API):每个国家一个上下文
from playwright.sync_api import sync_playwright

GATEWAY = "http://gw.crawlrelay.com:7777"
LOCALES = {"us": "en-US", "de": "de-DE", "jp": "ja-JP"}

with sync_playwright() as p:
    browser = p.chromium.launch()
    for country, locale in LOCALES.items():
        context = browser.new_context(
            proxy={"server": GATEWAY, "username": "USERNAME-country-%s" % country, "password": "PASSWORD"},
            locale=locale,
        )
        page = context.new_page()
        page.goto("https://api.ipify.org", wait_until="domcontentloaded")
        print(country, page.inner_text("body"))
        context.close()
    browser.close()

如何在 Node.js 的 Playwright 中设置代理并节省流量?

该选项在 Node.js 中与其他环境相同。渲染页面大部分流量来自图片、字体和媒体:HTTP Archive Web Almanac 2025 移动端的中位页面大小为 2,164 KB。如果仅需要文本和链接,可在路由处理程序中中止这些请求以节省流量。

Node.js:启动时的粘性会话,阻止大量资源
import { chromium } from "playwright";

const browser = await chromium.launch({
  proxy: {
    server: "http://gw.crawlrelay.com:7777",
    username: "USERNAME-country-us-session-pw1-ttl-30",
    password: "PASSWORD",
  },
});
const context = await browser.newContext();
// Images, fonts and media are most of a page's bytes
await context.route("**/*", (route) =>
  ["image", "font", "media"].includes(route.request().resourceType()) ? route.abort() : route.continue()
);
const page = await context.newPage();
const response = await page.goto("https://example.com/", { waitUntil: "domcontentloaded" });
console.log(response.status(), await page.title());
await browser.close();

如何使用 asyncio 并行运行多个页面?

使用带有固定上下文池的异步 API。每个上下文在其生命周期内保持一个粘性会话,因此网站看到的是少数稳定访客,而非每个请求一个 IP。在达到设定页面数或出现错误后,回收上下文并生成新会话 ID。

Python(异步 API):粘性上下文池
import asyncio
import uuid

from playwright.async_api import async_playwright

GATEWAY = "http://gw.crawlrelay.com:7777"
WORKERS = 4


async def worker(browser, queue):
    session = uuid.uuid4().hex[:10]
    context = await browser.new_context(proxy={
        "server": GATEWAY,
        "username": "USERNAME-country-us-session-%s-ttl-30" % session,
        "password": "PASSWORD",
    })
    page = await context.new_page()
    while not queue.empty():
        url = await queue.get()
        try:
            response = await page.goto(url, wait_until="domcontentloaded", timeout=45000)
            print(session, url, response.status if response else None)
        except Exception as exc:  # timeouts and network errors: log and move on
            print(session, url, type(exc).__name__)
        finally:
            queue.task_done()
    await context.close()


async def main(urls):
    queue = asyncio.Queue()
    for url in urls:
        queue.put_nowait(url)
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        await asyncio.gather(*(worker(browser, queue) for _ in range(WORKERS)))
        await browser.close()


asyncio.run(main(["https://example.com/", "https://example.org/"]))

为什么我会遇到 ERR_TUNNEL_CONNECTION_FAILED 或 ERR_PROXY_CONNECTION_FAILED?

  • net::ERR_TUNNEL_CONNECTION_FAILED 意味着代理未接受 CONNECT 请求。最常见的原因是凭证写在server内而非username和password,导致 Chromium 没有发送。详见隧道错误]。
  • net::ERR_PROXY_CONNECTION_FAILED 意味着浏览器根本没能连接到网关:主机或端口有错别字,或网络屏蔽该端口。详见代理连接错误]。
  • goto上的“超时 30000ms”通常意味着你正等待load或networkidle,页面不断加载跟踪器。请先等待domcontentloaded,然后等待你需要的选择器。

Playwright 抓取器不应该做什么?

使用 Playwright 来渲染需要 JavaScript 的公共页面,而非冒充用户。CrawlRelay的可接受使用政策禁止通过我们的网关批量创建账户、接管账户、自动识别 CAPTCHA 或绕过网站刻意设置的屏蔽。我们不提供隐形插件或指纹伪装的文档。如果网站对你的浏览器发起挑战,请放慢速度,查看其 robots.txt 和条款,申请访问权限或使用其 API。

Playwright 和代理:常见问题

我可以为每个 Playwright 上下文使用不同的代理吗?

可以。在 Python 中将proxy传递给browser.new_context(),在 Node.js 中传递给browser.newContext()。每个上下文拥有自己的出口 IP、Cookie 和存储。Windows 上的非常旧版本 Playwright 需要启动时指定代理;如果报错,请用任意占位代理启动,再为每个上下文设置真实代理。

Playwright 支持带认证的 SOCKS5 代理吗?

Chromium 不支持 SOCKS5 的用户名和密码认证,因此不支持。请使用网关的 HTTP 端口(7777):它通过 CONNECT 隧道处理 HTTPS 站点,并支持所有 Playwright 控制的浏览器引擎中的用户名密码认证。

如何检查 Playwright 页面使用的 IP 和国家?

在目标页面同一上下文中先打开https://api.ipify.org,读取响应正文,参考第一个示例。请记住,粘性会话仅在其住宅代理设备保持在线期间绑定该 IP;建议在每个上下文开始时记录 IP 以侦测变化。

Playwright 页面通过代理使用多少流量?

所有流量都计费:HTML、脚本、样式、图片、字体和 API 调用。完整页面中位流量约 2 MB;阻止图片、字体和媒体可将其减少至几百 KB。通过在response处理程序中累计 50 个页面的响应大小,测量你实际页面的流量。

抓取时我应该用无头还是有头浏览器?

无头是服务器的常用选择,占用资源更少。有头浏览器仅用于调试页面显示。两者规则相同:以礼貌速度渲染公共页面,尊重网站 robots.txt 和使用条款。

通过住宅代理渲染公共页面

US$5.94 适用于 10 GB,US$0.50/GB 来自 50 GB。

从 US$0.50/GB 开始 · 无需 KYC

开始使用