Skip to main content
Outcome: a browse -> parse in isolation -> analyze pipeline built from two boxes. Level: intermediate · Time: ~20 minutes · Pattern: the agent lives in the box.

When to use this

An agent that browses the open web faces two problems at once. The content is untrusted. Page scripts can be hostile, downloads can be malicious, and trackers pollute whatever profile they touch. Calling playwright.launch() on your host runs arbitrary remote code next to your process. Parsing the HTML afterwards with a heavyweight parser widens the surface further. The work does not fit one machine. Large-scale scraping and cross-browser checks want many browser instances at once, and installing Chromium, Firefox, and WebKit locally is both heavy and messy. The layered answer: a BrowserBox runs the real browser inside a microVM and exposes only a control endpoint; your automation script stays in your trusted process and drives it remotely. The HTML that comes back then goes into a CodeBox for parsing, so even the parser runs isolated. Only structured data crosses back.

Architecture

The automation logic stays on the host; only the browser and the parser are sandboxed. Two separate boxes means a hostile page cannot influence the parsing step either.

Prerequisites

  • BoxLite installed and a working virtualization host — see Installation.
  • A Playwright client pinned to the version inside the box — a mismatch fails the connection with 428 Precondition Required. You do not need playwright install; the browsers live in the box.
  • An OpenAI-compatible LLM endpoint for the analysis step.
  • The first run pulls a multi-gigabyte Playwright image.

Build it

Step 1: fetch the page with a real browser

Connect over CDP with endpoint(). That path drives the Chromium already baked into the image, so nothing has to be fetched at runtime.
To use Firefox, pass browser="firefox" and connect with playwright.firefox.connect(ws) — Firefox speaks WebDriver BiDi rather than CDP. WebKit has no CDP endpoint; it needs the Playwright Server mode described on Browser automation.

Step 2: parse the untrusted HTML in a second sandbox

The scraped HTML is never parsed on the host. It is copied into a CodeBox, extracted there with the standard library only, and comes back as JSON.
BrowserBoxOptions fields and both connection modes are documented on Browser automation.

Run it

The page was rendered by a browser in one microVM, parsed in another, and only a list of strings ever reached your process.

Trust and limits

  • What the boundary covers. Page scripts, downloads, and any parser weakness are confined to their box. Your process holds only the Playwright client and the extracted data. Both boxes are destroyed on exit.
  • Two boxes is the point. Parsing hostile HTML is itself risky. Keeping it in a separate CodeBox means a page that defeats your extraction logic still has not reached the host.
  • The client version must match the box. A Playwright client that disagrees with the in-box server fails with 428 Precondition Required. Pin both.
  • CDP does not cover every browser. endpoint() serves Chromium and Firefox. WebKit requires the Playwright Server mode.
  • Egress is open by default. Scraping needs that. If the target set should be fixed, add an egress allowlist — see Run untrusted tools safely.

Troubleshooting

Next steps

  • Scrape in parallel. One box per target URL, run with asyncio.gather, and bound the fan-out with a semaphore so you do not start dozens of VMs at once.
  • Cross-browser checks. The same script against chromium and firefox boxes, in parallel, with no local browser installs.
  • Turn the data into a chartBuild a data analysis agent picks up where the JSON lands.
  • Interact rather than read. Filling forms and taking screenshots is on Browser automation.