About browserbase-sdk
browserbase-sdk is a skill guide to Browserbase’s REST SDK for managing remote browser sessions, contexts, extensions, and projects. It explains how to connect browser automation libraries or Stagehand, while distinguishing session management from browser control.
Key features
- 01Manage sessions through the REST SDK
- 02Connect Playwright or Puppeteer over CDP
- 03Use Selenium with its remote URL
- 04Integrate Stagehand browser primitives
- 05Handle contexts, proxies, and session observability
Use cases
- 01Create and release a remote browser session
- 02Automate a browser with Playwright or Puppeteer
- 03Use Stagehand for AI-driven browser actions
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ thatjuan/ agent-skills --skill browserbase-sdkAfter installing, type/browserbase-sdkin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
README.mdreferences/contexts.mddownloads-uploads.mdextensions.mdobservability.mdplaywright-puppeteer.mdproxies.mdsessions.mdstagehand.mdstealth-and-captcha.mdDetails
From the project READMEBrowserbase 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:
BROWSERBASE_API_KEY— from https://browserbase.com/settingsBROWSERBASE_PROJECT_ID— required by Stagehand; inferred from key by@browserbasehq/sdk
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:
- Introduction: https://docs.browserbase.com/reference/introduction.md
- Node SDK reference: https://docs.browserbase.com/reference/sdk/nodejs.md
- Create session API: https://docs.browserbase.com/reference/api/create-a-session.md
- Full aggregate: https://docs.browserbase.com/llms-full.txt
- Index: https://docs.browserbase.com/llms.txt
- SDK source: https://github.com/browserbase/sdk-node
- Stagehand source: https://github.com/browserbase/stagehand
Common pitfalls
browser.contexts()[0]notbrowser.newContext()— only the pre-created context honorsbrowserSettings.context, proxies, and fingerprint.Browser.setDownloadBehaviordownloadPathis the literal string"downloads"— absolute paths like/tmp/downloadsbreak sync.solveCaptchasdefaults totrue— disable for compliance/audit runs.recordSessionandlogSessiondefault totrue— disable for privacy-sensitive flows; cannot be re-enabled mid-session.connectUrlis one-shot per CDP connect — reconnecting after disconnect requireskeepAlive: true.userMetadataJSON cap is 512 chars, string values only, no arrays — query withq: "user_metadata['env']:'staging'".- Stagehand requires
BROWSERBASE_PROJECT_IDeven 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: trueandadvancedStealthare Scale-plan only — they 4xx on lower tiers.browserbaseproxies 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_RELEASEviasessions.updateor lettimeoutexpire;keepAliveprolongs further. osandverifiedtogether require Scale tier —os: 'windows' | 'mac' | 'linux' | 'mobile' | 'tablet'.- Selenium uses
seleniumRemoteUrl, notconnectUrl— different protocol entirely.