SuperAPI AI Directory

browserbase-sdk

Agents & models

View repository

Updated 10-16 02:30

About this skill

Browserbase SDK

Browserbase runs production headless Chromium in isolated VMs and exposes a CDP WebSocket per session. Code drives the browser with Playwright, Puppeteer, Selenium, or Stagehand (AI primitives on top of Playwright). The @browserbasehq/sdk package is a thin REST client for sessions, contexts, extensions, and projects — it does not drive the browser itself.

Base URL & auth

POST https://api.browserbase.com/v1/sessions
x-bb-api-key: $BROWSERBASE_API_KEY
Content-Type: application/json

Env vars used by every official package:

Each browser runs in a dedicated VM destroyed after the session. SOC 2 Type II across plans, HIPAA on Scale.

Three integration paths

Path Packages Best for
Raw SDK @browserbasehq/sdk Manage sessions/contexts/extensions; no browser driving
SDK + Playwright/Puppeteer @browserbasehq/sdk + playwright-core or puppeteer-core Deterministic scripted automation
Stagehand @browserbasehq/stagehand AI-driven act/extract/observe/agent on top of Playwright

The SDK is REST only. Browser control happens through connectUrl (Playwright/Puppeteer/CDP) or seleniumRemoteUrl (Selenium). Stagehand wraps the SDK + Playwright internally.

Quickstart — Playwright (TypeScript)

import { chromium } from 'playwright-core';
import Browserbase from '@browserbasehq/sdk';

const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY! });

const session = await bb.sessions.create({
  projectId: process.env.BROWSERBASE_PROJECT_ID!,
});

const browser = await chromium.connectOverCDP(session.connectUrl);
const defaultContext = browser.contexts()[0];
const page = defaultContext.pages()[0];

await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.screenshot({ path: 'shot.png', fullPage: true });

await page.close();
await browser.close();
console.log(`Replay: https://browserbase.com/sessions/${session.id}`);

Quickstart — Puppeteer (TypeScript)

import puppeteer from 'puppeteer-core';
import Browserbase from '@browserbasehq/sdk';

const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY! });
const session = await bb.sessions.create({ projectId: process.env.BROWSERBASE_PROJECT_ID! });

const browser = await puppeteer.connect({ browserWSEndpoint: session.connectUrl });
const [page] = await browser.pages();
await page.goto('https://example.com');
await browser.disconnect();

Quickstart — Stagehand (TypeScript)

import { Stagehand } from '@browserbasehq/stagehand';
import { z } from 'zod';

const stagehand = new Stagehand({
  env: 'BROWSERBASE',
  apiKey: process.env.BROWSERBASE_API_KEY,
  projectId: process.env.BROWSERBASE_PROJECT_ID,
  model: 'google/gemini-3-flash-preview', // routed through Browserbase Model Gateway
});

await stagehand.init();
const page = stagehand.page;
await page.goto('https://news.ycombinator.com');

await page.act('click the first story link');
const data = await page.extract({
  instruction: 'extract the title and points',
  schema: z.object({ title: z.string(), points: z.number() }),
});

await stagehand.close();

Quickstart — raw HTTP

curl -X POST https://api.browserbase.com/v1/sessions \
  -H "x-bb-api-key: $BROWSERBASE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"projectId":"'"$BROWSERBASE_PROJECT_ID"'"}'

Session — request shape

type CreateSessionParams = {
  projectId: string;                  // optional with SDK; required via REST
  extensionId?: string;
  timeout?: number;                   // 60–21600 sec; defaults to project setting
  keepAlive?: boolean;                // Hobby+; survives disconnect
  region?: 'us-west-2' | 'us-east-1' | 'eu-central-1' | 'ap-southeast-1';
  proxies?: boolean | ProxyConfig[];
  userMetadata?: Record<string, string>; // ≤512 chars JSON, string values, no arrays
  browserSettings?: {
    context?: { id: string; persist?: boolean };
    viewport?: { width: number; height: number };
    blockAds?: boolean;               // default false
    solveCaptchas?: boolean;          // default true
    recordSession?: boolean;          // default true
    logSession?: boolean;             // default true
    advancedStealth?: boolean;        // Scale plan
    verified?: boolean;               // Scale plan, premium fingerprint
    captchaImageSelector?: string;
    captchaInputSelector?: string;
    os?: 'windows' | 'mac' | 'linux' | 'mobile' | 'tablet';
    ignoreCertificateErrors?: boolean; // default true
  };
};

Session — response shape

type Session = {
  id: string;
  createdAt: string; updatedAt: string;
  startedAt?: string; endedAt?: string; expiresAt?: string;
  projectId: string;
  status: 'PENDING' | 'RUNNING' | 'ERROR' | 'TIMED_OUT' | 'COMPLETED';
  region: string;
  contextId?: string;
  keepAlive: boolean;
  proxyBytes: number;
  userMetadata?: Record<string, string>;
  connectUrl: string;            // wss://… CDP endpoint
  seleniumRemoteUrl: string;     // https://… Selenium grid
  signingKey: string;
};

connectUrl is single-use per browser connection. Reconnecting the same connectUrl after disconnect requires keepAlive: true.

Default-context gotcha

Browserbase pre-creates the browser context. Calling browser.newContext() in Playwright spawns a second context that ignores browserSettings.context/proxies. Use the existing one:

const defaultContext = browser.contexts()[0];
const page = defaultContext.pages()[0]; // pre-created blank page

Lifecycle

// Release a session early
await bb.sessions.update(session.id, {
  projectId: process.env.BROWSERBASE_PROJECT_ID!,
  status: 'REQUEST_RELEASE',
});

// Live debugger URLs
const live = await bb.sessions.debug(session.id);
// { debuggerUrl, debuggerFullscreenUrl, wsUrl, pages: [{ id, url, debuggerUrl, ... }] }

// Filter sessions by metadata
const matches = await bb.sessions.list({ q: "user_metadata['env']:'staging'" });

Feature map

Feature Trigger Reference
Full session API: create/list/retrieve/update/debug, lifecycle, regions, keep-alive, metadata bb.sessions.* references/sessions.md
Playwright + Puppeteer connection patterns, default-context gotcha, screenshots, navigation connectOverCDP, puppeteer.connect references/playwright-puppeteer.md
Stagehand AI primitives: act/extract/observe/agent, ConstructorParams, Model Gateway, BYO LLM import { Stagehand } references/stagehand.md
Persistent auth state via Contexts, persist: true, one-per-site rule bb.contexts.*, browserSettings.context references/contexts.md
Browserbase-managed/external/none proxies, geolocation, domainPattern rules proxies: true, proxies: [{type:...}] references/proxies.md
Advanced stealth, verified browsers, captcha solving (custom selectors), block-ads advancedStealth, verified, solveCaptchas references/stealth-and-captcha.md
Downloads (Browser.setDownloadBehavior to "downloads"), uploads (setInputFiles, large-file API), file chooser bb.sessions.downloads.*, bb.sessions.uploads.* references/downloads-uploads.md
Live view, recordings (rrweb), logs, debugger URLs, embedding bb.sessions.debug, sessions.recording, sessions.logs references/observability.md
Custom extensions via uploaded zip bb.extensions.create, extensionId references/extensions.md

Always-fresh docs

Append .md to any docs page for clean Markdown:

Common pitfalls

  • browser.contexts()[0] not browser.newContext() — only the pre-created context honors browserSettings.context, proxies, and fingerprint.
  • Browser.setDownloadBehavior downloadPath is the literal string "downloads" — absolute paths like /tmp/downloads break sync.
  • solveCaptchas defaults to true — disable for compliance/audit runs.
  • recordSession and logSession default to true — disable for privacy-sensitive flows; cannot be re-enabled mid-session.
  • connectUrl is one-shot per CDP connect — reconnecting after disconnect requires keepAlive: true.
  • userMetadata JSON cap is 512 chars, string values only, no arrays — query with q: "user_metadata['env']:'staging'".
  • Stagehand requires BROWSERBASE_PROJECT_ID even though the raw SDK can infer it from the API key.
  • Free-tier concurrency is 3 sessions; rate-limited at the create endpoint even when under max concurrency.
  • verified: true and advancedStealth are Scale-plan only — they 4xx on lower tiers.
  • browserbase proxies have a 1 MB minimum per session then round to nearest MB; restricted-category sites (Apple, finance, streaming, ticketing, some Google) are blocked.
  • Sessions persist beyond script exit unless explicitly released — REQUEST_RELEASE via sessions.update or let timeout expire; keepAlive prolongs further.
  • os and verified together require Scale tier — os: 'windows' | 'mac' | 'linux' | 'mobile' | 'tablet'.
  • Selenium uses seleniumRemoteUrl, not connectUrl — different protocol entirely.