# 在 Playwright 中使用代理：每个浏览器或上下文使用独立出口

Playwright 可在启动时或按浏览器上下文接收代理和凭据，因此无需重启浏览器，每个上下文就能在各自的国家/地区使用独立的粘性会话。


## 启动级代理

**Python**

```python
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(proxy={
        "server": "http://res.proxshift.com:9000",
        "username": "USER-cc-us-sid-run1-ttl-30m",
        "password": "PASS",
    })
    page = browser.new_page()
    page.goto("https://api.ipify.org")
    print(page.inner_text("body"))
    browser.close()
```

**Node.js**

```node
import { chromium } from "playwright";

const browser = await chromium.launch({
  proxy: { server: "http://res.proxshift.com:9000", username: "USER-cc-us-sid-run1-ttl-30m", password: "PASS" },
});
const page = await browser.newPage();
await page.goto("https://api.ipify.org");
console.log(await page.innerText("body"));
await browser.close();
```

浏览器会保持连接，因此启动时应使用粘性会话 ID：在你选择的有效期内，整个浏览器都会表现为来自同一家庭住宅的同一位访问者。


## 按上下文配置代理

若要在同一浏览器中运行多个国家/地区或会话，请先使用占位代理启动，再为每个上下文分别指定代理。Chromium 必须设置启动级代理，按上下文代理才会生效。

**Python**

```python
browser = p.chromium.launch(proxy={"server": "http://per-context"})

de = browser.new_context(proxy={"server": "http://res.proxshift.com:9000", "username": "USER-cc-de-city-berlin-sid-de1-ttl-30m", "password": "PASS"})
us = browser.new_context(proxy={"server": "http://res.proxshift.com:9000", "username": "USER-cc-us-state-tx-sid-us1-ttl-30m", "password": "PASS"})
```

**Node.js**

```node
const browser = await chromium.launch({ proxy: { server: "http://per-context" } });

const de = await browser.newContext({ proxy: { server: "http://res.proxshift.com:9000", username: "USER-cc-de-city-berlin-sid-de1-ttl-30m", password: "PASS" } });
const us = await browser.newContext({ proxy: { server: "http://res.proxshift.com:9000", username: "USER-cc-us-state-tx-sid-us1-ttl-30m", password: "PASS" } });
```


## 让上下文与出口保持一致

为每个上下文设置出口所在国家/地区的区域设置和时区，确保 IP、语言与时钟一致。例如，柏林上下文应使用 `locale=\"de-DE\", timezone_id=\"Europe/Berlin\"`。这些信息不一致时，暴露自动化行为的风险甚至高于 IP 本身。


## 节省流量：屏蔽不需要的资源

**Python**

```python
def block(route):
    if route.request.resource_type in {"image", "media", "font", "stylesheet"}:
        return route.abort()
    return route.continue_()

page.route("**/*", block)
```

**Node.js**

```node
await page.route("**/*", (route) => {
  const t = route.request().resourceType();
  return ["image", "media", "font", "stylesheet"].includes(t) ? route.abort() : route.continue();
});
```

完整渲染的页面大小可达 3 至 5 MB，而其 HTML 和 API 调用通常只有几百 KB。在按 GB 计费的网络上，仅这一条规则就能减少 80% 至 90% 的费用。


## 验证与故障排查

- 先打开 IP 回显服务检查国家/地区，再使用地理位置查询服务核对城市。
- 启动时出现 `net::ERR_TUNNEL_CONNECTION_FAILED` 或 `ERR_PROXY_CONNECTION_FAILED`，表示凭据或某个参数有误；使用 cURL 测试同一个 URL，以读取网关状态码。
- 只有主动屏蔽 WebRTC，Playwright 上下文才不会使用它。若隐私很重要，请添加类似 `--disable-webrtc` 的加固参数或屏蔽 STUN。


## 问题

**每个标签页都可以使用不同的代理吗？**

每个上下文可以使用不同代理；同一上下文内的标签页（页面）共享其代理。请为每个会话或国家/地区创建一个上下文。

**Playwright 支持需要身份验证的 SOCKS5 代理吗？**

Chromium 不接受 SOCKS5 凭据；请通过用户名和密码使用 9000 端口的 HTTP 代理，或将服务器 IP 加入白名单，再使用无需凭据的 socks5://res.proxshift.com:9001。

来源：https://proxshift.com/zh/guides/playwright-proxy
