隆重推出 Kitesurf:一款基于 agent 优先的浏览器,可在 Cloudflare Workers 上的 V8 隔离环境中运行

来源 cloudflare blog: Introducing Kitesurf: The agent-first browser that runs in V8 isolates on Cloudflare Workers | Cloudflare Blog

我们应该开发自己的浏览器吗?

多年来,Cloudflare 内部每隔几个月就会出现一次这样的问题。不出所料,这类问题总是会引发长篇讨论,各种理由和令人信服的论据都会涌现,阐述我们为什么应该开发新浏览器。浏览器显然是我们每天在电脑上使用的最重要的软件;它甚至可以说就是互联网的操作系统。我们是一家致力于构建更美好互联网的公司——谁不想接受开发新浏览器的挑战呢?

但我们始终未能找到这项工程的技术难度与我们通过它所能解决的独特问题之间的平衡点。因此,这个想法一再被搁置。直到现在。

神奇的事情发生了:我们达到了一个转折点,我们的开发者平台的一系列强大的技术进步成为了现实,与此同时,人工智能代理的出现和对新型浏览器的需求也变得至关重要。

在 Workers 中运行WebAssembly (Wasm)已经非常成熟。动态 Worker基于 SQLite 的持久对象Worker 间 RPC服务绑定、更高的NodeJS 兼容性和更高的限制等基本功能,为以前根本无法实现的更宏大、更复杂的应用程序打开了大门。

随着人工智能的兴起,我们的无头浏览器自动化API产品Browser Run取得了巨大的增长。智能体需要浏览器才能执行许多任务,在很多情况下,没有浏览器它们根本无法完成任务。

但问题在于——像 Chromium 这样的浏览器引擎是为人类而非智能体设计的,它们会带来人工智能模型根本不需要的额外开销。它们消耗大量的内存和计算资源,为每个智能体提供独立的实例成本高昂,这使得网络的大部分内容只能由参数知识更丰富、成本更高的复杂人工智能模型访问,同时也把许多其他智能体应用拒之门外。

我们应该为所有 智能体配备一个浏览器,该浏览器在人工智能模型所需的重要功能方面表现出色,即使这意味着在仅对人类有用的功能方面有所妥协。例如:

  • 人工智能不关心标签页、主题、浏览器扩展程序或跨设备同步。它关心的是令牌数量、上下文窗口、可扩展性、性能和成本。
  • 结构化、机器可读的内容固然重要,但视觉上的完美无瑕、流畅的 60fps 滚动并非必要。即使 CSS 解析略有偏差或渲染并非像素级完美,代理也能正常工作。
  • 在浏览器环境下的人工智能威胁模型有所不同。诸如提示注入和工具安全等新问题是重中之重。

面对这些现实,12 周前我们再次提出了这个问题:我们应该开发自己的浏览器吗?这一次,答案是一致的:是的!

今天,我们宣布推出Kitesurf ,这是一款 完全基于我们专门为代理构建的 Workers 运行的新浏览器,目前在Browser Run中处于测试阶段,可免费使用。

对于截图和提取 HTML 等常见代理任务,Kitesurf 在 CPU 和内存消耗方面都比 Chromium 效率高得多。接下来,我们将讲述它的开发历程。准备好了吗?内容会比较技术性——但我们保证会很有趣。

复制链接它的起源

它的起源

Kitesurf 的诞生和 Cloudflare 的许多其他伟大创意一样。有人发现了一些有趣的东西,然后他们就用一个看似不可能但却极具吸引力的想法“抢占”了团队的其他成员的风头。

我们最初的灵感来自obscura,这是一个用 Rust 编写的用于 AI 自动化的无头引擎,它“没有 Chrome,没有 Node.js,没有依赖项”。


然后,我们借助人工智能代理尝试将其移植到 Workers 上。起初效果并不理想。但当我们为人工智能制定了完善的计划和清晰的成功定义——足够详细,能够让代理无限循环并在需要时提出问题——之后,它就成功了。
这个(勉强)可行的概念验证让我们大吃一惊,于是我们决定放手让团队继续探索。

复制链接设计决策

以下是我们开工前做出的一些设计决定。

测试,测试,测试

我们知道,从原型到能够大规模应用于生产环境的完整浏览器,需要大量的工作和迭代。我们毫不讳言,利用人工智能加速这一过程至关重要。但是,如何在如此复杂的项目中运用人工智能,既保证代码和结果的质量,又不影响开发速度呢?答案是:尽可能多地进行测试。

Web平台测试(WPT)应运而生,它提供了一套理想的方案:一套全面的成功标准,为AI代理评估功能一致性设定了明确的目标。我们精心挑选并安排了分配给代理的功能及其顺序,使人类能够专注于架构设计以及审查代理的实现方式。

然而,WPT 测试的局限性在于:它们只能衡量浏览器是否符合W3C标准,而无法评估浏览器渲染和与真实网站交互的能力。为了弥补这一不足,我们结合了 集成测试和视觉回归测试——它使用Puppeteer对真实网站进行多步骤测试,分别针对 Chromium 和 Kitesurf 进行测试。测试不仅比较测试结果,还会渲染每一步的输出,以突出显示任何异常差异。

尽可能使用 Rust

Cloudflare长期以来一直致力于在 Workers 中提供对WebAssembly (Wasm)的强大支持。这非常棒,因为我们可以使用高性能的 C、C++ 和 Rust 包,并将它们编译成 Wasm。如果我们使用 Emscripten(例如)及其多层模拟依赖项,编译后的二进制文件可能会变得臃肿且运行缓慢。

相反,我们尽可能选择原生 Rust,并使用wasm-bindgen直接编译为 WebAssembly,从而避免不必要的模拟层,并尽可能可靠地在底层运行。

异常处理

浏览器必须渲染整个不可靠且有时充满敌意的网络,同时不能丢弃它正在保存的页面,因此异常处理不仅仅是卫生问题——它是应用程序如何在遇到错误输入时存活下来而不直接崩溃的方式。

因此,我们一开始就定下了一条规则:任何故障都降级为空白帧或缺失元素,绝不会导致会话终止。在每个边界处捕获故障,默认值为安全且为空的内容,并记录足够的日志以便诊断。

隔离

与在笔记本电脑上运行浏览器(访问你信任的网站,并且可以在它们之间共享一些资源)不同,代理程序会指向任务所需的任何内容:来自任意来源的任意代码。

因此,我们在构建这款浏览器时,假设每次页面加载都是不可信的输入,并且每个会话都是全新开始的。每个组件都是隔离的,并且只能访问其功能绝对必要的资源。


这似乎与 Cloudflare Workers 非常契合,其安全模型正是基于隔离设计而构建的。但该平台仅能提供隔离层之间的边界。我们仍然需要在应用层强制执行同样的原则,决定每个组件可以访问哪些内容,并确保任何数据都不会泄露到不应该泄露的页面。

尽可能保持无国籍状态

状态是导致故障成本高昂的根本原因——如果没有可重建的内容,从崩溃中恢复就只是启动一个新的组件并重放请求。无状态组件本质上是可抛弃的,并且可以并行运行:一旦停止运行就立即终止,可以同时运行上千个组件,并根据需求调整其大小,而不是让组件保持“热机”状态。这完美契合自动化场景,因为自动化负载往往是突发性的,而最经济的做法就是启动只消耗实际使用资源的工作,并在完成后立即销毁。简而言之,只要组件可以做到无状态,就应该这样做

复制链接我们是如何建造它的

有了完善的计划、广泛的测试和良好的工具环境,我们就可以超越最初的概念验证阶段,着手开展后续工作了。以下是风筝冲浪项目至今仍适用的总体需求概述:

让我们深入了解构成 Kitesurf 的三个主要组件:引擎、页​​面脚本和页面渲染器。

复制链接从源头获取

为了渲染不受信任的网页,浏览器必须从互联网上获取任意资源——图像、字体、CSS、JavaScript 和 Wasm 文件。这是浏览器可以执行的最危险的操作之一。

Kitesurf 通过一个名为 SandboxOutbound 的工作线程来实现这一切,其他任何组件都不能直接访问网络——这是由动态工作线程强制执行的。引擎使用它来引导页面,获取主文档及其脚本,而 PageScript 则获取其他所有内容:样式表、图像、字体以及页面自身的 fetch() 调用。

我们使用 SandboxOutbound 来强制执行CORS 策略、注入浏览器格式的响应头、过滤响应,并将每个页面的 cookie 保存在各自独立的容器中。任何违反我们策略的操作都会返回 403 错误——每个组件都只获得其所需的网络资源,不多不少。

引擎

引擎是 Kitesurf 唯一面向公众的组件。它处理 Chrome DevTools 协议 (CDP) WebSocket 和 HTTP REST API,提供一个用于内部测试的登录页面,最重要的是,它存储每个会话的状态。所有其他组件都是无状态的。


使用 CDP 的优势在于其客户端兼容性:Puppeteer、Playwright、chrome-remote-interface 以及 Chrome DevTools 前端。只需将它们指向 Kitesurf,它们就能正常工作。Browser Run 的工作原理也是如此(稍后会详细解释其重要性)。

与名称相反,引擎实际上是风筝冲浪组件中最简单的部分。接下来才是真正有趣的部分。

复制链接PageScript

PageScript 很好地展现了我们全新 Workers 功能(在本例中为动态 Workers)的强大之处。在此之前,Kitesurf 根本无法实现。

以下是 PageScript 内部工作原理的简化示意图


每个下一页或进程外 iframe ( OOPIF ) 都使用动态工作线程来启动一个长期存在的 PageScript 隔离区,该隔离区处理页面会话,由一个干净的globalThisDOM文档对象组成。

然后,DOM 对象会填充解析 HTML 文档和运行所有 JavaScript 脚本的结果。解析 HTML 和 CSS 时,我们使用了Blitz(一个模块化渲染引擎)和Stylo( Firefox 的高性能 CSS 解析器)的部分代码,它们都是用 Rust 编写的。

对于找到的每个 标签或 .wasm 文件,我们都在同一个隔离区内运行 JavaScript 和 WebAssembly 代码。

是的,但是评价

你可能会问,那 eval呢?处理 eval 比较棘手,因为出于安全考虑,我们目前在 Workers 中仍然不支持原生 eval。我们也不能为了处理 eval 而创建一个新的隔离区,因为那样它就无法访问 globalThis 了。

我们的解决方案是使用Boa JS(一个用 Rust 编写的 ECMAScript 引擎)在 Workers 上编译和运行。我们实际上是在一个运行时之上执行另一个运行时,这看起来并非最优,也确实如此,但它足以应对代码中偶尔出现的 eval 操作。未来,当 Workers 原生支持 eval 时,我们将放弃 Boa。

复制链接页面渲染器

该组件主要负责根据计算出的页面对象生成实际像素。其工作原理如下:


PageRenderer 与 Engine Worker 循环工作。每次引擎需要一帧时,PageRenderer 都会从 PageScript 获取页面对象(也称为场景),从静态资源中获取内部字体和图像,将所有内容栅格化到图像缓冲区中,然后以客户端可以显示的格式(例如 JPEG/PNG 或 PDF)将缓冲区返回给引擎。

这里的大部分魔法是由另一个 Blitz 模块blitz-paint处理的,它又使用 Parley 将字符塑造成字形、选择字体并将文本分成行。

Workers 内置的 RPC 系统:同一应用程序,多个隔离区

Cloudflare Workers 内置了远程过程调用 (RPC) 系统,允许您调用其他 Workers 上的方法、在它们之间传递对象,以及调用这些对象上的方法。您无需担心 API 架构、类型或身份验证,只需调用 remoteFunction(...params) 即可。您既可以享受远程 Workers 的隔离性和资源优势,又可以像使用 JavaScript 在本地访问所有函数一样方便快捷。

Kitesurf 使用这种 RPC 系统:引擎工作进程通过 RPC 调用页面渲染器工作进程的 renderFrame() 方法,只需一次调用即可获得一个 PNG 图像作为结果。由于渲染器不保存页面状态(只有一个一次性缓存),引擎可以在任何失败或卡住的 RPC 调用时安全地终止并重新启动它——这使得每个渲染请求都是自包含的、可重试的,并且其隔离成本低廉且可丢弃。

复制链接Kitesurf 已通过超过 215,000 次 WPT 测试,并且还在不断增长

Kitesurf 运行正常。它已经通过了超过 215,000 次WPT 测试,而且我们每周都在新增数百次通过测试。您可以在这里看到自项目启动以来,Kitesurf 的发展历程,直至最新版本:


值得注意的是,对代理程序而言重要的浏览器组件(例如 CSS、DOM、HTML、选择、SVG 和 XHR)已经得到了很好的支持。即使是像流这样在代理程序上下文中可能并不特别重要的组件,现在也得到了相当不错的支持。


从性能上看,Kitesurf 的表现相当不错。以下是使用包含14 个 URL 的语料库,对 Chromium 和 Kitesurf 进行五次 Browser Run快速操作测试的中位数比较结果。

指标 风筝冲浪 铬(温水池) 风筝冲浪,相关
CPU:截图 380毫秒 1173毫秒 比 Chromium 节省 3.1 倍 CPU 资源
CPU:HTML提取 229毫秒 877毫秒 比铬少3.8倍
内存:屏幕截图 57.8 MiB 271.0 MiB 比铬少4.7倍
内存:HTML提取 39.4 MiB 273.7 MiB 比铬少7倍
墙时间:截图 1148毫秒 637毫秒 比 Chromium 慢 1.8 倍
墙时间:HTML提取 820毫秒 472毫秒 比 Chromium 慢 1.7 倍

Chromium之所以能赢得计时赛,是因为已经处理过该页面的即时编译器(JIT)总是比冷启动的软件渲染器更快——今天它的确领先了大约1.7倍。大部分差距来自于光栅化和JPEG/PNG编码,我们会继续优化这方面。

但与 Chromium 相比,Kitesurf 在内存和 CPU 方面优势显著,而内存和 CPU 正是真正影响账单金额的关键因素,Kitesurf 的内存占用量是 Chromium 的 3-7 倍。更少的内存意味着我们可以运行更多会话,更好地扩展,并从根本上降低我们和您的成本。

复制链接最重要的测试:风筝冲浪运行 Doom

我们在设计决策中强调了测试的重要性,但我们都知道,无论做了多少测试,只有 Doom 能在项目上运行,项目才算真正完成。这是几年前我们用 Doom 做的一个小实验,Kitesurf 运行https://silentspacemarine.com/ 的截图。

立即在浏览器中尝试运行

您今天即可使用 Browser Run 试用 Kitesurf,目前处于测试阶段,可免费使用 ,但每个帐户的使用次数有限制

浏览器运行 CDP 端点现在支持 Kitesurf,因此您现有的客户端PuppeteerPlaywrightchrome-remote-interface或任何支持 MCP 和 CDP 的 AI 代理均可正常工作。您只需将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 的快速操作功能。同样,只需将browser=kitesurf 其添加到快速操作端点即可。例如,如果您需要快速截取维基百科的屏幕截图,以下方法即可:

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 开发者工具运行 Kitesurf Playground

探索 Kitesurf 的另一种方法是使用我们的公共实验平台。您可以在这里输入任何网址,查看 Kitesurf 如何渲染页面并与之交互。

Playground 的一个亮点在于我们在用户界面中集成了 Chrome 开发者工具,因此您可以检查展开的 DOM 元素、读取控制台消息,并在 Kitesurf 渲染页面时监控网络活动。更重要的是,我们还实现了必要的 CDP 指令,使内存面板能够报告每个隔离区(包括框架)的 WebAssembly 占用空间,从而让您清楚地了解每个页面消耗的资源。


请查看我们的开发者文档,了解如何将 Kitesurf 与 Browser Run 结合使用的所有详细信息。

复制链接什么时候最适合风筝冲浪?

截至目前,Kitesurf 可以正确渲染TodoMVC(原生、React、Vue、Angular、Preact)、维基百科、Hacker News、Cloudflare 博客以及 Cloudflare 控制面板的大部分页面。我们将持续改进 Kitesurf,提高 WPT 测试的通过率,从而增强其对更复杂网页的兼容性。

Kitesurf 非常适合需要渲染页面但又能接受无法使用功能齐全、像素级精准的 Chromium 浏览器的 AI 代理。它也非常适合依赖一次性快速操作的自动化程序和应用程序,例如从页面提取内容或为兼容的网站生成 PDF 或屏幕截图。

可以将 Kitesurf 视为一个短暂的、完全隔离的、无状态的引擎,它设计为仅在任务期间存在,并且可以很好地扩展到突发性的、人工智能驱动的工作负载。

复制链接风筝冲浪目前还无法做到的事情

如果你需要播放视频、渲染 WebGL、使用真实的 TLS 指纹进行机器人挑战握手,或者启动需要持久状态的十分钟认证会话——Kitesurf 目前还不是最佳选择。只需使用 Browser Run 的默认设置即可,它基于 Chromium 内核。

要了解某个网站是否与 Kitesurf 兼容,最好的方法就是亲自尝试。您可以使用 API 进行测试,或者更快捷地在我们的公共测试环境中进行测试。

探索 DevTools 面板,了解幕后发生的事情,尤其要注意控制台和内存指标。

它去哪儿了

Kitesurf 项目上线十二周了。第一次提交是在五月份。以下是我们正在积极开发的一些内容:

  • 更完善的 CDP 覆盖范围。Kitesurf 实现了 CDP 协议的一个子集,足以满足大多数代理和自动化工具的需求,包括强大的 DOM 和网络检测功能。我们将持续扩展其功能,力求做到尽可能全面。
  • 提高屏幕截图和 PDF 的渲染保真度 ,因为我们知道 LLM 通常从图像而不是底层文本获得更好的效果。
  • WPT覆盖范围。 我们正在快速迭代,添加更多Web API,并通过更多WPT测试,力争使Kitesurf达到生产就绪状态。
  • 效率 。我们持续运行 CPU、内存和运行时间基准测试,并与其他开发者平台团队紧密合作,力求使 Kitesurf 尽可能地降低成本、提高效率。

复制链接最后说明

感谢您耐心读到这里——我们知道这是一篇篇幅较长且技术性较强的博文,但希望您能从中获得乐趣。我们之所以如此详尽地阐述,是因为我们深知开发一款新浏览器(即使是针对特定用途的浏览器)的重要性,同时也深知其复杂性。

风筝冲浪目前还处于早期阶段,但我们希望尽快向大家开放,并收集大家的反馈。团队将积极改进风筝冲浪,频繁更新,重点提升其性能、效率和兼容性。

最后还有一点:一旦准备就绪,我们将开源 Kitesurf——希望很快就能实现。我们的目标是让任何客户都能根据自身需求,在自己的账户上部署他们自己版本的 Kitesurf。

所以,不妨在测试服里试试,关注我们的更新日志,然后来Discord和团队交流。分享你的体验并给我们反馈;我们会认真倾听。

测试地址:
https://kitesurf.cloudflare.app/

和 虚拟浏览器差不多的东西,你懂的,也能拿来翻墙和匿名化自己

@chonglangtv 能不能开发一个一键翻译的功能,这样直接搬英文原文就行