关于 headless-browser
面向开发者的 Oxylabs Headless Browser 技能指南,通过远程 Chrome 会话执行网页采集。内容涵盖 CDP 连接、会话管理、代理与地域参数,以及错误处理和调试流程。
主要功能
- 01通过 WebSocket 连接远程 Chrome
- 02Playwright、Puppeteer 和 CDP 指南
- 03重试与错误处理规则
- 04会话配置文件与恢复
- 05实时检查与录制说明
适用场景
- 01使用 Playwright 或 Puppeteer 采集网页
- 02处理会话重连和故障
- 03在多个任务间保留登录状态
- 04通过检查功能调试页面行为
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ oxylabs/ agent-skills --skill headless-browser安装后在 Claude Code 中输入/headless-browser确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
errors.mdexamples.mdparameters.mdtargets.mdscripts/playwright_scrape.jsplaywright_scrape.py详细介绍
Oxylabs 无头浏览器
内置反检测、代理轮换和地理定位功能的远程 Chrome 会话。
所有操作都不会在本地运行:通过 WebSocket 连接,使用你已经在用的 CDP 库控制浏览器,完成后关闭会话。本文件列出规则;详细信息见相关文件:
scripts/(可复制的模板)、parameters.md、errors.md、examples.md、targets.md。
1. 连接
| 项目 | 值 |
|---|---|
| 端点 | wss://USERNAME:[email protected] |
| 凭证 | OXY_UNBLOCKER_USERNAME / OXY_UNBLOCKER_PASSWORD(别名:OXY_HB_USERNAME / OXY_HB_PASSWORD) |
| 选项 | 仅使用 URL 查询参数,例如 ?p_cc=US&session_name=job-42(参见 parameters.md) |
| 库 | Playwright chromium.connectOverCDP(推荐)、Puppeteer puppeteer.connect、任何 CDP 客户端 |
| 控制面板 / 支持 | https://hb.oxylabs.io/dashboard · [email protected] |
以下规则可避免最常见的 401 错误:
- 使用
wss://。虽然也接受纯ws://,但它会以未加密方式发送密码。 - 使用字符串拼接构建 URL,并使用原始密码。不要将完整 URL 传给
new URL()或urllib.parse:它们会对密码进行百分号编码,导致身份验证失败。 - 使用控制面板中显示的完整用户名,包括
_ab12之类的后缀。 - URL 中无法发送包含
:的密码。请申请新密码,或自行发送Authorization: Basic标头(参见examples.md)。 - 身份验证会先于参数进行检查:先解决
401,再检查其他问题。
2. 快速入门
最简示例(Playwright,JavaScript):
const { chromium } = require("playwright");
const url = `wss://${process.env.OXY_UNBLOCKER_USERNAME}:${process.env.OXY_UNBLOCKER_PASSWORD}@hb.oxylabs.io?p_cc=US`;
const browser = await chromium.connectOverCDP(url, { timeout: 60000 });
try {
const page = await browser.contexts()[0].newPage(); // default context: backed by fingerprint, proxy, o_profile
await page.goto("https://example.com", { waitUntil: "domcontentloaded", timeout: 30000 });
console.log(await page.content());
} finally {
await browser.close(); // always: an unclosed session keeps its concurrency slot
}
实际使用时,请完整复制 scripts/playwright_scrape.js 或 scripts/playwright_scrape.py,而不要重新实现。这些脚本加入了本文件其他内容所依赖的五种行为:
- 带退避机制连接(基准间隔 1 秒,上限 60 秒,加入随机抖动,最多尝试 6 次),但仅针对可重试错误:
429、5xx、CDP_SESSION_IN_USE、CDP_NO_BROWSERS_AVAILABLE、CDP_BROWSER_OVERWORKED、CDP_BAD_PROXY、CDP_GENERAL_ERROR、超时。400/401/403表示请求有误:请修正,切勿原样重试。 - 从所有错误消息中隐藏密码后再记录;Playwright 会在错误消息中嵌入连接 URL。
- 默认阻止
image、stylesheet、media、font;这些内容会耗费时间,数据提取时并不需要。 - 在导航前注册监听器:响应标头
X-Error-Description用于标记页面流量中 Oxylabs 端的错误。 - 在
finally中调用browser.close(),并为整个任务设置截止时间,确保即使会话卡住也能执行到此步骤。
Puppeteer、Python 异步、原始 CDP、会话移交、配置文件、录制和扇出:参见 examples.md。
3. 会话和限制
| 限制(账户默认值) | 值 | 超出时 |
|---|---|---|
| 每秒新建会话数 | 10 | 429 CDP_SESSION_RATE_LIMIT_REACHED(空间启动间隔 >= 150 ms) |
| 并发会话数 | 100 | 429 CDP_MAX_CONCURRENT_SESSIONS_REACHED |
| 命名(可恢复)会话数 | 5 | 429 CDP_MAX_PERSISTENT_SESSIONS_REACHED |
已存储的配置文件(o_profile)数 | 5 | 403 profile limit reached (5 profiles maximum) |
| 录制数 | 10 | 403 recording limit reached (10 recordings maximum) |
| 并发检查查看器数 | 10 | CDP_VNC_MAX_CONCURRENT_SESSIONS_REACHED |
session_name(^[A-Za-z0-9-]{3,36}$)可在断开连接后 10 分钟内恢复会话。 使用它即表示启用keep_alive;切勿单独发送keep_alive=true(400 keep_alive requires session_name)。- 如果旧连接仍处于连接状态,重新连接会返回
429 CDP_SESSION_IN_USE:请先关闭旧连接。 - 每个会话的最长存续时间为 1 小时。请将长任务安排为多个会话。
- 被遗弃的会话会继续占用并发槽位(约 20 秒;命名会话则为完整的 10 分钟),之后可能导致无关的
429 CDP_MAX_CONCURRENT_SESSIONS_REACHED。关闭 Playwright/Puppeteer 对象即可释放。 - 即使命名会话仍可恢复,
browser.close()也会清除已打开的页面和 Cookie。要交接会话,请使用 Puppeteerbrowser.disconnect()(参见examples.md中的“恢复命名会话”)。需要在会话结束后保留的状态(登录信息、通行 Cookie)应放在o_profile中,而非依赖 keep-alive。 - 每种不同的参数组合都会单独配置:请在整个任务期间保持参数集稳定。
- 负载较高时,连接可能会排队,并在约一分钟后以
503 queue timeout结束:请退避并重试。 可通过支持渠道申请更高的限制。
4. 错误
错误分为三个渠道。握手阶段:HTTP 状态码和简短响应正文(Playwright:WebSocket error: <URL with password> <status>,随后是响应正文;Puppeteer:Unexpected server response: <status>)。连接后:WebSocket 会以代码 3000 和 CDP_* 原因关闭,只有原始客户端能看到;Playwright/Puppeteer 只会报告 Target closed,因此会话开始后的前几秒内发生的断连都应视为可重试。页面内:某条被拒绝的命令会返回 CDP 错误 1337。对于页面流量,带有 X-Error-Description 的响应表示 Oxylabs 网络错误(重试);不带此标头的拦截页面则是目标网站的决定(更改方案,不要重试)。
connect failed?
├─ 401 ............ fix credentials/scheme, do not retry
├─ 400/403/409 .... fix the named parameter, do not retry unchanged (409: wait 30 s+ for the other session)
├─ 429 ............ backoff; if MAX_CONCURRENT: hunt for unclosed sessions
└─ 5xx/503 ........ backoff, up to ~2 min total
session dropped (close 3000)?
└─ new session with backoff; rotate sticky id on CDP_BAD_PROXY
navigate failed with 1337 Invalid target?
└─ stop; restricted target (section 7)
page shows block / 403 wall?
├─ X-Error-Description present .... Oxylabs network issue: backoff + retry
└─ absent ......................... target decision: change identity, geo, device, pacing (section 5)
每条消息的原因和解决方法:errors.md。
5. 目标安全性(DataDome 及类似服务)
大多数任务的默认参数集:仅 p_cc。 每个会话都会获得全新的指纹和住宅 IP,这正是单次抓取和独立页面并行抓取所需的。粘性 IP 和已存储的配置文件都是针对特定需求才选择使用的工具,绝不是默认设置。
受保护目标的操作顺序。 先编写普通脚本并确保其运行成功:每页使用一个全新会话,选择正确的地理位置和设备,按真人节奏操作,然后再按下方阶梯逐步升级。只有在尝试完阶梯后脚本仍然失败,才向用户建议使用持久配置文件(采用下方的设置端/使用端模式,并说明它为何可能有效以及代价:需要一个设置步骤,配置文件上限为 5 个),并且只有在用户同意后才实施。切勿自行添加配置文件或粘性 ID。
| 需求 | 添加 | 不适用于 |
|---|---|---|
| 多个连接必须看起来像同一位访客(登录、购物车、持续时间超过一个会话的流程) | proxy_resi_ses_id + proxy_resi_ses_time | 每个会话只访问一个页面 |
| Cookie 或登录状态必须在不同任务间保留(DataDome 放行状态、经过身份验证的抓取) | 用户同意后,由一次设置运行预先准备 o_profile | 首次尝试;不设拦截即可正常提供内容的目标 |
| 在 10 分钟内恢复同一个浏览器 | session_name | 其他所有情况 |
使用这些参数时,它们的组合代表一个身份。务必保持一致:
setup, exactly once : ?o_profile=acme-us-01&o_profile_save=true&p_cc=US&proxy_resi_ses_id=acmeus01&proxy_resi_ses_time=30
consumers, any number: ?o_profile=acme-us-01&p_cc=US&proxy_resi_ses_id=acmeus01&proxy_resi_ses_time=30
- 一个运行实例写入配置文件,其他实例读取。 设置运行实例是唯一会发送
o_profile_save=true的连接:它获取 Cookie(通过入口页面、登录),验证页面,然后关闭。使用运行实例仅发送o_profile=<name>:只读,不加写锁,也不会出现409。切勿由使用运行实例“补充”配置文件;如果配置文件失效,请使用新名称重新运行设置。在生产环境中,应由一个设置服务准备并验证配置文件,由一个使用服务仅负责使用它们(examples.md,“配置文件设置和使用运行”)。 proxy_resi_ses_id+proxy_resi_ses_time会固定出口 IP(最长 1440 min)。固定 ID 会禁用自动代理重试:遇到CDP_BAD_PROXY时,请更换为新的 ID。- 对于已有 Cookie 的身份,切勿更改
p_cc/p_city/p_state。 请新建配置文件和粘性 ID。 - 让交互方式匹配
p_device:mobile= 轻触、小幅滚动、不悬停;desktop(默认值)= 采用相反的操作方式。切勿自行设置视口或设备指标;指纹由服务管理。 - 按真人节奏操作:页面加载间隔 3 到 8 s,点击前先滚动,每个身份一次只访问一个页面。并行运行多个身份,而不是打开并行标签页。
- 被拦截时的升级步骤,每个全新连接逐级尝试:全新会话 → 扩大地理范围(移除
p_city)→p_device=mobile→ 放慢速度 → 检查(第 6 节)→ 向用户建议使用持久配置文件 → 停止并报告。重复完全相同的请求不算升级。
各供应商的拦截特征、注意事项表,以及新受保护目标的起始值:targets.md。
6. 运维规范
- 调试。 有两种工具;每当用户询问如何调试、浏览器正在做什么,或运行为何失败时,都要告知他们这两种工具:实时检查(通过 CDP 命令
__session_id获取会话 ID,打开https://hb.oxylabs.io/novnc/?id=<id>,并在会话运行时查看)和录制(record=true& record_name=<job>会将会话视频保存下来,以便之后在https://hb.oxylabs.io/dashboard中回放;上限为 10 个,可在那里删除旧视频)。两者默认均关闭。在同一目标上连续失败 3 次后,请自行使用这两种工具,确认页面实际显示的内容。代码片段见examples.md中的 "Session id, live inspection and recording"。 - 超时。 连接超时为 60 s,导航超时为 30 s,另有整体任务截止时间。
- 日志记录。 切勿记录连接 URL 或原始错误消息;记录参数集和会话 ID。
- 上下文。 使用
browser.contexts()[0]。newContext()与配置文件存储和指纹调优隔离。
7. 受限目标
默认禁止访问;需通过账户经理进行简短的 KYC 才能访问:娱乐和流媒体、银行和金融、政府网站、游戏平台、票务、网页邮箱、广告网络、第三方 IP 检查器。使用 https://ip.oxylabs.io/location 验证出口 IP 和地理位置。访问受限目标时,Page.navigate 会因 CDP 错误 1337 Invalid target 而失败。
另请参阅:scripts/(完整的 Playwright 模板、JS 和 Python)、parameters.md(所有参数及其验证)、errors.md(所有消息)、examples.md(Puppeteer、Python 异步、原始 CDP、重新连接、配置文件、录制、扇出)、targets.md(拦截检测、DataDome 操作手册)。