Skip to content

Browser Sandbox

New Feature

Fully managed, secure, isolated browser environments for AI agents. No Chromium installs, no driver setup, no infrastructure.

Overview

Browser Sandbox gives you disposable, sandboxed browser sessions accessible via API, CLI, or SDK. Each session includes pre-installed Playwright, a CLI with 40+ commands, and a CDP WebSocket endpoint.

Installation

bash
# Add browser support to AI coding agents (Claude Code, Codex, Cursor)
npx -y firecrawl-cli@latest init --all --browser

# Install CLI globally
npm install -g firecrawl-cli

# SDKs
pip install firecrawl-py
npm install @mendable/firecrawl-js

Quick Start

Node.js SDK

javascript
import Firecrawl from '@mendable/firecrawl-js';

const firecrawl = new Firecrawl({ apiKey: "fc-YOUR-API-KEY" });

// 1. Launch session
const session = await firecrawl.browser();
console.log(session.cdpUrl);      // wss://cdp-proxy.firecrawl.dev/cdp/...
console.log(session.liveViewUrl); // embeddable read-only stream

// 2. Execute code in the sandbox
const result = await firecrawl.browserExecute(session.id, {
  code: `
    await page.goto("https://news.ycombinator.com");
    const title = await page.title();
    console.log(title);
  `,
  language: "node",
});
console.log(result.result); // "Hacker News"

// 3. Close session (saves profile if configured)
await firecrawl.deleteBrowser(session.id);

Python SDK

python
from firecrawl import Firecrawl

app = Firecrawl(api_key="fc-YOUR-API-KEY")

# Launch session
session = app.browser(ttl=300, activity_ttl=120)

# Execute Python code in sandbox
result = app.browser_execute(
    session.id,
    code='await page.goto("https://news.ycombinator.com")\ntitle = await page.title()\nprint(title)',
    language="python",
)
print(result.result)  # "Hacker News"

# Execute JavaScript
result = app.browser_execute(
    session.id,
    code='await page.goto("https://example.com"); const t = await page.title(); console.log(t);',
    language="node",
)

# Close session
app.delete_browser(session.id)

Session Response

When you launch a session, you get:

json
{
  "success": true,
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "cdpUrl": "wss://cdp-proxy.firecrawl.dev/cdp/550e8400-...",
  "liveViewUrl": "https://liveview.firecrawl.dev/550e8400-...",
  "interactiveLiveViewUrl": "https://liveview.firecrawl.dev/550e8400-...?interactive=true"
}
FieldDescription
idSession ID for all subsequent calls
cdpUrlWebSocket endpoint for CDP/Playwright connection
liveViewUrlRead-only embeddable stream URL
interactiveLiveViewUrlInteractive stream (users can click/type)

TTL Configuration

ParameterDefaultRangeDescription
ttl300s (5 min)30-3600sMaximum session lifetime
activityTtl120s (2 min)10-3600sAuto-close after inactivity

agent-browser CLI (Bash Mode)

The sandbox comes with agent-browser pre-installed — 40+ commands your AI agent can use via simple bash instead of writing full Playwright code.

Via Firecrawl CLI

bash
# Auto-launches a session if needed
firecrawl browser "open https://example.com"
firecrawl browser "snapshot"
firecrawl browser "click @e5"

Via API/SDK (language: "bash")

python
# Navigate
result = app.browser_execute(session.id,
    code='agent-browser open https://example.com',
    language="bash"
)

# Get accessibility tree with clickable refs
result = app.browser_execute(session.id,
    code='agent-browser snapshot',
    language="bash"
)

# Click element by ref
result = app.browser_execute(session.id,
    code='agent-browser click @e5',
    language="bash"
)

# Type into element
result = app.browser_execute(session.id,
    code='agent-browser type @e3 "search query"',
    language="bash"
)

# Screenshot
result = app.browser_execute(session.id,
    code='agent-browser screenshot /tmp/page.png',
    language="bash"
)

# Scroll
result = app.browser_execute(session.id,
    code='agent-browser scroll down',
    language="bash"
)

# Wait
result = app.browser_execute(session.id,
    code='agent-browser wait 2000',
    language="bash"
)

Key agent-browser Commands

CommandDescription
open <url>Navigate to URL
snapshotGet accessibility tree with clickable refs
click @refClick element by ref ID
type @ref "text"Type into element
screenshot [path]Take screenshot
scroll up/downScroll page
wait <ms>Wait milliseconds

Connect via CDP (Full Playwright Control)

Connect your own Playwright instance for maximum control:

javascript
import { chromium } from "playwright-core";

// Connect to the sandbox via CDP
const browser = await chromium.connectOverCDP(session.cdpUrl);
const context = browser.contexts()[0];
const page = context.pages()[0] || await context.newPage();

await page.goto("https://example.com");
console.log(await page.title());

// Do complex interactions
await page.fill('#search', 'firecrawl');
await page.click('button[type="submit"]');
await page.waitForLoadState('networkidle');

const results = await page.$$eval('.result', els =>
  els.map(el => el.textContent)
);

await browser.close();
await firecrawl.deleteBrowser(session.id);

Persistent Sessions (Profiles)

Save and restore cookies, localStorage, and session state across browser sessions:

javascript
// Create session with profile (read-write)
const session = await firecrawl.browser({
  ttl: 300,
  profile: {
    name: "my-logged-in-profile",
    saveChanges: true,  // saves state when session closes
  },
});

// Log in, do work...
await firecrawl.browserExecute(session.id, {
  code: `
    await page.goto("https://app.example.com/login");
    await page.fill('#email', 'user@example.com');
    await page.fill('#password', 'secret');
    await page.click('button[type="submit"]');
    await page.waitForLoadState('networkidle');
  `,
  language: "node",
});

// Close session — state is saved to profile
await firecrawl.deleteBrowser(session.id);

// Later — reuse the profile (already logged in)
const session2 = await firecrawl.browser({
  ttl: 300,
  profile: {
    name: "my-logged-in-profile",
    saveChanges: false,  // read-only: multiple concurrent readers OK
  },
});

Profile Locking

Only one session can write to a profile at a time. Attempting to open a second write session on the same profile returns a 409 conflict. Use saveChanges: false for concurrent read-only access.

Live View (Embeddable)

Embed a real-time view of the browser session in your UI:

html
<!-- Read-only view -->
<iframe src="LIVE_VIEW_URL" width="100%" height="600" />

<!-- Interactive view (users can click and type) -->
<iframe src="INTERACTIVE_LIVE_VIEW_URL" width="100%" height="600" />

List and Manage Sessions

javascript
// List active sessions
const { sessions } = await firecrawl.listBrowsers({ status: "active" });

// List destroyed sessions
const { sessions: old } = await firecrawl.listBrowsers({ status: "destroyed" });

// Delete a session
await firecrawl.deleteBrowser(session.id);
python
# Python
sessions = app.list_browsers(status="active")
app.delete_browser(session.id)

Supported Languages

LanguageValueWhat's Available
Node.js"node"Full Playwright, page object pre-bound
Python"python"Full Playwright, page object pre-bound
Bash"bash"agent-browser CLI + system commands

When to Use Browser vs Other Features

Use CaseRight Tool
Extract content from a known URLScrape
Search the web and get resultsSearch
Navigate pagination, fill forms, click flowsBrowser
Multi-step workflows with interactionBrowser
Parallel browsing across many sitesBrowser
Autonomous research (no URLs needed)Agent

API Endpoints

MethodPathDescription
POST/v2/browserCreate browser session
POST/v2/browser/{id}/executeExecute code in session
GET/v2/browserList browser sessions
DELETE/v2/browser/{id}Delete browser session

Cost

  • 2 credits per browser minute
  • Free users get 5 hours of free usage
  • Rate limit: up to 20 concurrent sessions (all plans)

Next: Agent (Research) →