Skip to main content
BrowserBox runs a full browser (Chromium, Firefox, or WebKit) inside an isolated VM and exposes it via Playwright Server or Chrome DevTools Protocol. You connect with Playwright or Puppeteer from your host — no browser install needed on the host.

What you’ll build

A script that:
  1. Launches a BrowserBox with Chromium
  2. Connects via Playwright or Puppeteer
  3. Navigates to a page and takes a screenshot
  4. Scrapes content from the page

Prerequisites

pip install boxlite playwright

Step 1: Launch a BrowserBox

Create a BrowserBox and get a connection endpoint.
browser.py
import asyncio
from boxlite import BrowserBox, BrowserBoxOptions

async def main():
    opts = BrowserBoxOptions(browser="chromium", memory=2048, cpu=2)
    async with BrowserBox(opts) as browser:
        ws = await browser.playwright_endpoint()
        print(f"Playwright endpoint: {ws}")
        # → ws://localhost:3000/


if __name__ == "__main__":
    asyncio.run(main())

Connection modes

BrowserBox has two mutually exclusive connection modes:
ModeMethodProtocolUse with
Playwright Serverplaywright_endpoint()WebSocketPlaywright (all browsers)
Direct CDP/BiDiendpoint()WebSocketPuppeteer, Selenium (chromium/firefox only)

Supported browsers

BrowserWorks with PlaywrightWorks with Puppeteer
chromiumYesYes (CDP)
firefoxYesYes (WebDriver BiDi)
webkitYesNo

Step 2: Take a screenshot

Connect to the browser and capture a screenshot.
screenshot.py
import asyncio
from boxlite import BrowserBox, BrowserBoxOptions
from playwright.async_api import async_playwright


async def main():
    opts = BrowserBoxOptions(browser="chromium", memory=2048, cpu=2)
    async with BrowserBox(opts) as browser:
        ws = await browser.playwright_endpoint()

        async with async_playwright() as p:
            # Connect to the browser running inside the VM
            b = await p.chromium.connect(ws)
            page = await b.new_page()

            await page.goto("https://example.com")
            await page.screenshot(path="screenshot.png")
            print("Screenshot saved to screenshot.png")

            await b.close()


if __name__ == "__main__":
    asyncio.run(main())

Step 3: Scrape a page

Extract content from a web page using standard DOM queries.
scrape.py
import asyncio
from boxlite import BrowserBox, BrowserBoxOptions
from playwright.async_api import async_playwright


async def main():
    opts = BrowserBoxOptions(browser="chromium", memory=2048, cpu=2)
    async with BrowserBox(opts) as browser:
        ws = await browser.playwright_endpoint()

        async with async_playwright() as p:
            b = await p.chromium.connect(ws)
            page = await b.new_page()

            await page.goto("https://news.ycombinator.com")

            # Extract the top 5 story titles
            titles = await page.eval_on_selector_all(
                ".titleline > a",
                "elements => elements.slice(0, 5).map(e => e.textContent)"
            )

            print("Top 5 Hacker News stories:")
            for i, title in enumerate(titles, 1):
                print(f"  {i}. {title}")

            await b.close()


if __name__ == "__main__":
    asyncio.run(main())

Step 4: Interact with a page

Read content, click links, and handle navigation.
interact.py
import asyncio
from boxlite import BrowserBox, BrowserBoxOptions
from playwright.async_api import async_playwright


async def main():
    opts = BrowserBoxOptions(browser="chromium", memory=2048, cpu=2)
    async with BrowserBox(opts) as browser:
        ws = await browser.playwright_endpoint()

        async with async_playwright() as p:
            b = await p.chromium.connect(ws)
            page = await b.new_page()

            await page.goto("https://example.com")

            # Get page title and content
            title = await page.title()
            heading = await page.text_content("h1")
            print(f"Title: {title}")
            print(f"Heading: {heading}")

            # Click a link
            await page.click("a")
            print(f"Navigated to: {page.url}")

            await b.close()


if __name__ == "__main__":
    asyncio.run(main())
BrowserBox allocates 2 CPUs and 2048 MiB of memory by default. Increase these if your pages are heavy or you’re running multiple tabs.

What’s next?

Connect to an LLM

Give your LLM agent the ability to browse the web by combining BrowserBox with function calling.

BrowserBox API reference

Full API docs for BrowserBox, BrowserBoxOptions, and connection endpoints.

AI agent integration

Production patterns for using BoxLite with AI agents.