我们该自己造浏览器吗?多年来,这个问题每隔几个月就会在 Cloudflare 内部被重新提起。不出所料,它总会引发很长的讨论串:大家列出许多理由,并拿出颇有说服力的论证,说明我们为什么该做这件事。浏览器显然是我们每天在电脑上使用的最重要的软件;甚至可以说,它就是互联网的操作系统。我们的使命是帮助建设更好的互联网——又有谁会不想挑战亲手打造一款新浏览器?
但我们始终没能找到平衡点:一边是这项事业的技术难度,另一边是我们能借此解决的独特问题。于是,这个想法一次又一次被搁置。直到现在。
一件很神奇的事发生了:我们的开发者平台一系列强大的技术进展终于成为现实;与此同时,AI 智能体的出现,以及对一种新型浏览器的需求,也都到了关键拐点。
在 Workers 中运行 WebAssembly(Wasm)如今已经非常成熟。诸如动态 Worker、基于 SQLite 的 Durable Objects、Worker 间 RPC、服务绑定、更高的 NodeJS 兼容性和更高的资源限制等原语,打开了通往更具野心、更复杂应用的大门;这些应用在过去根本无从实现。
Browser Run——我们的无头浏览器自动化 API 产品——随着 AI 的兴起实现了惊人的增长。智能体需要浏览器来完成许多任务,而且在很多情况下,没有浏览器就根本无法成功。
但问题在于:Chromium 之类的浏览器引擎是为人类而造,不是为智能体而造;它们携带着 AI 模型根本不需要的开销。它们消耗了如此多的内存和算力,以至于为每个智能体配备独立实例的成本高得难以承受。这使得网络的大部分内容只对那些参数化知识更多、成本更高的 AI 模型开放,同时把许多其他智能体应用拒之门外。
我们应该为所有智能体提供一款在 AI 模型真正关心的事情上足够出色的浏览器,哪怕这意味着弱化那些只对人类有用的能力。例如:
- AI 不关心标签页、主题、浏览器扩展,或跨设备同步。它关心 token 数、上下文窗口、可扩展性、性能和成本。
- 结构化、机器可读的内容很重要;视觉上的完美,以及平滑的 60 fps 滚动则不重要。即使 CSS 解析略有偏差,或渲染并非像素级准确,智能体也能很好地工作。
- AI 使用浏览器时的威胁模型不同。提示词注入、工具安全等新问题是最高优先级。
意识到这些之后,12 周前我们再次提出了那个问题:我们该自己造浏览器吗?这一次,答案一致是:该!
今天,我们宣布推出 Kitesurf:一款专为智能体打造、完全运行在 Workers 之上的新浏览器。在测试阶段,它可通过 Browser Run免费使用。
对于截图、HTML 提取等常见的智能体任务,Kitesurf 的 CPU 和内存效率显著优于 Chromium。接下来我们会讲讲它是如何构建出来的。系好安全带:技术细节不少,但我们保证不会无聊。
从何而起
和 Cloudflare 的许多好点子一样,Kitesurf 的起点也很典型:有人发现了一件有趣的东西,紧接着,一个看似不可能、却极具吸引力的想法就把团队其他人都“技术钓”了进来。
最初的灵感来自 obscura:一个用 Rust 编写、面向 AI 自动化的无头引擎,主打“没有 Chrome、没有 Node.js、没有依赖”。

随后,在 AI 智能体的帮助下,我们尝试把它移植到 Workers。起初效果并不好;但当我们为 AI 提供了扎实的计划和清晰的成功定义——细致到足以让智能体持续循环,并在需要时主动提问——它就成功了。
这个勉强能跑的概念验证让我们大为震撼,于是决定让团队放开手做。
设计决策
下面是我们在动工前做出的一些设计决策。
测试、测试、还是测试
我们知道,把一个原型发展成能在生产环境中大规模执行真实任务的完整浏览器,需要大量工作和反复迭代。我们不避讳:用 AI 加速这一过程至关重要。但在如此复杂的项目里,如何使用 AI,既不牺牲速度,又能控制代码与结果的质量?答案是:尽可能提供更多测试。
Web Platform Tests(WPT)正好满足这一点:这套广泛的成功标准为 AI 智能体提供了明确的目标线,用于评估功能是否符合规范。我们精心挑选并排序要分配给智能体的功能,让人类能够专注于架构工作,以及审查智能体的实现路径。
但 WPT 的覆盖毕竟有限:它衡量的是对 W3C标准的符合程度,而不是浏览器渲染真实网站、并与之交互的能力。为了弥合这个缺口,我们组合实施了集成测试和视觉回归测试:它在真实网站上对 Chromium 和 Kitesurf 运行多步骤 Puppeteer测试;不仅对比断言结果,还会在每一步渲染输出,以凸显任何不应出现的差异。
尽可能使用 Rust
一段时间以来,Cloudflare 一直在为 Workers 提供出色的 WebAssembly(Wasm)支持。这很关键,因为我们可以使用高性能的 C、C++ 和 Rust 软件包,并将它们编译为 Wasm。若使用 Emscripten(举例而言)及其多层模拟依赖,编译出的二进制文件就可能臃肿而缓慢。
因此,我们尽可能选用原生 Rust,并用 wasm-bindgen直接编译为 WebAssembly。这样既避开了不必要的模拟层,也能尽可能贴近底层、可靠地运行。
异常处理
浏览器必须渲染整个不可靠、甚至有时带有恶意的网络,同时绝不能丢掉正在承载的页面。因此,异常处理不只是代码卫生问题——它决定了应用面对坏输入时,能否存活而不是直接崩溃。
所以我们一开始就立下一条规则:任何失败都应退化为空白帧或缺失元素,绝不能变成失效会话。要在每一个边界捕获故障,默认回退到安全、空白的状态,并记录足够的信息以供诊断。
隔离
与在笔记本电脑上运行浏览器不同:你通常访问的是自己信任的网站,而在网站之间共享部分资源也可以接受。智能体则会根据任务需求,被指向来自任意源的任意代码。
所以,我们假定每次页面加载都是不受信任的输入,并且每个会话都从全新状态开始。每个组件彼此隔离,只能访问完成功能所严格必需的资源。

这与 Cloudflare Workers 是天作之合,因为它的安全模型从设计上就以隔离为中心。但平台只为我们提供隔离体之间的边界;我们仍需在应用层贯彻同一原则,决定每个组件能够触及什么,并确保资源不会越过不应跨越的页面边界而泄漏。
能无状态就无状态
状态会让失败变得昂贵:如果没有东西需要重建,崩溃后的恢复就只是启动一个新实例并重放请求。无状态组件天生可丢弃、可并行:一旦卡住就杀掉它;同时运行上千个;按需伸缩,而不是为了保温而让它们常驻。这与自动化完美契合:负载会以突发方式到来,而最便宜的工作就是只消耗实际用量、完成后立刻消失的工作。简言之,只要一个组件可以无状态,它就应该无状态。
我们如何构建它
有了完善的计划、广泛的测试,以及趁手的工具环境,我们准备好从最初的概念验证继续向前。下面是 Kitesurf 至今仍适用的一次请求的高层生命周期:

让我们深入 Kitesurf 的三个核心组件:Engine、PageScript 和 PageRenderer。
从源站抓取
要渲染一个不受信任的网页,浏览器必须从互联网抓取任意资源——图片、字体、CSS、JavaScript 和 Wasm 文件。这是浏览器能做的最危险操作之一。
Kitesurf 只通过一个组件来做这件事:SandboxOutbound Worker;在动态 Worker 的约束下,其他组件都不能直接访问网络。Engine 用它来引导页面,获取主文档和脚本;PageScript 则用它来获取其余内容:样式表、图片、字体,以及页面自身发出的 fetch() 调用。
我们通过 SandboxOutbound 强制执行 CORS、注入浏览器风格的请求头、过滤响应,并为每个页面维护独立的 cookie 罐。任何不符合策略的请求都会收到 403:每个组件都只得到它所需的网络能力,绝不会更多。

Engine
Engine 是 Kitesurf 唯一面向公共网络的组件。它处理 Chrome DevTools Protocol(CDP)的 WebSocket 和 HTTP REST API,提供一个可供内部测试使用的落地页;最重要的是,它保存每个会话的状态。其他组件全部无状态。

采用 CDP 的优势是客户端兼容性:Puppeteer、Playwright、chrome-remote-interface,以及真正的 Chrome DevTools 前端都能直接使用。只要把它们指向 Kitesurf,一切就能工作。这也是 Browser Run 运行的方式(稍后会解释为什么这很重要)。
与名字给人的印象相反,Engine 其实是 Kitesurf 最简单的组件。真正有意思的部分还在后面。
PageScript
PageScript 是我们新 Workers 功能威力的一个好例子:这里指的是动态 Worker。没有它,Kitesurf 根本不可能实现。
下面是一张简化图,展示 PageScript 的内部工作方式。

每个后续页面或进程外 iframe(OOPIF)都会借助动态 Worker 启动一个长生命周期的 PageScript 隔离体,负责页面会话。这个会话由干净的 globalThis 和 DOM document 对象组成。
随后,DOM 对象会被解析 HTML 文档、执行全部 JavaScript 脚本的结果所填充。HTML 和 CSS 的解析使用了 Blitz(模块化渲染引擎)和 Stylo(Firefox 的高性能 CSS 解析器)的部分能力;两者都由 Rust 编写。
对于找到的每个 script 标签或 .wasm 文件,我们都会在同一个隔离体中执行其中的 JavaScript 和 WebAssembly 代码。
那 eval 呢?
你可能会问:eval 怎么办?由于安全原因,Workers 目前仍不原生支持 eval,因此处理起来更棘手。我们也不能另起一个隔离体来处理,因为它无法访问 globalThis。
我们的解法是使用 Boa JS:这是一个用 Rust 编写的 ECMAScript 引擎,可被编译并运行在 Workers 中。我们本质上是在一个运行时之上再执行另一个运行时;这看起来并不理想,事实也确实如此,但它足以处理代码里偶尔遇到的 eval。未来当 Workers 提供原生 eval 支持时,我们会迁离 Boa。
PageRenderer
这个组件本质上负责从计算得到的页面对象生成实际像素。它的工作方式如下:

PageRenderer 与 Engine Worker 循环协作。每当 Engine 需要一帧,PageRenderer 就会从 PageScript 获取页面对象(也称 scene),从 Static Assets获取内部字体和图片,将所有内容栅格化为图像缓冲区,再以客户端可显示的 JPEG/PNG 或 PDF 格式把缓冲区返还给 Engine。
其中很大一部分魔法由另一个 Blitz 模块 blitz-paint完成;它又使用 Parley 对字符进行整形为字形、选择字体并对文本进行换行。
Workers 内建 RPC 系统:同一个应用,多个隔离体
Cloudflare Workers 有一套内建远程过程调用(RPC)系统,可让你调用其他 Worker 上的方法、在它们之间传递对象,并调用这些对象的方法。你无需操心 API schema、类型或认证;只要调用 remoteFunction(...params),它就能工作。你既能获得远程 Worker 的隔离与资源,又不失在 JavaScript 中像本地函数一样访问其全部能力的便利。
Kitesurf 使用了这套 RPC 系统:Engine Worker 用一次 RPC 调用 PageRenderer Worker 的 renderFrame(),并取得 PNG 结果。渲染器不保存页面状态(只有可丢弃的缓存),因此 Engine 可以在任意失败或卡住的 RPC 调用后安全地终止并重新启动它——从而让每次渲染请求都自包含、可重试,并使其隔离体廉价且可随时丢弃。
Kitesurf 已通过 215,000 多项 WPT 测试,而且还在增长
Kitesurf 能跑起来。它已经通过约 215,000 多项 WPT 测试,而且我们每周都会新增数百项通过的测试。下面可以看到从项目启动到当前最新版本的演进情况:

值得一提的是,对智能体重要的浏览器部分(例如 CSS、DOM、HTML、选择、SVG 和 XHR)已经有良好覆盖。即使是对智能体场景未必特别重要的能力,例如流,如今也有不错支持。

从性能来看,Kitesurf 表现相当不错。下表是在一个包含 14 个 URL 的语料集上,对 Chromium 和 Kitesurf 各运行五次 Browser Run 快速操作后得到的中位数:
| 指标 | Kitesurf | Chromium(预热池) | Kitesurf 相对表现 |
|---|---|---|---|
| CPU:截图 | 380 ms | 1,173 ms | CPU 用量为 Chromium 的 1/3.1 |
| CPU:HTML 提取 | 229 ms | 877 ms | CPU 用量为 Chromium 的 1/3.8 |
| 内存:截图 | 57.8 MiB | 271.0 MiB | 内存用量为 Chromium 的 1/4.7 |
| 内存:HTML 提取 | 39.4 MiB | 273.7 MiB | 内存用量为 Chromium 的 1/7.0 |
| 实际耗时:截图 | 1,148 ms | 637 ms | 比 Chromium 慢 1.8 倍 |
| 实际耗时:HTML 提取 | 820 ms | 472 ms | 比 Chromium 慢 1.7 倍 |
Chromium 在计时器上获胜,因为已经见过这个页面的 JIT总能击败冷启动的软件渲染器——目前大约快 1.7 倍。大部分差距来自栅格化以及 JPEG/PNG 编码,我们会继续优化。
但在真正驱动账单的内存和 CPU 维度上,Kitesurf 比 Chromium 少用 3 至 7 倍。更少的内存意味着我们可以运行更多会话、更好地扩展,并从根本上降低我们的成本和你的成本。
最重要的测试:Kitesurf 能运行 Doom
我们在设计决策中强调了测试的重要性;但大家都知道,无论有多少测试,一个项目只有在 Doom 能跑起来之后才算真正完成。下面是 Kitesurf 运行 https://silentspacemarine.com/的画面;这个 Doom 实验来自我们几年前的一个小项目。
立即在 Browser Run 中试用
现在即可通过 Browser Run 试用 Kitesurf。它目前仍处于测试阶段,可免费使用,但受每账户限制约束。
Browser Run CDP endpoint现在已经支持将 Kitesurf 作为选项,因此你现有的 Puppeteer、Playwright、chrome-remote-interface 客户端,或任何会说 MCP 和 CDP 的 AI 智能体,都能直接工作。只需在 endpoint 中加入 browser=kitesurf 参数。
例如,要让 Kitesurf 配合 Opencode 使用,请查阅开发者文档中的通过 MCP 客户端使用(CDP),并采用以下配置:
{
"mcp": {
"kitesurf": {
"type": "local",
"command": [
"npx",
"-y",
"chrome-devtools-mcp@latest",
"--wsEndpoint=wss://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/browser-run/devtools/browser?browser=kitesurf",
"--wsHeaders={\"Authorization\":\"Bearer <API_TOKEN>\"}"
],
"enabled": true
}
}
}
使用 Kitesurf 的另一种方式是 Browser Run 的快速操作。同样,只要在快速操作 endpoint 中加入 browser=kitesurf,它就能工作。例如,若你需要快速截取 Wikipedia 的截图,下面的命令即可:
curl -X POST 'https://api.cloudflare.com/client/v4/accounts/<accountId>/browser-run/screenshot?browser=kitesurf' \
-H 'Authorization: Bearer <apiToken>' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com"
}' \
--output "screenshot.png"
用 Chrome DevTools 探索 Kitesurf Playground
另一种开始探索 Kitesurf 的方式,是使用我们的公共 Playground。你可以输入任何 URL,查看 Kitesurf 如何渲染该页面,并与之交互。
Playground 有一个很有意思的特性:我们在 UI 中嵌入了 Chrome DevTools。因此,在 Kitesurf 渲染页面时,你可以检查展开后的 DOM 元素、读取控制台消息并观察网络活动。更有意思的是,我们实现了 Memory 面板所需的 CDP 指令,用来报告每个隔离体(包括 frame)的 WebAssembly 占用,从而清楚了解每个页面消耗的资源。

有关如何将 Kitesurf 与 Browser Run 搭配使用的所有细节,请参阅我们的开发者文档。
Kitesurf 何时更合适?
截至今天,Kitesurf 已能正确渲染 TodoMVC(vanilla、React、Vue、Angular、Preact)、Wikipedia、Hacker News、Cloudflare Blog,以及 Cloudflare 控制台的大部分页面。我们会持续改进 Kitesurf,并提高通过 WPT 测试的比例,从而为更复杂的网页改善兼容性。
对于需要渲染页面、但能够接受不使用功能完整且像素级准确 Chromium 浏览器这一取舍的 AI 智能体,Kitesurf 很合适。它也特别适合依赖一次性快速操作的自动化和应用,例如在兼容站点上提取页面内容,或生成 PDF、截图。
可以把 Kitesurf 看作一个短暂存在、完全隔离、无状态的引擎:它只在任务持续期间存在,并能很好地适应突发的 AI 驱动负载。
Kitesurf 目前还做不了什么
如果你需要播放视频、渲染 WebGL、用真实 TLS 指纹协商机器人挑战握手,或启动一个需要持久状态、长达十分钟的已认证会话,Kitesurf 目前并不适合。请使用 Browser Run 由 Chromium 驱动的默认选项。
要知道某个具体网站是否兼容 Kitesurf,最好的方法就是试试。你可以通过 API,或更快捷地在公共 Playground中尝试。
探索 DevTools 面板,观察幕后正在发生什么,尤其留意控制台与内存指标。
接下来的方向
Kitesurf 只有 12 周大,第一笔提交发生在五月。以下是我们正在积极推进的一些事项:
- 更好的 CDP 覆盖。 Kitesurf 实现了 CDP 协议的一个子集——足以满足大多数智能体和自动化工具的要求,包括强健的 DOM 与网络检查;我们会持续扩展它的能力,使其尽可能完整。
- 渲染保真度。 我们会改善截图和 PDF 的效果,因为我们知道 LLM 往往能从图像中比从底层文本中更好地完成工作。
- WPT 覆盖。 我们正在快速迭代,增加更多 Web API,并通过更多 WPT 测试,向让 Kitesurf 达到生产就绪不断迈进。
- 效率。 我们持续运行 CPU、内存和实际耗时的基准测试,并与其他开发者平台团队紧密合作,让 Kitesurf 尽可能具备成本效益和高效率。
最后的话
感谢你读到这里——我们知道这是篇很长、很技术化的博客文章,但希望它也足够有趣。我们讲得很细,是因为我们绝不轻视打造一款新浏览器的重要性,以及其中的复杂性;即便它是一款高度专门化的浏览器也是如此。
Kitesurf 仍处于早期阶段,但我们希望尽快向你开放,并从你的反馈中学习。团队会积极改进它,频繁发布更新,重点关注性能、效率与兼容性。
最后一件事:等准备就绪后,我们会将 Kitesurf 开源——希望很快就能实现。我们的目标是让任何客户在愿意时,都可以在自己的账户中部署一份自己的 Kitesurf。
所以,请在 Playground中试用它,关注我们的变更日志,并到 Discord与团队交流。分享你的使用体验,告诉我们你的反馈;我们会认真倾听。