Cloudflare Blog (via Future Tools)

Introducing Kitesurf: The agent-first browser that runs in V8 isolates on Cloudflare Workers

Brief

Kitesurf is an agent-first browser implemented to run entirely on Cloudflare Workers (V8 isolates) and optimized for AI agents and bursty automation rather than human-grade visual fidelity. The project (first commit in May 2026, ~12 weeks old at announcement) uses a three-part design: Engine (exposes Chrome DevTools Protocol for compatibility with Puppeteer/Playwright and other CDP/MCP clients), PageScript (per-page Dynamic Worker isolates that populate globalThis/document and execute JS/Wasm using Rust-compiled modules like Blitz and Stylo; Boa JS handles eval), and PageRenderer (rasterizes scenes with blitz-paint and Parley to produce PNG/PDF outputs). All outbound network access is funneled through a single SandboxOutbound worker that enforces CORS, injects headers, filters responses, and isolates cookie jars.

Kitesurf emphasizes extensive automated testing (selected Web Platform Tests plus integration and visual regression tests against Chromium) and already passes 215,000+ WPTs. Benchmarks on a 14-URL corpus show 3–7× lower CPU and memory use than Chromium for screenshots and HTML extraction, at the cost of ~1.7–1.8× slower wall-clock times due to software rasterization and encoding. It is available in Browser Run (beta) today via the browser=kitesurf parameter and a public playground with integrated DevTools and memory metrics. The team plans wider CDP coverage, better rendering fidelity, more WPT compatibility, ongoing efficiency improvements, and eventual open sourcing; current gaps include video, WebGL, advanced fingerprinting, and long-lived authenticated sessions.

Why it matters

Kitesurf is a new agent-focused browser that runs entirely on Cloudflare Workers (V8 isolates) and was built in ~12 weeks with the first commit in May 2026; it is available free in beta via Browser Run (use parameter browser=kitesurf) subject to per-account limits.

Key details

  • Architecture is split into three main components — Engine (CDP-compatible public-facing worker), PageScript (per-page Dynamic Worker isolates that parse HTML/CSS/JS using Rust/Wasm modules like Blitz and Stylo, and Boa JS to handle eval), and PageRenderer (rasterizes scenes with blitz-paint/Parley) — with all network fetches proxied through a single SandboxOutbound worker enforcing CORS, headers, and per-page cookie jars.
  • Kitesurf passes 215,000+ Web Platform Tests (WPT) and is adding hundreds weekly; testing approach combines selected WPT, integration tests against real sites, and visual regression comparisons to Chromium.
  • Performance vs Chromium (median of five quick-action runs on a 14-URL corpus): CPU for screenshots 380 ms vs 1,173 ms (3.1× less), CPU HTML extraction 229 ms vs 877 ms (3.8× less); memory for screenshots 57.8 MiB vs 271.0 MiB (4.7× less), memory HTML extraction 39.4 MiB vs 273.7 MiB (7.0× less); wall-time is slower (screenshots 1,148 ms vs 637 ms, ~1.8× slower) due to software rasterization and PNG/JPEG encoding.
  • Current limitations: cannot play video, run WebGL, mimic real TLS fingerprints for bot-challenges, or handle long authenticated sessions; roadmap items include fuller CDP coverage, rendering fidelity, WPT coverage, efficiency optimizations, and planned open sourcing.
Source evidence

Introducing Kitesurf: The agent-first browser that runs in V8 isolates on Cloudflare Workers

Should we build our own browser?

This is one of those questions that has come up every few months internally at Cloudflare for years. Unsurprisingly, it’s the kind that triggers long threads with multiple reasons and persuasive arguments on why we should do it. The browser is obviously the most important software we use every day on our computers; it’s arguably the operating system of the Internet. We’re a company on a mission to help build a better Internet — who wouldn’t want to take on the challenge of building a new browser?

But we never quite found the balance between the technical difficulty of such an endeavour and the unique problems we’d be solving by doing it. And so, the idea was shelved, over and over again. Until now.

Something magical happened: we reached a tipping point where a series of powerful technical advancements in our Developer Platform became a reality, while the advent of AI agents and the demand for a new kind of browser became critical at the same time.

Running WebAssembly (Wasm) in Workers is now very mature. Primitives like

,

dynamic workers,

SQLite-based Durable Objects,

Worker-to-worker RPC, higher

service bindingsand higher

NodeJS compatibilityopen doors to much more ambitious and complex applications that were simply not possible before.

limits Browser Run, our headless browser automation API product, has seen tremendous growth with the rise of AI. Agents need browsers in order to perform many tasks, and in many cases cannot succeed without them.

But there's a problem — browser engines like Chromium were built for humans, not agents, and they come with overhead that AI models simply do not need. They consume so much memory and compute that providing every agent with its own instance is prohibitively expensive, restricting large parts of the Web to only the most sophisticated and costly AI models with higher parametric knowledge, while locking out many other agentic applications.

We should be giving *all *agents a browser that excels at what’s important for an AI model, even if that means being light on what’s only useful for humans. For example:

  • AI doesn’t care about tabs, themes, browser extensions, or synchronization across devices. It cares about token count, context windows, scalability, performance, and costs.
  • Structured, machine-readable content is important, but visual perfection, smooth 60-fps scrolling is not. Agents will be just fine if the CSS parsing is slightly off or the rendering isn’t pixel perfect.
  • The threat model in the context of AI using a browser is different. New problems like prompt injection and tool safety are top priorities.

Faced with these realizations, 12 weeks ago we asked the question again: Should we build our own browser? This time the answer was unanimous: Yes!

Today we are announcing Kitesurf, a new browser that runs entirely on top of Workers that we built specifically for agents, available for free while in beta in Browser Run.

Kitesurf is significantly more efficient in CPU and memory consumption than Chromium for common agentic tasks like screenshots and HTML extraction. What follows is the story of how we built it. Buckle up, it’s going to get technical — but we promise to keep it interesting.

How it started

Kitesurf started as many other great ideas have started at Cloudflare. Someone found something interesting, and the next thing you know they end up “nerd sniping” the rest of the team with a seemingly impossible but very attractive idea.

We got the initial inspiration from obscura, a headless engine written in Rust for AI automation that has “no Chrome, no Node.js, no dependencies.”

Then, with the help of an AI agent, we tried to port it to Workers. It didn't work very well at first. But once we gave the AI a solid plan and a clear definition of success — detailed enough for the agent to loop endlessly and ask questions when needed — it did work.

Blown away by this (barely) working proof of concept, we decided to let the team cook.

Design decisions

Here are some of the design decisions we made before we started.

Tests, tests, tests

We knew that moving from a prototype to a full-blown browser that could actually be useful for tasks at scale in production would take a lot of work and iteration. We won’t hide that using AI to accelerate the process was key. But how do you use AI in such a complex project, keeping the quality of both code and results under control without losing velocity? The answer is to provide as many tests as you can.

Enter the Web Platform Tests (WPT), the ideal setup: an extensive suite of success criteria that gave the AI agents clear goalposts for assessing feature conformance. We curated the selection and order of features to assign to the agents, allowing humans to focus on architectural work and reviewing the agents' approaches.

However, WPT tests only go so far: they measure conformance to W3C standards, not a browser's ability to render and interact with real-world websites. To bridge this gap, we implemented a

combination of integration testing and visual regression testing — it runs multistep

tests on real websites against both Chromium and Kitesurf not only by comparing the assertions that it makes, but also rendering outputs at every step to highlight any unwanted differences.

PuppeteerUse Rust when possible

Cloudflare has been working on providing great support for WebAssembly (Wasm) in Workers for quite some time. This is great because we can use high-performance C, C++, and Rust packages and compile them to Wasm. If we use Emscripten (for example) and its many layers of mocked dependencies, the compiled binary can get bulky and slow.

Instead, we opted for native Rust whenever possible and to compile directly to WebAssembly using wasm-bindgen, thus avoiding unnecessary emulation layers and running as close to the metal as possible,

.

reliablyException handling

A browser must render the whole unreliable and sometimes hostile web without ever dropping the page it's holding, so exception handling is more than just hygiene — it's how the application survives bad input without just crashing outright.

So we committed to one rule up front: any failure degrades to a blank frame or a missing element, never a dead session. Catch faults at every boundary, default to something safe and empty, and log enough to diagnose.

Isolation

Contrary to running a browser on your laptop (where you're visiting sites you trust, and it's acceptable to share some resources between them), an agent is pointed at whatever a task demands: arbitrary code from arbitrary origins.

So we built this browser on the assumption that every page load is untrusted input and every session starts fresh. Each component is isolated and has access only to the resources strictly necessary for its function.

This seems like a perfect fit for Cloudflare Workers, whose security model is built around isolation by design. But the platform only gets us the boundary between isolates. We still have to enforce the same principle at the application level, deciding what each component is allowed to touch and making sure nothing leaks across a page it shouldn't.

Stateless whenever possible

State is what makes failure expensive — if there's nothing to reconstruct, recovering from a crash is just starting a new one and replaying the request. A stateless component is disposable and parallel by nature: kill it the moment it stalls, run a thousand at once, and size them to demand instead of keeping things warm. That fits automation perfectly, where load arrives in bursts and the cheapest thing you can do is spin up work that costs only what it used and vanishes when it's done. In short, wherever a component can be stateless, it should be.

How we built it

Armed with a good plan, extensive tests, and a good tooling environment, we were ready to get started beyond the initial proof of concept. This is Kitesurf’s very high level life of a request that still holds today:

Let’s dive into the three main components that make Kitesurf work: the Engine, PageScript, and PageRenderer.

Fetching from origins

In order to render an untrusted web page, a browser has to fetch arbitrary assets — images, fonts, CSS, JavaScript, and Wasm files — off the Internet. This is one of the most dangerous operations a browser can do.

Kitesurf does it through one single component, the SandboxOutbound worker, and nothing else can touch the network directly — enforced by Dynamic Workers. The Engine uses it to bootstrap the page, fetching the main document and its scripts, and PageScript fetches everything else: stylesheets, images, fonts, and the page's own fetch() calls.

We use SandboxOutbound to enforce CORS, inject browser-shaped headers, filter responses, and keep each page's cookies in their own jar. Anything that fails our policy gets a 403 — each component gets precisely the network it needs and nothing more.

The Engine

The Engine is the only public-facing component of Kitesurf. It handles the Chrome DevTools Protocol (CDP) WebSocket and HTTP REST APIs, serves a landing page that is useful for internal testing purposes and, most importantly, stores each session state. All other components are stateless.

The advantage of using CDP is client compatibility: Puppeteer, Playwright, chrome-remote-interface, and the actual Chrome DevTools frontend. Point them at Kitesurf and they will all just work. This is also how Browser Run

(more on why this is important later).

worksContrary to what the name suggests, the Engine is actually the simplest of the Kitesurf components. The fun parts come next.

PageScript

PageScript offers a good example of the power of our new Workers features: in this case, Dynamic Workers.  Kitesurf simply wouldn’t have been possible before this.

Here’s a simplified diagram of how PageScript works internally.

Every next page or out-of-process iframe ( OOPIF) uses Dynamic Workers to spin up a long-lived PageScript isolate that handles the page session, consisting of a clean

and the

globalThisdocument object.

DOMThe DOM object is then populated with the results of parsing the HTML document and running all the JavaScript scripts. For parsing the HTML and the CSS we use parts of Blitz, a modular rendering engine, and

, Firefox’s high-performance CSS parser, both written in Rust.

StyloFor each found