One Parameter, 3.8× Less CPU: Kitesurf Pulls Chromium Out of Browser Run

One Parameter, 3.8× Less CPU: Kitesurf Pulls Chromium Out of Browser Run (and Costs You 1.7× in Time)

By Devy · Category: AI Dev Tools — General (Cat 10)

If you already have something running on Browser Run — a scraper, a screenshot pipeline, an agent that reads pages — the change Cloudflare shipped on August 6 is one query string:

browser=kitesurf

That’s the whole migration. Same endpoint, same Chrome DevTools Protocol, same Puppeteer or Playwright client. What changes underneath is that there is no longer a Chrome underneath. Kitesurf is a browser Cloudflare built from scratch on top of Workers — Rust and WebAssembly running inside V8 isolates — and it is explicitly not trying to be a browser for people to look at.

That’s the trade, and it’s a real one in both directions. Let’s measure it before deciding anything.

The numbers, side by side

Cloudflare published a comparison against a warm Chromium instance. These are their figures, self-reported, on two operations most agent pipelines actually do:

Kitesurf Chromium (warm)
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

Read the memory column first, because it’s the one describing a different thing than the others. 39 MiB versus 274 MiB per page isn’t “faster” — it’s how many pages fit at once. On a per-page budget that shrinks by 7×, concurrency stops being the thing that caps your pipeline. The CPU column is what shows up on the bill. The wall time column is what your agent feels.

And the wall time column goes the wrong way. Cloudflare doesn’t hide it or explain it away: a warmed-up JIT beats a software renderer, and Kitesurf renders in software. If your workload is one page at a time and a human is waiting, this is a downgrade. If your workload is ten thousand pages and nobody is waiting, you just cut CPU by roughly 3–4× and memory by 5–7× for the price of a query parameter.

The tutorial: measure your own before and after

Don’t take the table on faith — it was measured on Cloudflare’s pages, not yours. The whole point of a one-parameter change is that A/B testing it is nearly free.

Step 1 — Run the operation you actually care about, on Chromium. The quick action endpoint is enough to get a baseline:

curl -X POST \
  'https://api.cloudflare.com/client/v4/accounts/<accountId>/browser-run/screenshot' \
  -H 'Authorization: Bearer <apiToken>' \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://the-site-you-actually-scrape.com"}'

Step 2 — Add the parameter. Change nothing else.

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://the-site-you-actually-scrape.com"}'

Step 3 — If you drive it with Puppeteer or Playwright, the parameter goes on the WebSocket endpoint, not on the code:

const browser = await puppeteer.connect({
  browserWSEndpoint: `wss://…/v4/accounts/${accountId}/browser-run/…?browser=kitesurf`
});

Your selectors, your waits, your extraction logic — none of it changes. Kitesurf speaks CDP, so chrome-remote-interface and MCP clients work the same way: add the query string to --wsEndpoint and you’re done.

Step 4 — Compare three things, not one. Wall time (which will get worse), CPU time on the invocation (which should drop), and — the one people forget — whether the output is the same. Diff the extracted HTML. Eyeball the two screenshots. That comparison is the actual decision, and it takes an afternoon.

There’s also a playground at kitesurf.cloudflare.app where you can point it at a URL and inspect the result with Chrome DevTools, including a memory panel showing the WebAssembly footprint per isolate. Useful for a first look before you wire anything up.

What actually breaks

This is the half of the article that decides whether you migrate. Kitesurf does not support:

  • WebGL — anything canvas-3D renders nothing
  • Video playback
  • TLS fingerprinting for bot challenges — if your target site gates on it, you don’t get through
  • Persistent authenticated sessions beyond ~10 minutes — long logged-in flows are out
  • Pixel-perfect rendering — deliberately, this is the design premise
  • 60 fps scrolling

Notice the shape of that list. Everything on it is something a human needs from a browser. Kitesurf passes 215,000+ Web Platform Tests, so it’s not that the engine is thin — it’s that the parts it skipped are the parts an agent reading a page never asks for. It builds on Blitz, the open-source modular rendering engine, with Stylo for CSS and Parley for text shaping.

The practical rule: the workload that moves is the one where the output is text or a rough image, at volume, unattended. Scraping, HTML extraction, feeding pages to a model, thumbnail generation. The workload that stays on Chromium is visual regression testing, anything behind a long login, anything with a video or a 3D canvas, and anything where a person is watching a spinner.

Nothing stops you from splitting the two — it’s the same API, and the parameter is per-request.

Two open questions worth holding

Cold start isn’t in the table. Every Chromium figure Cloudflare published is against a warm instance, and they say so. But cold start is exactly where a V8 isolate should demolish a browser process, and it’s the one measurement missing from a benchmark table that otherwise has everything. Its absence is odd in the direction that would flatter them. If your pipeline is bursty rather than steady, that’s the number you’d want, and you’ll have to measure it yourself.

Nobody has answered the anti-bot question. A browser running on Cloudflare’s own network, fetching pages protected by Cloudflare — someone in the launch thread asked whether Kitesurf traffic gets treated differently from anyone else’s, and nobody from the team replied. It’s not an accusation, it’s an unanswered question, and it’s the first thing to test if the sites you fetch sit behind Cloudflare.

Cloudflare says it plans to release Kitesurf as open source — the word used is “hopefully soon” — with the goal of letting customers run their own instance on their own account. That is a plan, not a shipped artifact. Today the only way to run it is the hosted beta, which is free with per-account usage limits.

Where this sits

We covered Browser Run when Cloudflare turned a headless Chrome into an HTTP endpoint, and Lightpanda when an independent team argued that a browser for agents shouldn’t be a browser for humans with the screen turned off.

Kitesurf is Cloudflare conceding that argument inside its own product. Browser Run’s whole pitch was making Chrome easy to call; the follow-up is making Chrome optional. Lightpanda made the case; the interesting thing here is who’s now making it, and that they attached numbers.


And you? If you swapped one parameter on your heaviest scraping pipeline today, which would matter more to you — the CPU you stop paying for, or the wall time you’d be adding to every request?


Sources: