使用 Browser Run 在选定请求之后捕获屏幕截图。将图像保存到 R2,同时向用户返回原始响应。
浏览器会对固定的公开 URL 进行独立访问。它不会继承用户的 Cookie、授权信息、Gateway 会话或出站(egress)配置。结果是公开页面的屏幕截图,而不是用户所见内容的精确捕获。请将此模板用于您控制的公开页面。
在 Worker 项目中,将 @cloudflare/zt-types ↗ 2026.10.1 或更高版本安装为开发依赖项:
npm i -D @cloudflare/zt-typesyarn add -D @cloudflare/zt-typespnpm add -D @cloudflare/zt-typesbun add -d @cloudflare/zt-types保留 src/index.ts 中 GatewayMiddlewareContext 和 GatewayMiddlewareNext 的 import type 声明。它们描述 Gateway 上下文和延续函数,并会在 TypeScript 编译时被移除。从 cloudflare:workers 导入运行时 WorkerEntrypoint 类。
创建一个名为 gateway-screenshots 的私有 R2 存储桶,然后将浏览器和 R2 绑定添加到 Worker 配置:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"browser": {
"binding": "BROWSER"
},
"r2_buckets": [
{
"binding": "CAPTURES",
"bucket_name": "gateway-screenshots"
}
]
}[browser]
binding = "BROWSER"
[[r2_buckets]]
binding = "CAPTURES"
bucket_name = "gateway-screenshots"浏览器绑定的 quickAction() 方法要求兼容日期为 2026-03-24 或更晚。请参阅 Browser Run 配置。
将 https://example.com/ 替换为您控制的公开测试页面。本地浏览器接口仅包含此处使用的 Quick Action。
import { WorkerEntrypoint } from "cloudflare:workers";
const PAGE = "https://example.com/";
export class GatewayMiddleware extends WorkerEntrypoint {
async handle(request, context, next) {
const response = await next(request);
const url = new URL(request.url);
if (
request.method === "GET" &&
url.origin + url.pathname === PAGE &&
response.ok
) {
this.ctx.waitUntil(
this.capture().catch(() => console.error("Screenshot capture failed")),
);
}
return response;
}
async capture() {
const image = await this.env.BROWSER.quickAction("screenshot", {
url: PAGE,
viewport: { width: 1280, height: 720 },
gotoOptions: { timeout: 10_000 },
});
if (!image.ok) {
await image.body?.cancel();
throw new Error("Screenshot request failed");
}
await this.env.CAPTURES.put(
`${crypto.randomUUID()}.png`,
await image.arrayBuffer(),
{
httpMetadata: { contentType: "image/png" },
},
);
}
}import { WorkerEntrypoint } from "cloudflare:workers";
import type {
GatewayMiddlewareContext,
GatewayMiddlewareNext,
} from "@cloudflare/zt-types";
const PAGE = "https://example.com/";
interface Env {
CAPTURES: R2Bucket;
BROWSER: {
quickAction(
action: "screenshot",
options: {
url: string;
viewport: { width: number; height: number };
gotoOptions: { timeout: number };
},
): Promise<Response>;
};
}
export class GatewayMiddleware extends WorkerEntrypoint<Env> {
async handle(
request: Request,
context: GatewayMiddlewareContext,
next: GatewayMiddlewareNext,
): Promise<Response> {
const response = await next(request);
const url = new URL(request.url);
if (
request.method === "GET" &&
url.origin + url.pathname === PAGE &&
response.ok
) {
this.ctx.waitUntil(
this.capture().catch(() => console.error("Screenshot capture failed")),
);
}
return response;
}
async capture(): Promise<void> {
const image = await this.env.BROWSER.quickAction("screenshot", {
url: PAGE,
viewport: { width: 1280, height: 720 },
gotoOptions: { timeout: 10_000 },
});
if (!image.ok) {
await image.body?.cancel();
throw new Error("Screenshot request failed");
}
await this.env.CAPTURES.put(
`${crypto.randomUUID()}.png`,
await image.arrayBuffer(),
{
httpMetadata: { contentType: "image/png" },
},
);
}
}该脚本使用固定的浏览器目标,不会从用户请求复制查询参数或会话凭据。视口会将图像限制为常规视口屏幕截图。
部署 Worker,并为测试页面的 Host(主机)、URL Path(URL 路径) 以及 HTTP Method(HTTP 方法) GET 创建 Forward 策略,作用范围限定为您的测试用户组。
通过 Gateway 访问该页面。确认页面正常加载,并且 R2 中出现 PNG 对象。打开该对象以检查屏幕截图。Browser Run Quick Action 需要远程浏览器绑定,无法完全通过本地模拟进行验证。
屏幕截图会消耗 Browser Run 用量。请限定范围或对捕获进行采样以控制用量。浏览器排队、导航和 R2 写入必须在后台执行时限内完成。对于加载较慢的页面,请使用 Queues 或 Workflows 以可靠地完成捕获。