Last of three field briefs this week — verdict first, sourced facts, then the decisions they force. If this format works better than my usual essays, say so and I’ll keep it.
What shipped. Cloudflare released Kitesurf, a browser built for agents instead of people, running in V8 isolates on Workers and reachable through Browser Run. Free in beta, per-account limits, opt in with a parameter.
Why it matters. The per-page cost of agent browsing just dropped by a factor of three to seven. Everything downstream of that — your bill, your egress volume, your injection surface — was sized against the old number.
What to do. Route to it for batch extraction; don’t migrate interactive loops to it. And re-check the controls that were implicitly rate-limited by browsing being expensive.
The facts
Cloudflare’s own measurements, across a 14-URL corpus run through Browser Run quick actions:
| Metric | Task | Kitesurf | Chromium | Ratio |
|---|---|---|---|---|
| CPU | Screenshot | 380 ms | 1,173 ms | 3.1× less |
| CPU | HTML extraction | 229 ms | 877 ms | 3.8× less |
| Memory | Screenshot | 57.8 MiB | 271.0 MiB | 4.7× less |
| Memory | HTML extraction | 39.4 MiB | 273.7 MiB | 7.0× less |
| Wall time | Screenshot | 1,148 ms | 637 ms | 1.8× slower |
| Wall time | HTML extraction | 820 ms | 472 ms | 1.7× slower |
And the structural facts:
| Claim | Detail |
|---|---|
| Compatibility | Implements the Chrome DevTools Protocol over WebSocket and HTTP REST; verified against Puppeteer, Playwright, chrome-remote-interface and the Chrome DevTools frontend |
| Standards coverage | Reported to pass over 215,000 Web Platform Tests |
| Built from | A modular rendering engine (Blitz), Firefox’s CSS engine (Stylo), plus Parley for text shaping — Rust components rather than a Chromium fork |
| Architecture | Four isolated parts: an Engine holding CDP and session state, PageScript for DOM and JS execution, PageRenderer for pixels, and SandboxOutbound as the single network egress point enforcing CORS and policy |
| Security stance | Designed on the assumption that every page load is untrusted and every session starts fresh |
| Not suitable for | Video playback, WebGL, bot-challenge handshakes needing real TLS fingerprints, and long authenticated sessions requiring persistent state |
Note the last row is Cloudflare’s own list, published in the launch post. That’s unusually direct for a launch, and it’s the most useful paragraph in it.
The number nobody quoted
Almost every write-up of this launch led with “3–7× less CPU and memory” and stopped there. The wall-clock row was in the same table and got dropped, which is a shame, because the two numbers together are the actual product decision and either one alone is misleading.
Kitesurf is cheaper per unit of work and slower per request. That is not a flaw; it’s a legible engineering trade, and it tells you exactly where the thing belongs:
- If your agent loop is latency-bound — a user is waiting, the browse is inside an interactive turn, the p95 of the whole loop is your SLO — a 1.7–1.8× regression on every page fetch lands directly in the number you’re judged on. Efficiency you can’t spend doesn’t help you.
- If your agent workload is throughput- or cost-bound — overnight enrichment, crawling a supplier catalogue, screenshotting a few thousand pages for a monitor — you’re paying for CPU-seconds and memory, both of which fall by a large multiple, and nobody is watching the clock on any individual page.
Most teams have both workloads and reach for one browser fleet for both. The interesting move here isn’t picking a winner; it’s noticing you now have two runtimes with genuinely different cost curves and a single parameter to select between them. That’s a routing decision, and it’s the same shape as routing traffic to the right model tier rather than sending everything to the biggest one.
Route it, don’t migrate to it
| Workload | Pick | Why |
|---|---|---|
| Batch HTML extraction, enrichment, crawls | Kitesurf | 3.8× CPU and 7× memory saving; per-page latency is irrelevant |
| Scheduled screenshot monitoring | Kitesurf | Same economics; nobody is waiting |
| Interactive agent turn with a user present | Chromium | The 1.8× wall-time hit lands in your p95 |
| Long authenticated session, multi-step form flows | Chromium | Persistent state is explicitly out of scope today |
| Anything needing video or WebGL | Chromium | Named limitation |
| Sites behind bot challenges | Neither — get an API or an agreement | See below |
That last row deserves saying plainly. Cloudflare lists bot-challenge negotiation as something Kitesurf doesn’t do, and the correct response to that is not to go looking for a runtime that does. If your agent architecture depends on defeating the bot detection of sites you don’t own, the problem is the architecture. Get an API, get an agreement, or accept the data isn’t available to you. Every reliability property you care about is worse on the other path anyway: no contract, no rate limit you can reason about, no notice before it breaks.
The part that matters more than the benchmarks
Buried under the performance table is the design decision I’d actually copy: SandboxOutbound, a single network egress point through which all page traffic passes and where policy is enforced, in a runtime where every session starts fresh and every page load is treated as untrusted.
Compare that with how agent browsing usually gets built. A pool of headless Chrome containers, started by whichever service needed them, with whatever egress the VPC happens to allow, retained between tasks because starting them is expensive, and no single place where you could answer “what did our agents fetch last Tuesday?” The performance difference between that and Kitesurf is interesting. The architectural difference is the one that shows up in an incident review.
Here’s why this is now a platform concern rather than an application detail. Every page an agent loads is untrusted text that ends up inside a context window, next to instructions. That is indirect prompt injection, and unlike most injection classes it needs no attacker access to your systems at all — it needs a page your agent will visit. Which means:
- Injection surface scales with browse volume, and browse volume is exactly what just got cheaper by 3–7×. Controls sized for the old volume are now sized for the wrong number. This is the same pattern as agent sprawl: the capability grew faster than the ability to govern it.
- A single policy-enforcing egress point is the control you want, and it’s the one hand-rolled fleets almost never have. Allowlists, per-agent egress attribution, and a retained record of what was fetched all become possible when there’s one door.
- Fresh-session-per-load is a security property that reads as a feature gap. No persistent state means no cookie or token carried from a poisoned page into the next task. The same fact that rules out long authenticated sessions is what makes cross-task contamination structurally hard. Take the trade knowingly rather than treating it as a limitation to work around.
None of that is unique to Cloudflare — you can build all three yourself. The point is that a purpose-built runtime starts you at a posture most self-managed fleets never reach, and the OWASP agentic risks I’ve walked through for platform teams largely live at exactly this boundary.
What I’d measure before switching anything
I have not run this against a real workload, and neither has anyone quoting the launch numbers at you. Cloudflare’s benchmark is 14 URLs and quick-action runs; that is a reasonable published baseline and it is not your traffic. Before routing anything meaningful:
- Replay your actual URL mix, not a synthetic corpus. Extraction cost is dominated by page complexity, and your pages are probably heavier than a benchmark set.
- Diff the extracted output, not just the timings. A different rendering engine can produce subtly different DOM for the same page. For a screenshot pipeline that’s cosmetic; for a scraper feeding a decision, it’s a correctness question.
- Measure at your concurrency, since the memory saving is the one that changes how many parallel sessions fit, and that’s usually where the real bill is.
- Check the tail, not the mean. Published means hide the pages that fall back or fail, and those are what page your on-call.
What I’d push back on
Twelve weeks from decision to beta is impressive and also exactly the right thing to be cautious about. A browser is a security boundary. Chromium’s hardening is the accumulated product of a very long time and a very large number of exploited bugs, and a new engine assembled from good Rust components does not inherit that history. The isolation architecture is a strong starting position — genuinely stronger than a container full of headless Chrome — but “passes 215,000 web platform tests” measures conformance, not adversarial resistance. Those are different properties and the number invites conflating them.
“Agent-first” is a positioning claim doing double duty. Dropping tabs, themes and pixel-perfect rendering is a sensible scope cut for automated browsing — but it’s a cut for automation, not specifically for agents, and headless automation has wanted this for a decade. That’s not a criticism of the engineering; it’s a reason to evaluate it as a cheaper headless runtime, on ordinary headless-runtime criteria, rather than as something categorically new.
And free-in-beta is not a cost model. The economics that make this attractive are the ones after pricing lands. Build the routing switch, keep the fallback path warm, and don’t let a batch pipeline become load-bearing on a beta price.
Open questions
- Does the per-page saving hold on heavy real-world pages, or does it narrow as JS execution comes to dominate? The published corpus can’t answer this and it decides the whole economic case.
- Is SandboxOutbound policy customer-configurable — can I express “these agents may fetch these domains” — or is it internal enforcement? That single answer determines whether this is a security control I own or one I merely benefit from.
- What’s the audit story? For an agent-browsing platform, a durable record of what was fetched by which identity is the artifact an incident review needs, and it’s the audit-trail question showing up in a new place.
- If agents get their own runtime, do sites get a way to serve them differently — and does that end up as a standard, or as everyone’s private heuristic?
Related: Agent sprawl is your next production incident · The OWASP Agentic Top 10, translated for platform teams · Your agent installs Markdown from the internet and runs it
Comments