Browser sandboxes

September 19, 2026 ยท View on GitHub

A browser sandbox runs Chromium in a disposable sandbox. Use it when an agent needs a real browser without using your desktop profile.

Choose a sandbox for command-only work. Choose a browser sandbox for web-only automation. Choose a Linux computer when the agent needs a visible desktop with multiple applications.

Start and open a browser

celesto browser start --session-id research --live
celesto browser open research

The first command starts Chromium and prints connection details. The second opens its browser view on your machine.

List running browser sandboxes when you need to find a session:

celesto browser list

Stop one when you are finished:

celesto browser stop research

Keep a browser profile

A normal browser sandbox is temporary. Use a persistent profile when you deliberately want later sessions to reuse browser state:

celesto browser start --profile-mode persistent --profile-id work

Use --live when you need the interactive display URLs, and --record-video when you need a recording. Browser downloads are enabled unless you pass --no-downloads.

Use it from Python

Install Playwright on your machine before using the Python browser connection:

pip install playwright

Then connect to Chromium running inside the sandbox:

from celesto import Celesto

with Celesto.browser() as browser:
    remote_browser = browser.connect_playwright()
    page = remote_browser.contexts[0].new_page()
    page.goto("https://example.com")

Use it from TypeScript

The source checkout contains the browser-session API planned for the next TypeScript preview. Until that preview is published, install the local ts/ package rather than 0.1.0-preview.1.

Install the browser automation client before running the example:

npm install playwright-core

Playwright connects through CDP, the Chrome DevTools Protocol used to automate Chromium.

import { chromium } from "playwright-core";
import { SmolVM } from "@celestoai/smolvm";

const smolvm = new SmolVM({ runtimePath: "celesto" });
const session = await smolvm.browsers.create({
  mode: "live",
  profile: { mode: "ephemeral" },
});

try {
  await session.files.write("/workspace/task.txt", "visit example.com");
  const browser = await chromium.connectOverCDP(session.cdpUrl);
  const context = browser.contexts()[0];
  if (!context) throw new Error("Browser context is unavailable.");
  const page = context.pages()[0] ?? await context.newPage();
  await page.goto("https://example.com");
  console.log({
    sandboxId: session.sandboxId,
    cdpUrl: session.cdpUrl,
    viewerUrl: session.viewerUrl,
    displayUrl: session.displayUrl,
  });
  await browser.close();
} finally {
  await smolvm.close();
}

The returned browser session also supports commands and file transfer. Use session.exec() and session.files for work related to the browser. In live mode, viewerUrl opens Chromium's graphical display through noVNC, a browser-based remote-display client. displayUrl connects a VNC client or visual-control agent directly to that display. This browser view is not a general desktop; use a Linux computer for a terminal, file manager, and text editor.

The automation, viewer, and display endpoints are loopback-only, meaning they accept connections only from the same machine. Keep them in the trusted Node process rather than sending them to browser JavaScript or a remote client.

Implementation notes

Python browser sessions, profile IDs, local viewer endpoints, artifacts, and Playwright connections are implemented in src/celesto/browser.py. The TypeScript session wrapper is in ts/src/browser-session.ts, and the private bridge routes are in src/celesto/server/app.py. Public configuration types are in src/celesto/types.py and ts/src/types.ts, with coverage in tests/e2e/test_browser.py, tests/integration/test_server.py, and ts/test/sdk.test.ts.