Puppeteer 移动代理配置指南
Puppeteer 通过启动参数把代理传给 Chrome,而 Chrome 不接受写在该参数中的凭证——这就是为什么最直观的写法只会弹出一个代理认证对话框并卡住,而不是打开页面。正确的做法分两步:启动参数中只写服务器地址,凭证通过 page.authenticate 传入。其余一切都由此展开。
问题所在:--proxy-server 不接受密码
Chrome 的 --proxy-server 参数只接受协议、主机和端口,别无其他。把凭证写进去,Chrome 会直接忽略,上游返回 407,而 Puppeteer 会停在一个无头模式下看不见的认证弹窗上——所以症状是页面导航永远不结束,而不是一个指明原因的报错。更深一层,促使大家使用 Puppeteer 的那个问题依然存在:从云服务器 IP 运行的无头 Chrome 很容易被识别,因此您自动化操作的内容,可能并不是真实访客看到的内容。
如果您遇到过以下情况
- 在 --proxy-server 中加入凭证后,goto() 一直卡到超时,没有任何报错。
- 出现 ERR_INVALID_AUTH_CREDENTIALS,或网络日志中出现无声的 407。
- 认证在第一个页面有效,之后的每个页面都失败。
- 新页面或弹窗绕过了您在第一个页面上设置的代理认证。
- 因为没有拦截任何请求,带宽费用随完整页面体积增长。
可运行的代码
只要 PROXY_URL 中填入真实的连接字符串,下面的每段代码都能直接运行。首次充值后,可在控制台复制您的连接字符串。
设置连接 URL
bashexport PROXY_URL="http://USERNAME-mbl-us-sid-pptr01-rot-sticky:[email protected]:7000"
# 每个会话一个浏览器实例。Chrome 在整个进程范围内应用代理参数,
# 所以第二个身份就需要第二个浏览器。正确写法:参数指定主机,authenticate 传入凭证
javascriptimport puppeteer from 'puppeteer';
const url = new URL(process.env.PROXY_URL);
const browser = await puppeteer.launch({
headless: 'new',
args: [
// 这里只写主机和端口——Chrome 会忽略写在这里的凭证。
`--proxy-server=http://${url.host}`,
],
});
const page = await browser.newPage();
// 大多数示例都漏掉了这一步。
await page.authenticate({
username: decodeURIComponent(url.username),
password: decodeURIComponent(url.password),
});
await page.goto('https://api.ipify.org?format=json', { waitUntil: 'domcontentloaded' });
console.log(await page.evaluate(() => document.body.innerText));
await browser.close();page.authenticate 是按页面生效的。每个新页面或弹窗都需要单独调用——见下文。
为每个页面认证,包括弹窗
javascriptconst creds = {
username: decodeURIComponent(url.username),
password: decodeURIComponent(url.password),
};
// 捕获网站自行打开的页面,否则它们会遇到一个您看不到的 407。
browser.on('targetcreated', async (target) => {
if (target.type() !== 'page') return;
const p = await target.page();
if (p) await p.authenticate(creds);
});
const page = await browser.newPage();
await page.authenticate(creds);没有 targetcreated 钩子时,目标网站的一次 window.open 就会让任务悄悄中断。
拦截请求——流量按 GB 计费
javascriptawait page.setRequestInterception(true);
page.on('request', (req) => {
if (['image', 'media', 'font', 'stylesheet'].includes(req.resourceType())) {
return req.abort();
}
return req.continue();
});
// 使用移动端视口,让网站向您的移动 IP 返回移动版页面。
await page.setViewport({ width: 390, height: 844, isMobile: true, deviceScaleFactor: 3 });
await page.goto('https://target.example/product/123', { waitUntil: 'domcontentloaded' });必须在 goto 之前启用拦截,并且每个请求都必须恰好调用一次 abort 或 continue。
应该使用哪种轮换模式
-rot-stickyChrome 把代理作为进程级启动参数,整个浏览器共用一个出口——在 Puppeteer 中,身份的最小单位是浏览器实例,而不是页面。因此粘性会话是最自然的选择:用 -rot-sticky 和独立的 -sid- 固定浏览器,完成整个会话后再关闭它。需要不同身份时,用不同的 sid 启动第二个浏览器,而不是试图在运行中的 Chrome 底下切换出口——那会让您已建立的会话状态全部失效。
何时选择其他模式
| 模式 | 适用场景 |
|---|---|
| auto10 | 执行无状态任务的短时浏览器,每次启动只处理少量相互独立的页面。 |
| hard | 持续数小时、不能更换设备的长时间监控会话。 |
| auto30 | 需要在长时间运行中获得一定 IP 多样性、又不干扰短会话的后台爬取。 |
预计带宽用量
Puppeteer 驱动的是真实的 Chrome,所以 Chrome 下载什么,它就下载什么。在这里,请求拦截不是可有可无的优化——在按 GB 计费的代理池上,它是您最主要的成本控制手段。
| 任务类型 | 单次用量 | 每 GB 可完成 |
|---|---|---|
| 典型页面,全部资源,全新配置文件 | 2–5 MB | 约 200–520 页 |
| 同一页面,中止图片/媒体/字体请求 | 400–900 KB | 约 1,150–2,600 页 |
| 同一页面,复用已预热缓存的浏览器 | 150–500 KB | 约 2,000–7,000 页 |
| 屏蔽文档,仅保留 XHR/fetch | 5–50 KB | 约 20,000–200,000 次调用 |
为每个 URL 启动新浏览器会丢掉缓存、重新下载所有资源——这是 Puppeteer 账单超出预估数倍的最常见原因。在一个会话的多个页面之间复用同一个浏览器,积极拦截请求,只在真正出错的页面上截图。以上为商业网站的典型范围,请先对自己的目标计量,再确定预算。
| 带宽 | 价格 | 每 GB | 节省 |
|---|---|---|---|
| 1 GB | $7 | $7 | — |
| 5 GB | $35 | $7 | — |
| 10 GB | $68 | $6.80 | 3% |
| 25 GB | $150 | $6 | 14% |
| 50 GB | $283 | $5.66 | 19% |
| 100 GB | $500 | $5 | 29% |
适用国家
修改代理用户名中的一个参数即可切换国家——无需重新部署,也无需第二个账户。 IP 池规模因国家而异,也取决于您使用的是移动(mbl) 还是住宅(peer)IP 池;实时可用情况请查看各国家页面和您的控制台。
仅限合法用途
ProxyMobile 仅用于在您拥有或已获授权测试的系统上进行测量、质量保证和研究。购买带宽并不代表您获得了访问第三方系统的许可。您仍需自行遵守每个目标网站的服务条款、robots 指令和速率限制,以及适用于您的数据保护法律。
本场景的使用要求
- 只对您拥有或已获授权的网站进行自动化操作。
- 无头浏览器产生负载的速度远超人类——请主动限速,并遵守 Retry-After。
- 不得使用自动化批量注册账户、破解不该由您通过的验证码,或绕过访问控制。
- 尽可能避免合成流量混入他人的分析数据,也绝不要产生非预期的计费事件。
任何套餐均严禁
- 禁止撞库、盗用账户,或任何冒充他人进行身份验证的行为。
- 禁止绕过您未获授权测试的访问控制、付费墙或安全措施。
- 禁止收集您没有合法依据处理的个人数据。
- 禁止产生合理运营方会视为拒绝服务攻击的负载——请限速,遇到 429 时退避,并遵守 Retry-After。
用于欺诈、入侵或批量滥用的账户将被终止且不予退款,我们会配合有效的法律程序。完整条款请参阅我们的可接受使用政策。
Puppeteer常见问题
为什么把凭证写在 --proxy-server 的 URL 里不起作用?
Chrome 的这个参数只接受协议、主机和端口。写在其中的凭证会被忽略,上游返回 407,而无头 Chrome 会停在一个看不见的认证对话框上——所以症状是卡住而不是报错。请改用 page.authenticate 传入凭证。
每个页面都要调用 page.authenticate 吗?
是的。它按页面生效,而不是按浏览器。请在您创建的每个页面上调用它,并添加 browser.on("targetcreated") 钩子,让网站自行打开的页面也能完成认证。
一个浏览器中的不同页面可以使用不同代理吗?
通过启动参数做不到——Chrome 在整个进程范围内应用该参数,所以一个浏览器只有一个出口。请为每个身份启动单独的浏览器实例,并各自设置 -sid-。如果需要在单个浏览器中按上下文使用不同代理,Playwright 原生支持这一点。
Puppeteer 该用粘性会话还是轮换?
粘性会话。浏览器是身份的最小单位,在其整个生命周期内保存着 cookie 和会话状态,所以出口应在这段时间内保持固定。需要新身份时,用新的 sid 启动新的浏览器。
如何降低带宽消耗?
在导航之前启用 setRequestInterception,中止图片、媒体、字体和样式表请求,然后复用同一个浏览器以保持缓存有效。这通常能减少 70–80% 的流量。
可以配合 puppeteer-extra 和 stealth 插件使用吗?
可以——代理配置使用的是普通的 Puppeteer 启动和页面 API,所以封装了启动器的插件会自动继承。代理和指纹是两个独立的问题,而运营商 IP 解决的恰恰是指纹插件无法解决的那一个。
相关指南
用您自己的目标网站试一试
本页的带宽估算是如实给出的参考范围,而非承诺——唯一重要的数字,是您的目标网站实际消耗的流量。首次充值额外赠送 $2,足够您在确定预算之前,先实际计量一次运行。
