On Runtime, a screenshot is one call. It is taken inside a microVM that is discarded afterward. The page you capture runs in its own Firecracker machine, so a hostile site or a broken app never touches your server. Each capture can start from a clean browser. A sandbox that waits on a page load costs $0.03125 an hour at 2 vCPU and 4 GiB, because Runtime bills the CPU it uses (pricing).
Capture the screen
TypeScriptimport { writeFile } from "node:fs/promises";import { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ diskMiB: 8192 });await sbx.desktop.start({ width: 1440, height: 900 }); // ready in about a secondawait sbx.desktop.open("https://example.com");await writeFile("example.png", await sbx.desktop.screenshot());Pythonfrom withruntime import Sandboxwith Sandbox.create(disk_mib=8192) as sbx: sbx.desktop.start(width=1440, height=900) sbx.desktop.open("https://example.com") with open("example.png", "wb") as file: file.write(sbx.desktop.screenshot())Terminalruntime sandboxes desktop "${id}" startruntime sandboxes desktop "${id}" open https://example.comruntime sandboxes desktop "${id}" screenshot example.pngThe screenshot shows the whole screen at the size you started it with. That includes the browser window, its address bar and anything else open. The desktop and Chromium are ready on every server, so the first start in a sandbox takes well under a second.
Capture an app running in the same sandbox
An app that an agent just built can be photographed without exposing it to the
internet. Start it with spawn, which keeps it running. Then point the
desktop's browser at localhost:
TypeScriptimport { writeFile } from "node:fs/promises";import { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ diskMiB: 8192, timeoutSeconds: 1800 });await sbx.files.upload("./site", "/workspace/site");await sbx.spawn("python3 -m http.server 3000", { cwd: "/workspace/site" });await sbx.desktop.start({ width: 1280, height: 800 });await sbx.desktop.open("http://localhost:3000");await writeFile("home.png", await sbx.desktop.screenshot());Pythonfrom withruntime import Sandboxwith Sandbox.create(disk_mib=8192, timeout_seconds=1800) as sbx: sbx.files.upload("./site", "/workspace/site") sbx.spawn("python3 -m http.server 3000", cwd="/workspace/site") sbx.desktop.start(width=1280, height=800) sbx.desktop.open("http://localhost:3000") with open("home.png", "wb") as file: file.write(sbx.desktop.screenshot())To view the app yourself too, share port 3000 as a private HTTPS preview.
A full-page capture with Playwright
The desktop captures only what fits on the screen. For the full length of a
page, or for thousands of pages from a script, use a headless browser. With an
image named playwright, built as in the Playwright guide,
one script takes the capture:
TypeScriptimport { writeFile } from "node:fs/promises";import { Sandbox } from "withruntime";const script = `import { chromium } from "playwright";const browser = await chromium.launch();const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });await page.goto(process.argv[2], { waitUntil: "networkidle" });await page.screenshot({ path: "full.png", fullPage: true });await browser.close();`;await using sbx = await Sandbox.create({ image: "playwright" });await sbx.files.write("/workspace/full.mjs", script);await sbx.exec(["node", "full.mjs", "https://example.com"], { check: true, timeoutMs: 120_000 });await writeFile("full.png", await sbx.files.read("/workspace/full.png"));Many pages at once
Each capture can have its own sandbox, so no two pages share cookies, storage or a crashed browser. A paid account runs 100 sandboxes at the same time. An account without credit runs four:
TypeScriptimport { writeFile } from "node:fs/promises";import { Sandbox } from "withruntime";const urls = ["https://example.com", "https://example.org", "https://example.net"];await Promise.all( urls.map(async (url, i) => { await using sbx = await Sandbox.create({ diskMiB: 8192 }); await sbx.desktop.start(); await sbx.desktop.open(url); await writeFile(`page-${i}.png`, await sbx.desktop.screenshot()); }),);A create past the account's limit waits up to two minutes for room instead of failing. A batch larger than the limit therefore queues (errors and retries).
Which way to take it
| Way | Captures | Best for |
|---|---|---|
sbx.desktop.screenshot() |
The whole screen, as PNG | Agents that act on what they see |
runtime sandboxes desktop <id> screenshot <file> |
The same, from a terminal | Scripts and quick checks |
runtime_sandboxes_desktop_screenshot |
The same, as an MCP tool result | Agents connected to Runtime's MCP |
Playwright page.screenshot() |
One page, visible area or full length | Pages in bulk, visual tests |
sbx.desktop.recordings |
An MP4 of the screen over time | Showing what happened between shots |
Mistakes and how Runtime handles them
- A disk too small for what you capture. The desktop and Chromium install
nothing on the sandbox's disk, but Playwright's browsers, a site's files and
recordings do. The default 4 GiB sandbox had about 2.5 GiB free on
24 September 2026. Ask for
diskMiB: 8192. - Capturing before the page draws.
openstarts Chromium on the address and returns; it does not wait for a slow page to load. Wait for a known element with Playwright, or take another screenshot after a pause. - A server started with
exec. It ends with its command, and the browser then shows an error page.spawnkeeps it running. - Ports without credit. A sandbox without credit reaches ports 80 and 443 only, which covers ordinary websites; a paid sandbox reaches any port.
Related
- Control a desktop for clicks, keys and video.
- A browser automation agent.
- Preview agent-built apps.
Start
Terminalnpx withruntime sandboxes run --keep -- echo readyA new account gets 100 free hours of a 1 GB machine in its first 30 days, with no card required.
Facts on this page were checked on 26 October 2026.