Cloudflare Browser Run 能力范围、运行原理与使用方式
AI 参与说明(Agent:Codex):本文根据 Cloudflare Browser Run 官方文档辅助整理,覆盖产品能力、协议、API、会话管理和费用边界。资料核验日期为 2026-10-20;未取得任务级模型与 reasoning effort 运行记录。
Browser Run 可以为应用和 Agent 提供远程 Chrome,完成网页提取、自动化操作、实时观看和人工接管。一次性输出适合 Quick Actions,连续交互适合 Browser Sessions;需要完整 Linux 桌面时,应使用 Containers 或 Sandboxes。
| 英文术语 | 中文名称 | 简要解释 |
|---|---|---|
| Browser Run | Browser Run | Cloudflare 托管的远程 Chrome 服务,原名 Browser Rendering。 |
| Quick Actions | 快捷操作 | 用一次请求完成截图、PDF 或内容提取等常见任务。 |
| Browser Sessions | 浏览器会话 | 保留浏览器实例,通过多个命令完成有状态的交互。 |
| Chrome DevTools Protocol(CDP) | Chrome 开发者工具协议 | Chrome DevTools 使用的远程控制协议,可导航、检查和操作网页。 |
| Live View | 实时视图 | 在浏览器中观看并操作远程页面的托管界面。 |
| Human in the Loop | 人工参与 | 自动化遇到需要人工判断或输入的步骤时,把操作交给人,再恢复自动化。 |
| Browser Context | 浏览器上下文 | 同一浏览器中的独立状态空间,用于隔离 Cookie、缓存和本地存储。 |
| Guardrails | 访问限制 | 约束会话能够访问的 HTTP 和 HTTPS 主机名。 |
什么时候需要 Browser Run
截图服务、网页转 PDF、抓取动态页面、浏览器测试和网页 Agent,都需要真正运行网页 JavaScript 的浏览器。Browser Run 把 Chrome 的启动、托管和服务接入交给 Cloudflare,应用通过 API 操作它。它既能返回一次截图,也能维持一个有多个标签页的会话,让 Agent 连续操作,并让人实时观看和接管。
只需要一次截图或页面内容,用 Quick Actions;需要登录、搜索、填写表单或跨页操作,用 Browser Sessions。完整 Linux 桌面、终端和任意原生软件则属于 Containers 或 Sandboxes 的范围。Browser Run 总览
Browser Run executes Chrome remotely. Your application controls it through APIs; Chrome does not run inside the Worker isolate.
部署时,Worker 可以保存业务逻辑、鉴权和任务路由,Chrome 在远程浏览器服务中运行。应用也可以放在本地脚本、CI 或其他服务器上,通过 CDP 连接同一个服务,不要求把整个后端迁到 Cloudflare。CDP
Quick Actions 与 Browser Sessions
| 需求 | 选择 | 需要编写的逻辑 |
|---|---|---|
| 网页截图、生成 PDF | Quick Actions | 指定 URL 或 HTML、输出和等待参数。 |
| 获取 HTML、Markdown、链接或指定元素 | Quick Actions | 描述要提取的内容。 |
| 按提示或 Schema 提取结构化数据 | Quick Actions /json | 给出任务及结果约束,评估提取结果。 |
| 批量发现并抓取网站页面 | Quick Actions /crawl | 提交异步任务、查询结果和处理逐页状态。 |
| 登录后执行多步操作 | Browser Sessions | 导航、定位元素、输入、等待和失败处理。 |
| Agent 自动浏览并展示操作过程 | Browser Sessions | Agent 工具、会话协调和 Live View。 |
| 浏览器端测试 | Browser Sessions | Playwright 或 Puppeteer 脚本及断言。 |
Quick Actions 目前包含 /content、/screenshot、/pdf、/markdown、/snapshot、/accessibilityTree、/scrape、/json、/links 和 /crawl。其中 /snapshot 是一次采集多种页面输出的接口,不是保存浏览器进程或容器磁盘。/crawl 仅支持 REST API,其他 Quick Actions 也可以经 Worker 的 env.BROWSER.quickAction() 调用。Quick Actions
Browser Sessions 可以通过 Puppeteer、Playwright、CDP、Stagehand 或 MCP 集成控制。标准脚本适合操作路径明确的任务;AI 方式可以帮助理解意图和选择元素,但页面状态判断、结果核验和失败恢复仍属于应用逻辑。服务提供浏览器,不自动替应用完成业务任务。接入选择
一次请求怎样变成浏览器操作
Quick Actions 把常见操作封装成 HTTP 请求,平台管理浏览器资源和输出。Browser Sessions 则把会话管理与具体操作分开:HTTP 接口用于创建、查询和关闭会话,CDP WebSocket 用于向浏览器发送命令并接收事件。
flowchart TD
APP["应用或 Agent"] --> CHOICE{"是否需要连续交互"}
CHOICE -->|否| QUICK["Quick Actions HTTP 或 Worker Binding"]
CHOICE -->|是| SESSION["创建或复用 Browser Session"]
QUICK --> OUTPUT["截图 PDF HTML Markdown JSON"]
SESSION --> CDP["CDP WebSocket"]
CDP --> CHROME["远程 Chrome 与多个标签页"]
CHROME --> SITE["目标网站"]
CHROME --> LIVE["Live View"]
HUMAN["用户"] -->|观看或操作| LIVE
CDP 与 Chrome DevTools 使用同一套协议。Puppeteer 和 Playwright 把导航、元素定位、截图等操作封装成高层 API;开发者也可以直接发送 CDP 命令。一个 Browser Session 对应一个远程 Chrome 实例,可以包含多个标签页。CDP 使用 target 表示可调试对象,页面 target 通常对应一个标签页。CDP 原理
Worker 内的 browser binding 还提供 acquire()、connectSession()、launch()、listSessions()、closeSession() 和 devtools 等类型化接口。这里 binding 的 launch() 返回供 CDP 客户端连接的对象,与 @cloudflare/playwright 返回高层 Browser 对象的 launch() 不应混为一谈。Browser binding API
三种最小接入方式
以下示例依据官方接口整理,没有调用真实 Cloudflare 账户执行。REST 和外部 Node.js 示例需要账户 ID,以及具有 Browser Run 编辑权限的 API Token;部分文档或控制台仍使用旧名称 Browser Rendering - Edit。Worker binding 示例不需要把账户 API Token 写进代码。
用 REST 截图
准备 ACCOUNT_ID 和 CLOUDFLARE_API_TOKEN 环境变量后执行:
curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/browser-run/screenshot" \
--fail-with-body \
--request POST \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
--header "Content-Type: application/json" \
--data '{"url":"https://example.com"}' \
--output screenshot.png
预期得到 screenshot.png。接口接受 url 或 html,还支持 viewport、整页截图、指定元素、Cookie、HTTP Basic Auth、自定义请求头和等待参数。动态页面应等待目标元素或业务状态,不要仅凭页面开始加载就认定内容已完整渲染。/screenshot 参数
产品更名后,当前端点使用 /browser-run。部分旧示例仍保留 /browser-rendering,SDK 也可能保留 browserRendering 属性。阅读时应按具体接口文档核对路径和字段,避免只替换显示名称便假设所有标识同步更名。
从 Node.js 使用 Playwright
这条路线适合已有 Node.js 后端、脚本和 CI。安装不附带本地浏览器的 playwright-core:
npm install playwright-core
把以下内容保存为 browser-run.mjs。环境变量使用 CF_ACCOUNT_ID 和 CF_API_TOKEN:
import { chromium } from "playwright-core";
const accountId = process.env.CF_ACCOUNT_ID;
const apiToken = process.env.CF_API_TOKEN;
if (!accountId || !apiToken) {
throw new Error("Set CF_ACCOUNT_ID and CF_API_TOKEN before running.");
}
const base =
`https://api.cloudflare.com/client/v4/accounts/${accountId}/browser-run`;
const headers = { Authorization: `Bearer ${apiToken}` };
const acquired = await fetch(`${base}/devtools/browser?keep_alive=600000`, {
method: "POST",
headers
});
if (!acquired.ok) throw new Error(`Acquire failed: ${acquired.status}`);
const session = await acquired.json();
if (typeof session.sessionId !== "string") {
throw new Error("Acquire response did not include a sessionId.");
}
const endpoint = session.webSocketDebuggerUrl ??
`${base.replace("https:", "wss:")}/devtools/browser/${session.sessionId}`;
let browser;
try {
browser = await chromium.connectOverCDP(endpoint, {
headers
});
const context = browser.contexts()[0] ?? await browser.newContext();
const page = context.pages()[0] ?? await context.newPage();
await page.goto("https://example.com");
console.log(await page.title());
await page.screenshot({ path: "screenshot.png" });
} finally {
try {
if (browser) await browser.close();
} finally {
const closed = await fetch(`${base}/devtools/browser/${session.sessionId}`, {
method: "DELETE",
headers
});
if (!closed.ok && closed.status !== 404) {
throw new Error(`Close failed: ${closed.status}`);
}
}
}
运行 node browser-run.mjs,预期打印页面标题并保存截图。创建接口直接返回 sessionId 和可选的 webSocketDebuggerUrl,不使用通用 result 封套。此例结束时既关闭客户端,也通过 HTTP DELETE 结束服务端会话;如果会话已经关闭而返回 404,则视为已释放。浏览器操作发生在远程 Chrome,本地只运行控制逻辑。Playwright over CDP、HTTP 会话管理、创建接口响应
在 Worker 中启动 Browser Session
Worker 内使用适配 Cloudflare 的 @cloudflare/playwright:
npm create cloudflare@latest -- browser-run-demo
cd browser-run-demo
npm install @cloudflare/playwright
创建项目时选择 Worker 和 TypeScript。将 wrangler.jsonc 中对应配置设为:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "browser-run-demo",
"main": "src/index.ts",
"compatibility_date": "2026-10-20",
"compatibility_flags": ["nodejs_compat"],
"browser": {
"binding": "BROWSER",
"remote": true
}
}
src/index.ts:
import { launch } from "@cloudflare/playwright";
interface Env {
BROWSER: Fetcher;
}
export default {
async fetch(_request: Request, env: Env): Promise<Response> {
const browser = await launch(env.BROWSER);
try {
const page = await browser.newPage();
await page.goto("https://example.com");
return Response.json({ title: await page.title() });
} finally {
await browser.close();
}
}
} satisfies ExportedHandler<Env>;
运行 npx wrangler dev,访问本地 Worker 地址,预期返回包含标题的 JSON。remote: true 让本地控制逻辑连接真实远程服务,因此会消耗浏览器额度。确认行为后可用 npx wrangler deploy 部署。Workers Playwright
若任务只是截图,不需要安装 Playwright,可以让 Worker 直接返回 Quick Actions 响应:
export default {
async fetch(_request, env) {
return env.BROWSER.quickAction("screenshot", {
url: "https://example.com"
});
}
};
quickAction() 要求 compatibility date 至少为 2026-03-24,本地使用 remote: true 或 wrangler dev --remote。它管理操作所需的会话,不需要应用自行保存 Session ID。Quick Actions binding
接入已有 Agent
已有 MCP 客户端可以通过 chrome-devtools-mcp 接入 Browser Run。MCP server 将工具调用转换为 CDP 命令,Agent 因而能够导航、截图、检查 Console 和调用相应调试工具。配置中的 --wsEndpoint 指向 Browser Run,--wsHeaders 提供服务端认证;Token 不应进入网页前端或公开配置。
通过现成的工具适配层,可以先验证 Agent 能否完成真实网页任务。需要自定义操作权限、并发协调或人工交接时,再在应用侧补充任务状态与控制逻辑。MCP 连接本身不提供业务授权,也不保证网页操作结果正确。MCP 接入
Live View 与 Human in the Loop
Live View 提供三种界面:tab 展示并控制单个页面,full 展示浏览器界面和打开的标签页,devtools 展示 Elements、Console 等调试面板。可从控制台、REST 或 CDP 获取 devtoolsFrontendUrl。默认五分钟有效期约束开始连接的时间,可扩展至一小时;已经建立的连接可以在会话仍存活时继续使用。
链接包含签名 JWT,拿到完整链接的人就可能获得对应访问能力。只读入口可以通过 REST 的 guardrails: { mode: "readonly" } 生成,但只限制该连接;Agent 通过其他连接仍能操作会话。API Token 始终留在可信服务端。Live View
已有会话时,可用下面的请求生成入口。SESSION_ID 必须来自当前应用拥有并允许该用户访问的会话:
curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/browser-run/devtools/browser/$SESSION_ID/live_view" \
--fail-with-body \
--request POST \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
--json '{"mode":"tab","expiresInMs":300000}'
应用取得响应中的 devtoolsFrontendUrl 后,可把它展示为用户入口。服务端生成链接前仍需验证会话归属;链接持有者的访问能力不能替代应用的用户鉴权。
Human in the Loop 在此基础上增加交接状态。应用可以等待人工登录、输入敏感信息或检查结果,再决定是否继续。结构化交接的顺序如下:
sequenceDiagram
participant A as Agent 控制程序
participant B as Browser Session
participant H as 用户
A->>B: 订阅 Cloudflare.handoffComplete
A->>B: Cloudflare.getLiveView mode tab
B-->>A: 返回 devtoolsFrontendUrl
A-->>H: 展示操作入口与所需任务
A->>B: Cloudflare.handoff instructions timeout
H->>B: 打开 Live View 并执行操作
H->>B: 选择 Done 或 Failed
B-->>A: handoffComplete success reason
alt 人工步骤成功
A->>B: 验证页面状态并继续
else 失败或超时
A->>A: 记录原因并结束或转人工处理
end
要先订阅完成事件,再发起 Cloudflare.handoff,避免漏掉快速完成的结果。结构化交接只支持 mode: "tab";timeout 显式设置时最大 30 分钟,不设置则没有这一层交接超时,浏览器本身仍受会话生命周期约束。用户点击 Done 是继续处理的信号,涉及业务结果时仍应核验页面状态。Human in the Loop
Live View、Human in the Loop 和 Session Recording 当前均标为 Beta。依赖这些功能上线时,应把它们的状态变化和异常恢复纳入应用设计,不能仅凭能生成一个观看链接就认定完整协作流程已经完成。
Session Recording 与调试
Session Recording 使用 rrweb 捕获 DOM 变化、鼠标键盘事件和导航,产物是 JSON 事件,适合回放和检查自动化过程。它不等同于连续屏幕录像,也不应被当成所有视觉内容都能完整还原的保证。
Session recording stores structured browser events, not a video stream.
录制必须在首次获取会话时启用:SDK 使用 recording: true,CDP URL 使用 recording=true。重连已有会话时不能补开。会话结束后才完成录制,可在控制台 Browser Run 的 Runs 中回放,也可用 Session ID 访问 /browser-run/recording/{session_id}。刚结束时可能尚在整理并暂时返回 404,应按文档重试。Session Recording
Playwright trace 是另一种调试材料,包含操作、页面快照、截图和控制台信息,可以生成 trace.zip 用于 Trace Viewer。它与平台 Session Recording 的入口、产物和使用方式不同;应按排查目标选择,不要将两者混称为视频。Playwright Trace
会话复用与长期状态
默认空闲超时为 60 秒,keep_alive 可以延长到 20 分钟。持续活跃的会话没有固定最大生命周期,但服务升级仍可能关闭会话。
The keep_alive option sets an inactivity timeout, not a maximum session lifetime.
十分钟的 keep_alive 不代表任务只能运行十分钟,也不代表浏览器状态已经持久化。复用时保存 Session ID,重连前检查会话是否存在;失效后重新创建,并从应用保存的进度恢复。任务完成后若不再复用,应明确关闭会话,否则等待空闲超时的时间仍会消耗额度。Limits
多个标签页复用同一个浏览器实例并共享资源预算,页面过重或标签页过多仍可能使会话不稳定。Browser Context 可以隔离 Cookie、缓存和存储,但不承诺进程或容器隔离。共享会话能减少创建次数和冷启动,适合可信任务池;需要独立配置或更强隔离时,应使用不同会话并核对平台的隔离保证。Durable Object 可以路由同一任务的请求并协调冲突,但其持久化存储不会让远程 Chrome 的内存跨重启保存。Reuse Sessions、FAQ
登录状态也应显式管理。Playwright 可以导出 storageState 并在新 Context 中恢复,官方示例将 Cookie、localStorage 和 IndexedDB 状态存入 KV。应按用户和任务隔离这些数据,并把它们视为具有账户访问能力的敏感材料;保存结果文件和任务进度则可用 R2、Durable Objects 等产品。Storage State
网络访问与 Guardrails
Session Guardrails 限制 Browser Session 的 HTTP 和 HTTPS 主机名,启动时确定,并在整个会话中保持不变。allowedDomains 最多 50 条,allowedDomainSets 最多 4 个;省略两者表示不限制,空 allowedDomains: [] 则禁止外部 HTTP/HTTPS。页面可能依赖第三方脚本、CDN、字体、API 和登录跳转,这些域名也必须纳入策略。
Guardrails 当前是 Beta,且不适用于 Quick Actions。它约束整个会话的目标主机,Live View 的 readonly 只约束一个观看连接,两者不能互相替代。Guardrails
需要访问受控私有服务时,可以通过 outboundByHost 把指定主机名的浏览器请求交给 service binding 连接的 Worker。该 Worker 再补充认证、访问目标服务或转换响应;目标主机名不要求有公网 DNS。它提供了受控路由入口,不表示 Browser Run 默认能直连任意内网地址。Outbound Workers
Browser Run 请求带有不可移除的来源标识和 Web Bot Auth 签名。更换 User-Agent 不会隐藏身份;人工接管也不会把它变成普通用户设备的网络请求。目标网站可能仍阻止访问,服务不提供绕过 CAPTCHA、Turnstile 或其他机器人保护的保证,也不支持逐请求 IP 轮换。Automatic Request Headers、FAQ
抓取网站时的额外约束
/crawl 是异步网站抓取入口,会从起始 URL、sitemap 和页面链接发现内容。它遵守 robots.txt、crawl-delay 和 Content Signals;没有指定 crawl-delay 时,同域请求默认间隔 0.5 秒。禁止抓取的 URL 会在结果中标记状态,任务完成也不代表每一页都成功。
当前 /crawl 的 crawlPurposes 和 contentUse 会影响任务能否启动。crawlPurposes 使用 search、ai-input、ai-train,默认声明全部三项。目标站点允许搜索、禁止训练,而实际任务只建立搜索索引时,应声明 crawlPurposes: ["search"];若还要把内容送入模型,则必须按实际用途声明并满足对应限制。
contentUse 接受 reference 或 full,默认 full,用于声明内容使用层级。站点要求 use=reference 时,默认 full 会被拒绝,需按实际用途设为 reference;站点要求 use=immediate 时,所有 /crawl 请求都会被拒绝,因为该接口保留抓取结果,不接受即时、无留存用途。用途声明不能替代业务许可;上述执行行为属于 /crawl,不应推广为所有 CDP 命令统一具有的策略。/crawl 行为
限额与费用怎样估算
以下为核验日期的默认技术限额,不等于包含额度:
| 项目 | Workers Free | Workers Paid |
|---|---|---|
| 浏览器时间 | 每日 10 分钟 | 无固定用量上限,按价格计费 |
| Browser Sessions 并发实例 | 3 | 200,可申请提高 |
| 新浏览器创建速率 | 每 20 秒 1 个 | 每秒 3 个 |
| Quick Actions 请求速率 | 每 10 秒 1 个 | 每秒 30 个 |
| 默认空闲超时 | 60 秒 | 60 秒 |
浏览器实例和创建速率按实例统计,打开更多标签页不会增加这两项计数,但会增加同一会话的资源压力。200 是技术并发上限,不能理解为付费套餐免费包含 200 个并发。Limits
Workers Paid 每月包含 10 browser-hours,超出部分为 0.09 美元每小时。Browser Sessions 另按每日峰值并发的月平均数计费,包含 10 个,超过部分每个每月 2 美元。Quick Actions 不收取并发费;Worker、存储、AI 提取和模型等产品的费用仍需分别计算。Pricing
假设一个月使用 100 browser-hours,且每日峰值并发的月平均数为 15,超额浏览器时间为 (100 − 10) × 0.09 = 8.10 美元,并发超额为 (15 − 10) × 2 = 10 美元,合计 18.10 美元,尚未包含上述其他产品费用。这是便于复算的假设,不是任意 15 并发任务的固定报价。
人工等待也占用活跃会话,长 keep_alive 会延长闲置资源释放时间。应用应同时观察 browser-hours、峰值并发和任务成功率。Quick Actions 响应的 X-Browser-Ms-Used 可用于统计单次浏览器耗时,再用真实任务样本估算单位成本。Quick Actions 用量
上线前按真实任务验收
先选一条完整业务路径,例如“打开页面、登录、查询、填写、人工确认、保存结果”,再检查下列结果:
| 验收项 | 操作 | 通过标准 |
|---|---|---|
| 网站可达 | 用实际账户和目标域名运行 | 能区分网站拒绝、认证失败、页面未就绪和服务限额。 |
| 等待逻辑 | 模拟较慢页面和动态加载 | 依据页面业务状态继续,不因固定等待结束而误判完成。 |
| 人工交接 | 分别选择 Done、Failed,并触发超时 | Agent 按结果进入对应分支,失败时不会继续执行后续操作。 |
| 会话恢复 | 主动结束会话后重连任务 | 能识别失效、重建会话并恢复可恢复的进度。 |
| 数据隔离 | 用两个用户的独立状态运行 | Cookie、登录状态、观看入口和产物不会串用。 |
| 容量与费用 | 增加并发和单会话标签页数量 | 不超过账户限额,能观察内存相关失败和实际用量。 |
任务只涉及网页时,Browser Run 能减少浏览器基础设施的维护;需要完整桌面或原生工具时,应使用 Containers/Sandboxes。需要同时操作代码、文件和网页的 Agent,也可以组合 Computer Workspace 与 Browser Run,分别负责长期工作文件和浏览器交互。