Every box can come with its own browser. Create one with browser: true and you get a managed, headless Chromium that boots on first use. Nothing to install, no apt-get, no Chromium binary to keep up to date.
This guide scrapes a JavaScript-heavy site with that built-in browser. We read rendered pages through the SDK, extract structured data against a schema, then connect Playwright over CDP to harvest many pages deterministically.
The browser can only be provisioned when the box is created. It cannot be enabled on an existing box. See Browser for the full surface.
1. Installation#
playwright-core is enough. You connect to the box's Chromium instead of launching one locally, so there are no browser binaries to download on your side either.
Set your environment variable:
2. Create a box with a browser#
The first tab.create boots Chromium. The tab handle is addressed by its Chrome DevTools Protocol target id, so it stays valid across navigations and you can re-attach to it later with box.browser.getTab(id).
3. Read the rendered page#
content() returns the tab's current title, URL, visible text, and links from the real DOM, including anything JavaScript rendered after load. No model is involved, so this costs no tokens.
This is already enough for a crawler: follow the links you care about with tab.goto(url), read each page with content(), and chunk the text into a dataset.
Client-rendered pages can hydrate after domcontentloaded. If page.text comes back short, wait briefly and call content() again until it settles.
4. Extract structured data with a schema#
When you want typed fields instead of raw text, extract() hands the page to a DOM-aware agent inside the box and validates the result against a Zod schema:
The result is parsed with your schema before it is returned, so a successful call always gives you the shape you asked for. Capture a screenshot next to it if you want provenance for what was on screen:
extract uses an LLM and is metered. It needs a model provider key on the box or your account. See AI Actions for the model override and the full list of providers.
5. Scrape many pages with Playwright over CDP#
An AI call per page gets expensive fast. For repeatable multi-page work, drive the same browser with Playwright. cdpUrl() returns an authenticated WebSocket URL that chromium.connectOverCDP accepts directly:
This is an ordinary Playwright script. Migrating an existing one is usually a single line: chromium.launch() becomes chromium.connectOverCDP(await box.browser.cdpUrl()), and your selectors, actions, and assertions stay as they are.
The CDP URL carries its auth token in the URL. Anyone who has it gets full control of the browser, so treat it as a secret.
CDP and the SDK drive the same browser and the same tabs. A page opened by Playwright shows up in box.browser.listTabs(), and a tab created by the SDK is visible to Playwright, so you can mix scripted steps with AI steps in one run.
6. Compile the selectors once, then scrape for free#
The two previous sections combine into the pattern worth using in production: let the model read the layout once and emit selectors, then run every later scrape deterministically with no model tokens at all.
This is a file of its own rather than a continuation of the script above, so it opens its own box and browser:
Leave that tab open. Closing the last tab shuts the browser down, and the CDP connection in scrape() then fails with The browser is shutting down.
Caching the recipe on the box filesystem means the box carries its own knowledge: the next run reuses it and calls no model at all.
Validate the harvest (row count, non-empty fields, price format) on every run. When validation fails, the site's layout changed: recompile the recipe with one extract call and cache the new one. That way the AI cost is paid once per layout, not once per page.
A full runnable version of this is the AI-compiled scraper example.
7. Reuse the box across runs#
A browser box has nothing to install, so there is no setup cost to snapshot away. What is worth keeping is the box itself: the cached recipe, the cookies, and a logged-in session.
Keep the box id and re-attach on the next run:
The box pauses when idle and resumes on demand with its filesystem intact. It bills until you delete it, so delete it when you are done with the target site:
To log in once and have every later script reuse that session, see the login once, reuse session example.
Next steps#
- Reading pages for
content,screenshot, andextract. - AI actions for
observeandact, including replaying a resolved action with no LLM. - Live view and recordings to watch or replay a scrape.
- Browser cookbook for runnable examples across crawling, automation, and testing.