Browser & computer use
Chromium with CDP and a live noVNC desktop inside a microVM. Drive it with Playwright or browser-use, watch it live, and run agent loops.
Run Chromium with the Chrome DevTools Protocol (CDP) and a live noVNC desktop inside an Isorun microVM. Point a CDP client at it (Playwright, pyppeteer, browser-use), and open the noVNC URL to watch the session in real time.
The image ships Xvfb (a virtual display), a window manager, Chromium started
with --remote-debugging-port=9222, x11vnc, and noVNC. The public-port proxy
exposes CDP and the noVNC web UI through the same
https://<port>-<runID>.isorun.app/ URLs as any other in-sandbox service.
Tip
You don't need to handle bind-address quirks. Services that default to localhost-only, including Chromium's CDP, are reached automatically when you call sandbox.url(port).
What you get:
- CDP on port 9222. Connect Playwright, pyppeteer, browser-use, or any client that speaks the Chrome DevTools Protocol.
- noVNC web UI on port 6080. Open it in any browser to watch the agent operate Chromium in real time. WebSocket pass-through is end-to-end, so the live screen updates without extra setup.
Start the sandbox
import { Isorun } from 'isorun'
const isorun = new Isorun()
const sandbox = await isorun.create({
image: 'docker.io/isorun/computer-use:1',
vcpus: 2,
memMiB: 4096,
})
try {
// Start the desktop. & disown so exec returns immediately and the
// server keeps running.
await sandbox.exec('/usr/local/bin/start-vnc.sh & disown', 2)
await new Promise((r) => setTimeout(r, 2000)) // wait for binds
console.log('CDP :', sandbox.url(9222)) // https://9222-<runID>.isorun.app/
console.log('noVNC :', sandbox.url(6080)) // https://6080-<runID>.isorun.app/
} finally {
await sandbox.destroy()
}Drive it with Playwright
import { chromium } from 'playwright'
import { Isorun } from 'isorun'
const isorun = new Isorun()
const sandbox = await isorun.create({
image: 'docker.io/isorun/computer-use:1',
vcpus: 2,
memMiB: 4096,
})
try {
await sandbox.exec('/usr/local/bin/start-vnc.sh & disown', 2)
await new Promise((r) => setTimeout(r, 2000))
const browser = await chromium.connectOverCDP(sandbox.url(9222))
const ctx = browser.contexts()[0] ?? (await browser.newContext())
const page = await ctx.newPage()
await page.goto('https://example.com')
console.log(await page.title())
await page.screenshot({ path: '/tmp/screenshot.png' })
await browser.close()
} finally {
await sandbox.destroy()
}The same CDP endpoint works with browser-use, pyppeteer, or anything else
that connects over the DevTools Protocol.
Watch the agent in real time
Open sandbox.url(6080) in any browser. You get the noVNC web UI showing the
live Chromium session: mouse moves, page loads, typed input, all of it. It's
useful for debugging agent loops and for building supervised flows where a
human watches the agent.
The page connects to a WebSocket VNC endpoint inside the sandbox. Isorun handles the protocol bridge, so the desktop session streams without custom network setup.
Use it with Anthropic or OpenAI computer use
Anthropic's computer use tool and OpenAI's computer-use model both work as a screenshot-and-action loop: the model looks at a screenshot, returns an action (click, type, key, scroll), your code executes that action, and you send back a fresh screenshot. The model never connects to the browser, and there is no CDP URL to hand it. That is the key difference from the Playwright path above, where your code drives Chromium directly over CDP.
To run that loop against an Isorun sandbox, the sandbox provides the desktop
(the Xvfb display you can watch over noVNC), and your agent loop captures
screenshots and injects mouse and keyboard events inside the sandbox through
sandbox.exec. For that you need an input tool such as xdotool in your
image. Anthropic's reference implementation
(Xvfb plus a window manager plus xdotool) is the simplest starting point. The
current tool version is computer_20251124 with the computer-use-2025-11-24
beta header.
For most browser tasks the CDP path above (Playwright or browser-use) is faster, cheaper, and more reliable than pixel-level computer use. Reach for computer use when there is no clean DOM to drive, such as a native desktop app or a canvas UI.
Size the sandbox
- vCPUs: 2 minimum. Chromium is slow when CPU-starved.
- Memory: 4 GiB minimum, more if you'll have many tabs open.
- Disk: the default 4 GiB scratch is enough. Bump it via
diskMiBif you expect downloads or large session storage.
A browser sandbox costs the same as any sandbox at the same vCPU + RAM
($0.025/vCPU-hr + $0.015/GiB-hr, see pricing),
and like every other Isorun sandbox you can sandbox.hibernate() it when idle
and pay nothing until the user comes back.
Next steps
- Public URLs shows how the CDP and noVNC ports are exposed.
- Lifecycle and hibernation covers hibernating an idle browser session.
- Any OCI image explains how to build your own browser image.