# Playwright代理集成：浏览器、上下文和轮换

Playwright是唯一一个主要的浏览器框架，支持经过身份验证的代理——凭证是一级配置。关键在于上下文：一个浏览器，每个任务使用不同的出口IP。以下是完整的模式。

Playwright是唯一一个主要的浏览器自动化框架，其中经过身份验证的代理是一级公民：用户名和密码是简单的配置字段，无需扩展黑客，无需认证对话框，无需包装库。这使得基本的Playwright代理设置在Node或Python中只需五行代码。真正的杠杆作用在于更深一层——每个上下文的代理允许一个浏览器进程运行多个独立的会话，每个会话都有自己的出口IP，这是任何框架提供的最便宜的轮换架构。本指南涵盖了这两个层次，SOCKS5和localhost的陷阱，代理对带宽账单的影响，以及隐身真正结束的地方。

## 浏览器启动时的Playwright代理

将一个`proxy`对象传递给`launch()`，浏览器中的每个页面都通过它路由。注意其结构：服务器URL不携带凭证——它们在单独的`username`和`password`字段中，这就是Playwright避免了困扰Selenium和Puppeteer的认证弹出问题的原因：

```js
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({
    proxy: {
      server: 'http://residentialpremium.quantumproxies.io:8080',
      username: 'USER',
      password: 'PASS',
    },
  });
  const page = await browser.newPage();
  await page.goto('https://httpbin.org/ip');
  console.log(await page.textContent('body')); // proxy exit IP
  await browser.close();
})();
```

Python API完全镜像它：

```python
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(proxy={
        "server": "http://residentialpremium.quantumproxies.io:8080",
        "username": "USER",
        "password": "PASS",
    })
    page = browser.new_page()
    page.goto("https://httpbin.org/ip")
    print(page.text_content("body"))
    browser.close()
```

如果您的凭证存在于标准的`http://user:pass@host:port`字符串中，请使用URL类（Node中的`new URL()`，Python中的`urllib.parse`）拆分它，而不是字符串手术——这样密码中的特殊字符才能保留。一个测试运行器的注意事项：`playwright.config.ts`中的`use.proxy`涵盖了测试，但长期以来有报告称在混合设置中配置级别的代理设置被忽略，因此对于抓取脚本，请始终在`launch()`或上下文中直接设置代理。

## 每个上下文的代理：无需新浏览器的轮换

`BrowserContext`是一个隔离的浏览器内的浏览器：独立的cookie、存储和缓存，仅共享进程。上下文接受自己的`proxy`选项，创建一个上下文只需几毫秒，而完整启动需要几秒钟——因此轮换模式是一个浏览器，每个任务一个上下文：

```js
const { chromium } = require('playwright');

const PROXY = {
  server: 'http://residentialpremium.quantumproxies.io:8080',
  username: 'USER',
  password: 'PASS',
};

(async () => {
  const browser = await chromium.launch();
  const urls = ['https://example.com/a', 'https://example.com/b'];

  for (const url of urls) {
    const context = await browser.newContext({ proxy: PROXY });
    const page = await context.newPage();
    try {
      await page.goto(url, { timeout: 30000 });
      // ...extract...
    } finally {
      await context.close(); // frees cookies, cache, session
    }
  }
  await browser.close();
})();
```

指向一个旋转网关，每个上下文从90M+住宅池中的不同IP退出，无需任何列表管理——这就是[旋转代理](https://quantumproxies.io/rotating-proxies)在服务器端所做的。当一个任务需要在多个页面上使用相同的IP（登录加结账）时，通过用户名参数请求一个粘性会话，出口在会话窗口内保持不变。上下文还隔离故障：被禁的出口与其上下文一起消亡，而不是污染整个浏览器。

同样的模式让您免费获得地理定位。因为代理是一个上下文选项，一个浏览器可以同时持有一个美国上下文、一个德国上下文和一个日本上下文——每个上下文从本地出口IP看到本地化的价格、搜索结果和同意横幅。对于价格比较和广告验证工作，这取代了三个云区域，只需三行配置。

![一个 Playwright 浏览器进程包含三个隔离的上下文，分别是美国、德国和日本，每个都通过自己的住宅出口 IP 访问同一网站。卡片说明：同一进程，Cookie 和存储彼此独立，每个 newContext 一个代理，创建一个上下文只需几毫秒，而启动一个浏览器需要几秒。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335143/blog/generated/qp-b9-004-diag1.png)
*上下文是Playwright的轮换单位：相同的进程，独立的身份，自己的代理。启动一个上下文只需几毫秒；一个浏览器需要几秒钟。*

## SOCKS5、绕过规则和localhost陷阱

- **SOCKS5有效，SOCKS5认证无效。**Chromium不支持SOCKS凭证，因此`server: 'socks5://...'`仅连接到未经认证的端点。对于经过认证的SOCKS5代理，要么切换到同一网关的HTTP端口，要么将您的机器IP列入白名单，这样就不需要凭证。
- **绕过主机**使用`bypass: '*.internal.example.com, localhost'`——流向这些主机的流量直接传输。当您的脚本还与必须不通过代理传输的内部服务通信时，这很有用。
- **localhost是特殊的。**Chromium默认绕过环回地址的代理，因此对本地模拟服务器的测试似乎“忽略”了您的代理。这是浏览器的行为，而不是Playwright的行为——请改为对外部端点如httpbin.org/ip进行测试。
- **代理“不起作用”检查清单：**凭证在字段中（而不是服务器URL中），服务器值上有方案，并通过加载IP回显页面验证出口，然后再责怪目标站点。

## 在扩展之前削减带宽

一个渲染浏览器下载所有内容——图像、字体、分析、广告脚本——通过计量的住宅流量，您为所有这些付费。阻止非必要的资源类型通常可以将每页传输量减少一半或更多，而Playwright的路由使其在上下文中只需一行代码。更多模式请参阅我们的[减少代理带宽成本](https://quantumproxies.io/blog/reduce-proxy-bandwidth-costs-scraping)指南：

```js
await context.route('**/*', (route) => {
  const type = route.request().resourceType();
  if (type === 'image' || type === 'font' || type === 'media') {
    return route.abort();
  }
  return route.continue();
});
```

测量效果而不是假设：订阅上下文的响应事件，汇总有路由和无路由页面样本的传输大小，您将获得真实的每页GB成本——这个数字决定了对一百万页的抓取是四舍五入误差还是预算线。

## 隐身限制：代理无法解决的问题

诚实面对上限。住宅出口解决了IP声誉问题——这是第一个也是最大的过滤器——但Playwright仍然在网络层之上呈现自动化痕迹：无头渲染怪癖、CDP工件和反指纹表面，反机器人供应商直接探测。隐身插件修补了一些信号，但在其他方面落后于检测器更新；这是您继承的军备竞赛，而不是您启用的设置。务实的分工：通过[住宅代理](https://quantumproxies.io/residential-proxies)运行Playwright以应对正常站点的长尾，并通过[Scraper API](https://quantumproxies.io/scraper-api)路由真正敌对的域，该API负责管理指纹、渲染和重试，并返回HTML、markdown或结构化JSON。您的Playwright代码继续做其独特擅长的事情——交互流程——而抓取和解析工作则转移到API。相同的计算适用于[Puppeteer](https://quantumproxies.io/blog/puppeteer-proxy-setup)和[Selenium](https://quantumproxies.io/blog/selenium-proxy-setup-authenticated)；没有框架交换可以解决指纹问题。

![从普通网站到敌对域名的刻度：住宅代理能通过第一道墙，即 IP 信誉；在指纹检测上，隐身插件总是落后于检测器的更新；对于敌对域名，由 Scraper API 处理第二道墙。卡片建议：Playwright 继续使用住宅 IP，最难的域名交给 API。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335143/blog/generated/qp-b9-004-diag2.png)
*干净的IP让您通过第一道墙。指纹检查是第二道墙——也是API胜过另一个隐身补丁的地方。*

## 常见问题解答

### 如何在Playwright Python中设置代理？

将代理字典传递给`launch()`：`p.chromium.launch(proxy={"server": "http://host:port", "username": "USER", "password": "PASS"})`。相同的字典适用于`browser.new_context()`，用于每个上下文的路由。凭证始终放在单独的字段中，绝不放在服务器URL内。

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

可以——将`proxy`选项传递给每个`newContext()`调用。上下文除了浏览器进程外不共享任何东西，因此两个具有不同代理的上下文对目标站点的行为就像两个不相关的浏览器。这是标准的轮换模式：一次启动，然后每个任务或每个身份一个新的上下文。

### Playwright支持SOCKS5代理认证吗？

不支持。Playwright将SOCKS5传递给浏览器，而Chromium没有SOCKS凭证的机制，因此经过认证的SOCKS5端点会失败。使用相同代理网关的HTTP(S)端口，使用用户名和密码字段，或通过IP白名单进行认证，并保持SOCKS5方案。

### Playwright代理的正确格式是什么？

一个包含`server`字段的对象（`scheme://host:port`——http、https或socks5）加上可选的`username`、`password`和`bypass`字段。不要将凭证放在服务器URL内；Playwright期望它们是分开的，具有特殊字符的密码只有在专用字段中才能保留。

### 为什么我的Playwright代理在localhost上不起作用？

Chromium默认绕过环回地址的代理，因此对`localhost`或`127.0.0.1`的请求直接传输，似乎忽略了您的配置。通过外部URL（如httpbin.org/ip）验证代理。在测试设置中，也更倾向于在`launch()`时设置代理，而不是依赖于配置文件选项。

Playwright的代理故事是生态系统中最干净的：凭证作为配置，上下文作为轮换单位，路由作为带宽阀门。将IP质量调整到位，框架就会淡出背景——这正是良好基础设施应该做的。

[将Playwright指向住宅代理](https://quantumproxies.io/residential-proxies)
