关于 cloudflare-browser-rendering
为使用 Cloudflare Browser Rendering 的开发者提供浏览器自动化参考,涵盖 Puppeteer 与 Playwright 的 Worker 绑定、会话管理和常见问题处理。
主要功能
- 01Puppeteer 与 Playwright 用法
- 02浏览器会话复用与隔离
- 03页面截图与 PDF 生成
- 04动态网页抓取与交互
- 05常见错误与限制说明
适用场景
- 01为网页生成截图或 PDF
- 02抓取动态网页内容
- 03自动化表单和前端测试
MCP 相关
文档提及 Playwright MCP 支持及 Playwright MCP 服务端,但本技能主要介绍 Workers 绑定下的浏览器自动化。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jezweb/ claude-skills --skill cloudflare-browser-rendering安装后在 Claude Code 中输入/cloudflare-browser-rendering确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.md.claude-plugin/plugin.jsonreferences/common-errors.mdpricing-and-limits.mdpuppeteer-vs-playwright.mdsession-management.mdrules/cloudflare-browser-rendering.mdscripts/check-versions.shtemplates/ai-enhanced-scraper.tsbasic-screenshot.tspdf-generation.tsplaywright-example.tsscreenshot-with-kv-cache.tssession-reuse.tsweb-scraper-basic.tsweb-scraper-batch.ts详细介绍
Cloudflare Browser Rendering - 完整参考
用于构建 Cloudflare Browser Rendering 浏览器自动化工作流的生产就绪知识领域。
状态:生产就绪 ✅ 最后更新:2026-01-21 依赖项:cloudflare-worker-base(用于 Worker 设置) 最新版本:@cloudflare/[email protected]、@cloudflare/[email protected]、[email protected]
近期更新(2025):
- 2025 年 9 月:Playwright v1.55 正式发布,支持 Stagehand 框架(Workers AI),/links 新增 excludeExternalLinks 参数
- 2025 年 8 月:计费正式发布(8 月 20 日),本地开发中新增 /sessions 端点,新增 X-Browser-Ms-Used 标头
- 2025 年 7 月:Playwright v1.54.1 + MCP v0.0.30,支持 Playwright 本地开发([email protected]+),同步 Puppeteer v22.13.1,/content 返回标题,/json 新增 custom_ai 参数,/screenshot 默认视口为 1920x1080
- 2025 年 6 月:自动包含 Web Bot Auth 标头
- 2025 年 4 月:推出 Playwright 支持,引入免费套餐
目录
快速入门(5 分钟)
1. 添加 Browser 绑定
wrangler.jsonc:
{
"name": "browser-worker",
"main": "src/index.ts",
"compatibility_date": "2023-03-14",
"compatibility_flags": ["nodejs_compat"],
"browser": {
"binding": "MYBROWSER"
}
}
为什么需要 nodejs_compat? Browser Rendering 需要 Node.js API 和 polyfill。
2. 安装 Puppeteer
npm install @cloudflare/puppeteer
3. 截取第一张屏幕截图
import puppeteer from "@cloudflare/puppeteer";
interface Env {
MYBROWSER: Fetcher;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { searchParams } = new URL(request.url);
const url = searchParams.get("url") || "https://example.com";
// Launch browser
const browser = await puppeteer.launch(env.MYBROWSER);
const page = await browser.newPage();
// Navigate and capture
await page.goto(url);
const screenshot = await page.screenshot();
// Clean up
await browser.close();
return new Response(screenshot, {
headers: { "content-type": "image/png" }
});
}
};
4. 部署
npx wrangler deploy
在以下地址测试:https://your-worker.workers.dev/?url=https://example.com
重要提示:
- 始终将
env.MYBROWSER传递给puppeteer.launch()(不能是 undefined) - 完成后始终调用
browser.close()(或使用browser.disconnect()以复用会话) - 使用
nodejs_compat兼容性标志
Browser Rendering 概述
什么是 Browser Rendering?
Cloudflare Browser Rendering 在 Cloudflare 的全球网络上提供无头 Chromium 浏览器。使用 Puppeteer 和 Playwright 等熟悉的工具自动执行浏览器任务:
- 屏幕截图 - 捕获网页的视觉快照
- PDF 生成 - 将 HTML/URL 转换为 PDF
- 网页抓取 - 从动态网站提取内容
- 测试 - 自动执行前端测试
- 爬取 - 浏览多页面工作流
两种集成方式
| 方法 | 最适合 | 复杂度 |
|---|---|---|
| Workers 绑定 | 复杂自动化、自定义工作流、会话管理 | 高级 |
| REST API | 简单的屏幕截图/PDF 任务 | 简单 |
本文介绍 Workers 绑定(使用完整 Puppeteer/Playwright API 的高级方法)。
Puppeteer 与 Playwright
| 特性 | Puppeteer | Playwright |
|---|---|---|
| API 熟悉度 | 最受欢迎 | 采用率不断增长 |
| 软件包 | @cloudflare/[email protected] | @cloudflare/[email protected] |
| 会话管理 | ✅ 高级 API | ⚠️ 基础 |
| 浏览器支持 | 仅 Chromium | 仅 Chromium(暂不支持 Firefox/Safari) |
| 最适合 | 屏幕截图、PDF、抓取 | 测试、前端自动化 |
建议:大多数情况下使用 Puppeteer。如果你已经在使用 Playwright 进行测试,它会是理想选择。
Puppeteer API 参考
核心 API(完整参考:https://pptr.dev/api/):
全局函数:
puppeteer.launch(env.MYBROWSER, options?)- 启动新浏览器(重要:必须传入绑定)puppeteer.connect(env.MYBROWSER, sessionId)- 连接到现有会话puppeteer.sessions(env.MYBROWSER)- 列出正在运行的会话puppeteer.history(env.MYBROWSER)- 列出最近的会话(已打开 + 已关闭)puppeteer.limits(env.MYBROWSER)- 检查账户限制
浏览器方法:
browser.newPage()- 创建新标签页(优先于启动新浏览器)browser.sessionId()- 获取会话 ID 以供复用browser.close()- 终止会话browser.disconnect()- 保持会话运行,以供复用browser.createBrowserContext()- 创建隔离的无痕上下文(使用独立的 Cookie/缓存)
页面方法:
page.goto(url, { waitUntil, timeout })- 导航(对于动态内容,使用"networkidle0")page.screenshot({ fullPage, type, quality, clip })- 捕获图像page.pdf({ format, printBackground, margin })- 生成 PDFpage.evaluate(() => ...)- 在浏览器中执行 JS(提取数据、XPath 变通方案)page.content()/page.setContent(html)- 获取/设置 HTMLpage.waitForSelector(selector)- 等待元素page.type(selector, text)/page.click(selector)- 表单交互
重要模式:
// Must pass binding
const browser = await puppeteer.launch(env.MYBROWSER); // ✅
// const browser = await puppeteer.launch(); // ❌ Error!
// Session reuse for performance
const sessions = await puppeteer.sessions(env.MYBROWSER);
const freeSessions = sessions.filter(s => !s.connectionId);
if (freeSessions.length > 0) {
browser = await puppeteer.connect(env.MYBROWSER, freeSessions[0].sessionId);
}
// Keep session alive
await browser.disconnect(); // Don't close
// XPath workaround (not directly supported)
const data = await page.evaluate(() => {
return new XPathEvaluator()
.createExpression("/html/body/div/h1")
.evaluate(document, XPathResult.FIRST_ORDERED_NODE_TYPE)
.singleNodeValue.innerHTML;
});
Playwright API 参考
状态:GA(2025 年 9 月)- 支持 Playwright v1.55、MCP v0.0.30,支持本地开发([email protected]+)
安装:
npm install @cloudflare/playwright
配置要求(2025 年更新):
{
"compatibility_flags": ["nodejs_compat"],
"compatibility_date": "2025-09-15" // Required for Playwright v1.55
}
基本用法:
import { chromium } from "@cloudflare/playwright";
const browser = await chromium.launch(env.BROWSER);
const page = await browser.newPage();
await page.goto("https://example.com");
const screenshot = await page.screenshot();
await browser.close();
Puppeteer 与 Playwright 对比:
- 导入:
puppeteer与来自 "@cloudflare/playwright" 的{ chromium } - 会话 API:Puppeteer 提供高级会话管理(sessions/history/limits),Playwright 提供基础管理
- 自动等待:Playwright 内置自动等待,Puppeteer 需要手动调用
waitForSelector() - MCP 支持:Playwright MCP v0.0.30(2025 年 7 月),提供 Playwright MCP 服务
- 最新版本:支持 Playwright v1.57(2026 年 1 月更新)
建议:会话复用时使用 Puppeteer。迁移现有测试或需要 MCP 集成时使用 Playwright。
官方文档:https://developers.cloudflare.com/browser-rendering/playwright/
会话管理
原因:启动新浏览器速度慢且会占用并发限额。复用会话可加快响应、降低并发用量并提高资源利用率。
会话复用模式(重要)
async function getBrowser(env: Env): Promise<Browser> {
const sessions = await puppeteer.sessions(env.MYBROWSER);
const freeSessions = sessions.filter(s => !s.connectionId);
if (freeSessions.length > 0) {
try {
return await puppeteer.connect(env.MYBROWSER, freeSessions[0].sessionId);
} catch (e) {
console.log("Failed to connect, launching new browser");
}
}
return await puppeteer.launch(env.MYBROWSER);
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const browser = await getBrowser(env);
try {
const page = await browser.newPage();
await page.goto("https://example.com");
const screenshot = await page.screenshot();
await browser.disconnect(); // ✅ Keep alive for reuse
return new Response(screenshot, {
headers: { "content-type": "image/png" }
});
} catch (error) {
await browser.close(); // ❌ Close on error
throw error;
}
}
};
关键规则:
- ✅
browser.disconnect()- 保持会话运行,以供复用 - ❌
browser.close()- 仅在发生错误或确实不再需要会话时调用 - ✅ 始终处理连接失败
浏览器上下文(Cookie/缓存隔离)
使用 browser.createBrowserContext() 共享浏览器,同时隔离 Cookie/缓存:
const browser = await puppeteer.launch(env.MYBROWSER);
const context1 = await browser.createBrowserContext(); // User 1
const context2 = await browser.createBrowserContext(); // User 2
const page1 = await context1.newPage();
const page2 = await context2.newPage();
// Separate cookies/cache per context
多标签页模式
❌ 不佳:为 10 个 URL 启动 10 个浏览器(浪费并发资源)
✅ 推荐:1 个浏览器,通过 Promise.all() + browser.newPage() 打开 10 个标签页
const browser = await puppeteer.launch(env.MYBROWSER);
const results = await Promise.all(
urls.map(async (url) => {
const page = await browser.newPage();
await page.goto(url);
const data = await page.evaluate(() => ({ title: document.title }));
await page.close();
return { url, data };
})
);
await browser.close();
常见模式
使用 KV 缓存截图
缓存截图以减少浏览器用量并提升性能:
interface Env {
MYBROWSER: Fetcher;
CACHE: KVNamespace;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { searchParams } = new URL(request.url);
const url = searchParams.get("url");
if (!url) return new Response("Missing ?url parameter", { status: 400 });
const normalizedUrl = new URL(url).toString();
// Check cache first
let screenshot = await env.CACHE.get(normalizedUrl, { type: "arrayBuffer" });
if (!screenshot) {
const browser = await puppeteer.launch(env.MYBROWSER);
const page = await browser.newPage();
await page.goto(normalizedUrl);
screenshot = await page.screenshot();
await browser.close();
// Cache for 24 hours
await env.CACHE.put(normalizedUrl, screenshot, { expirationTtl: 60 * 60 * 24 });
}
return new Response(screenshot, { headers: { "content-type": "image/png" } });
}
};
AI 增强型抓取
将 Browser Rendering 与 Workers AI 结合,以提取结构化数据:
interface Env {
MYBROWSER: Fetcher;
AI: Ai;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { searchParams } = new URL(request.url);
const url = searchParams.get("url");
// Scrape page content
const browser = await puppeteer.launch(env.MYBROWSER);
const page = await browser.newPage();
await page.goto(url!, { waitUntil: "networkidle0" });
const bodyContent = await page.$eval("body", el => el.innerHTML);
await browser.close();
// Extract structured data with AI
const response = await env.AI.run("@cf/meta/llama-3.1-8b-instruct", {
messages: [{
role: "user",
content: `Extract product info as JSON from this HTML. Include: name, price, description.\n\nHTML:\n${bodyContent.slice(0, 4000)}`
}]
});
return Response.json({ url, product: JSON.parse(response.response) });
}
};
其他常见模式:生成 PDF(page.pdf())、抓取结构化数据(page.evaluate())、表单自动化(page.type() + page.click())。请参阅附带的 templates/ 目录。
定价与限制
计费正式推出:2025 年 8 月 20 日
免费套餐:每天 10 分钟、3 个并发浏览器、每分钟启动 3 次、超时 60 秒 付费套餐:每月包含 10 小时(超出后每小时 $0.09)、30 个并发浏览器(超出后每个浏览器 $2.00)、每分钟启动 30 次、超时 60 秒至 10 分钟
并发数计算:按每日峰值用量的月平均值计算(例如,平均 35 个浏览器 =(35 - 包含的 30 个)× $2.00 = 每月 $10.00)
速率限制:按固定的每秒填充速率执行(不支持突发请求)。每分钟 30 个请求 = 每 2 秒 1 个请求。即使配额尚未用完,也不能一次性发送全部 30 个请求。启动前请检查 puppeteer.limits(env.MYBROWSER):
const limits = await puppeteer.limits(env.MYBROWSER);
if (limits.allowedBrowserAcquisitions === 0) {
const delay = limits.timeUntilNextAllowedBrowserAcquisition || 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
已知问题预防
此技能可预防8 个已记录的问题:
问题 #1:不支持 XPath 选择器
错误:“不支持 XPath 选择器”或选择器失败
来源: https://developers.cloudflare.com/browser-rendering/faq/#why-cant-i-use-an-xpath-selector-when-using-browser-rendering-with-puppeteer
原因: XPath 会给 Workers 带来安全风险
**预防:**使用 CSS 选择器,或使用 page.evaluate() 和 XPathEvaluator
解决方案:
// ❌ Don't use XPath directly (not supported)
// await page.$x('/html/body/div/h1')
// ✅ Use CSS selector
const heading = await page.$("div > h1");
// ✅ Or use XPath in page.evaluate()
const innerHtml = await page.evaluate(() => {
return new XPathEvaluator()
.createExpression("/html/body/div/h1")
.evaluate(document, XPathResult.FIRST_ORDERED_NODE_TYPE)
.singleNodeValue.innerHTML;
});
问题 #2:未传递浏览器绑定(Fetcher 类型混淆)
错误:“无法读取未定义对象的属性(读取‘fetch’)”或“RPC 接收器未实现方法‘launch’”
来源:GitHub 问题 #10772,https://developers.cloudflare.com/browser-rendering/faq/#cannot-read-properties-of-undefined-reading-fetch
**原因:**调用 puppeteer.launch() 时未传入浏览器绑定,或尝试直接调用 env.MYBROWSER.launch()。浏览器绑定是一个 Fetcher(REST API 封装器),而非浏览器实例。
**预防:**始终将 env.MYBROWSER 传递给 puppeteer.launch() 或 chromium.launch() 封装器
解决方案:
// ❌ Missing browser binding
const browser = await puppeteer.launch(); // Error!
// ❌ Wrong - trying to call launch() on Fetcher directly
const browser = await env.MYBROWSER.launch(); // "RPC receiver does not implement the method 'launch'"
// ✅ Pass binding to Puppeteer/Playwright wrapper
const browser = await puppeteer.launch(env.MYBROWSER);
// or for Playwright:
const browser = await chromium.launch(env.MYBROWSER);
TypeScript 类型说明:
interface Env {
MYBROWSER: Fetcher; // It's a Fetcher, not a Browser!
}
问题 #3:浏览器超时(60 秒)
**错误:**浏览器在 60 秒后意外关闭
**来源:**https://developers.cloudflare.com/browser-rendering/platform/limits/#note-on-browser-timeout
**原因:**默认超时为 60 秒无活动
**预防:**使用 keep_alive 选项将超时时间延长至最多 10 分钟
解决方案:
// Extend timeout to 5 minutes for long-running tasks
const browser = await puppeteer.launch(env.MYBROWSER, {
keep_alive: 300000 // 5 minutes = 300,000 ms
});
**注意:**如果在指定时长内没有 devtools 命令,浏览器就会关闭。
问题 #4:达到并发限制
错误:“超出速率限制”或无法启动新浏览器 **来源:**https://developers.cloudflare.com/browser-rendering/platform/limits/、[2025-09-25 更新日志](https://developers.cloudflare.com/browser-rendering/changelog/) **原因:**超出并发浏览器限制(截至 2025 年 9 月,免费套餐为 3 个,付费套餐为 30 个) **预防:**复用会话,使用标签页而非多个浏览器,启动前检查限制,并将请求速率控制在每秒限制内
解决方案:
// 1. Check limits before launching
const limits = await puppeteer.limits(env.MYBROWSER);
if (limits.allowedBrowserAcquisitions === 0) {
return new Response("Concurrency limit reached", { status: 429 });
}
// 2. Reuse sessions
const sessions = await puppeteer.sessions(env.MYBROWSER);
const freeSessions = sessions.filter(s => !s.connectionId);
if (freeSessions.length > 0) {
const browser = await puppeteer.connect(env.MYBROWSER, freeSessions[0].sessionId);
}
// 3. Use tabs instead of multiple browsers
const browser = await puppeteer.launch(env.MYBROWSER);
const page1 = await browser.newPage();
const page2 = await browser.newPage(); // Same browser, different tabs
问题 #5:本地开发请求大小限制
**错误:**在 wrangler dev 中,超过 1MB 的请求会失败
**来源:**https://developers.cloudflare.com/browser-rendering/faq/#does-local-development-support-all-browser-rendering-features
**原因:**本地开发限制
**预防:**本地开发时,在浏览器绑定中使用 remote: true
解决方案:
// wrangler.jsonc for local development
{
"browser": {
"binding": "MYBROWSER",
"remote": true // Use real headless browser during dev
}
}
问题 #6:始终触发机器人防护
**错误:**网站将请求拦截为机器人流量 **来源:**https://developers.cloudflare.com/browser-rendering/faq/#will-browser-rendering-bypass-cloudflares-bot-protection **原因:**Browser Rendering 请求始终会被识别为机器人 **预防:**无法绕过;如果要抓取自己的区域,请创建 WAF 跳过规则(机器人管理需要 Enterprise 套餐)
解决方案:
// ❌ Cannot bypass bot protection
// Requests will always be identified as bots
// ✅ If scraping your own Cloudflare zone (Enterprise plan only):
// 1. Go to Security > WAF > Custom rules
// 2. Create skip rule with custom header:
// Header: X-Custom-Auth
// Value: your-secret-token
// 3. Pass header in your scraping requests
await page.setExtraHTTPHeaders({
'X-Custom-Auth': 'your-secret-token'
});
// Note: Automatic headers are included:
// - cf-biso-request-id
// - cf-biso-devtools
**重要提示:**即使在自有网站上,免费、Pro 和 Business 套餐也无法绕过机器人检测。WAF 允许列表要求使用带有 Bot Management 的 Enterprise 套餐。
问题 #7:page.evaluate() 函数名注入(__name 错误)
错误: ReferenceError: __name is not defined
来源: GitHub 问题 #7107
原因: esbuild 压缩(wrangler 3.80.1+)会在包含嵌套函数声明的箭头函数中注入 __name() 辅助函数调用。这些调用会在浏览器上下文中运行,而该上下文中不存在此辅助函数。
预防方法: 保持 page.evaluate() 函数简洁,避免嵌套函数声明
适用范围: wrangler 3.80.1 - 3.83.0(已在 3.83.0+ 中修复)
解决方案:
// ❌ Avoid nested function declarations
const data = await page.evaluate(async () => {
function toNumber(str: string | undefined): number | undefined {
const num = typeof str === 'string' ? str.replaceAll('.', '').replaceAll(',', '.').match(/[+-]?([0-9]*[.])?[0-9]+/) : false;
if (num) {
return Number(num[0]);
} else {
return undefined;
}
}
return toNumber('123.456');
});
// Error: ReferenceError: __name is not defined
// ✅ Inline the logic without nested functions
const data = await page.evaluate(async () => {
const str = '123.456';
const num = typeof str === 'string' ? str.replaceAll('.', '').replaceAll(',', '.').match(/[+-]?([0-9]*[.])?[0-9]+/) : false;
return num ? Number(num[0]) : undefined;
});
// ✅ Or update to wrangler 3.83.0+
// npm install wrangler@latest
注意: 复杂回调中的 page.waitForSelector() 也会受此影响。已在 wrangler 3.83.0+ 中修复(2024 年 11 月)。
问题 #8:waitForSelector() 超时行为已更改
错误: 依赖无限等待的代码现在会超时
来源: 更新日志 2026-01-07
原因: 以前,当找不到选择器时,waitForSelector() 不会超时(会无限期挂起)。此问题已修复,现在会正确遵循超时值。
预防方法: 始终设置明确的超时时间,并处理超时错误
适用范围: 2026 年 1 月之前编写且依赖无限等待的所有代码
解决方案:
// ❌ Old behavior - would hang forever if selector not found
await page.waitForSelector('#dynamic-element');
// ✅ New behavior - properly times out (set explicit timeout)
try {
await page.waitForSelector('#dynamic-element', { timeout: 5000 });
} catch (error) {
if (error.name === 'TimeoutError') {
console.log('Element not found within 5 seconds');
// Handle missing element gracefully
} else {
throw error;
}
}
// ✅ Use longer timeout for slow-loading elements
await page.waitForSelector('#slow-element', { timeout: 30000 }); // 30 seconds
注意: 这是一项具有破坏性的修复(行为更改)。依赖无限等待的代码现在会超时并抛出错误。务必妥善处理 TimeoutError。
生产环境检查清单
将 Browser Rendering Workers 部署到生产环境之前:
配置
- 已在 wrangler.jsonc 中配置 Browser 绑定
- 已启用 nodejs_compat 标志(Browser Rendering 必需)
- 如果任务耗时超过 60 秒,已设置保活超时时间
- 如有需要,已为本地开发启用远程绑定
错误处理
- 已为速率限制实现重试逻辑
- 已处理 page.goto() 的超时
- 已在 try-finally 代码块中清理浏览器
- 已在启动浏览器前检查并发限制
- 浏览器不可用时可平稳降级
性能
- 已为高流量路由实现会话复用
- 使用多个标签页,而非多个浏览器
- 使用无痕上下文隔离会话
- 使用 KV 缓存重复生成的屏幕截图/PDF
- 批量执行操作,以最大限度提高浏览器利用率
监控
- 记录浏览器会话 ID 以便调试
- 跟踪浏览器运行时长,以估算费用
- 使用 puppeteer.limits() 监控并发用量
- 针对速率限制错误设置告警
- 在 https://dash.cloudflare.com/?to=/:account/workers/browser-rendering 进行仪表板监控
安全
- 验证 URL 输入(防止 SSRF)
- 设置超时限制以防止滥用
- 对公共端点进行速率限制
- 为敏感的抓取端点启用身份验证
- 如果抓取自己的区域,则配置 WAF 规则
测试
- 使用各种页面尺寸测试屏幕截图捕获
- 使用自定义 HTML 测试 PDF 生成
- 使用动态内容(networkidle0)测试抓取
- 测试错误场景(无效 URL、超时)
- 对并发限制进行负载测试
错误处理最佳实践
生产环境模式——使用 try-catch 并妥善清理:
async function withBrowser<T>(env: Env, fn: (browser: Browser) => Promise<T>): Promise<T> {
let browser: Browser | null = null;
try {
// 1. Check limits before launching
const limits = await puppeteer.limits(env.MYBROWSER);
if (limits.allowedBrowserAcquisitions === 0) {
throw new Error("Rate limit reached");
}
// 2. Try session reuse first
const sessions = await puppeteer.sessions(env.MYBROWSER);
const freeSessions = sessions.filter(s => !s.connectionId);
browser = freeSessions.length > 0
? await puppeteer.connect(env.MYBROWSER, freeSessions[0].sessionId)
: await puppeteer.launch(env.MYBROWSER);
// 3. Execute user function
const result = await fn(browser);
// 4. Disconnect (keep alive)
await browser.disconnect();
return result;
} catch (error) {
// 5. Close on error
if (browser) await browser.close();
throw error;
}
}
关键原则:检查限制 → 复用会话 → 执行 → 成功时断开连接,出错时关闭
使用捆绑资源
模板(templates/)
常见模式的即用型代码模板:
basic-screenshot.ts- 最简截图示例screenshot-with-kv-cache.ts- 使用 KV 缓存的截图pdf-generation.ts- 从 HTML 或 URL 生成 PDFweb-scraper-basic.ts- 基本网页抓取模式web-scraper-batch.ts- 批量抓取多个 URLsession-reuse.ts- 通过复用会话提升性能ai-enhanced-scraper.ts- 使用 Workers AI 进行网页抓取playwright-example.ts- Playwright 替代方案示例wrangler-browser-config.jsonc- 浏览器绑定配置
用法:
# Copy template to your project
cp ~/.claude/skills/cloudflare-browser-rendering/templates/basic-screenshot.ts src/index.ts
参考文档(references/)
深入文档:
session-management.md- 完整的会话复用指南pricing-and-limits.md- 详细的定价说明common-errors.md- 所有已知问题及其解决方案puppeteer-vs-playwright.md- 功能对比与迁移指南
加载时机: 实现高级模式或排查特定问题时参考。
依赖项
必需:
@cloudflare/[email protected]- 适用于 Workers 的 Puppeteer[email protected]+- Cloudflare CLI
可选:
@cloudflare/[email protected]- 适用于 Workers 的 Playwright(替代方案)@cloudflare/[email protected]+- TypeScript 类型
相关技能:
cloudflare-worker-base- 使用 Hono 设置 Workercloudflare-kv- 用于截图的 KV 缓存cloudflare-r2- 用于存储生成文件的 R2cloudflare-workers-ai- AI 增强的网页抓取
官方文档
- Browser Rendering 文档:https://developers.cloudflare.com/browser-rendering/
- Puppeteer API:https://pptr.dev/api/
- Playwright API:https://playwright.dev/docs/api/class-playwright
- Cloudflare Puppeteer 分支:https://github.com/cloudflare/puppeteer
- Cloudflare Playwright 分支:https://github.com/cloudflare/playwright
- 定价:https://developers.cloudflare.com/browser-rendering/platform/pricing/
- 限制:https://developers.cloudflare.com/browser-rendering/platform/limits/
软件包版本(已于 2026-01-21 验证)
{
"dependencies": {
"@cloudflare/puppeteer": "^1.0.4"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20251014.0",
"wrangler": "^4.59.3"
}
}
替代方案(Playwright):
{
"dependencies": {
"@cloudflare/playwright": "^1.1.0"
}
}
注意: Playwright v1.1.0 支持 Playwright v1.57(2026 年 1 月)。Wrangler 3.83.0+ 修复了 page.evaluate() 的 __name 注入错误。
故障排除
问题:"Cannot read properties of undefined (reading 'fetch')"
解决方案: 将浏览器绑定传递给 puppeteer.launch():
const browser = await puppeteer.launch(env.MYBROWSER); // Not just puppeteer.launch()
问题:XPath 选择器不起作用
解决方案: 使用 CSS 选择器,或通过 XPathEvaluator 配合 page.evaluate() 使用 XPath(参见 Issue #1)
问题:浏览器在 60 秒后关闭
解决方案: 使用 keep_alive 延长超时时间:
const browser = await puppeteer.launch(env.MYBROWSER, { keep_alive: 300000 });
问题:达到速率限制
解决方案: 复用会话、使用标签页,并在启动前检查限制(参见 Issue #4)
问题:本地开发请求超过 1 MB 时失败
解决方案: 在 wrangler.jsonc 中启用远程绑定:
{ "browser": { "binding": "MYBROWSER", "remote": true } }
问题:网站将请求拦截为机器人流量
解决方案: 无法绕过。如果是你自己的区域,请创建 WAF 跳过规则(参见 Issue #6)
有疑问?遇到问题?
- 查看
references/common-errors.md获取详细解决方案 - 查看
references/session-management.md了解性能优化 - 确认已在 wrangler.jsonc 中配置浏览器绑定
- 查看官方文档:https://developers.cloudflare.com/browser-rendering/
- 确保已启用
nodejs_compat兼容性标志