TypeScript SDK
Official TypeScript client for Browserbeam. Full type safety, ESM and CJS builds, zero runtime dependencies.
Installation #
Install the package from npm.
npm install @browserbeam/sdk
yarn add browserbeam
fetch API — no runtime dependencies required.
Quick Start #
Create a session, interact with a page, extract data, and close.
import Browserbeam from "@browserbeam/sdk";
const client = new Browserbeam({ apiKey: "bb_live_..." });
const session = await client.sessions.create({
url: "https://example.com",
});
// Click a link
await session.click({ text: "More information" });
// Extract structured data
const result = await session.extract({
title: "string",
description: "string",
});
console.log(result.extraction);
// Close the session
await session.close();
Configuration #
Pass options when creating the client.
import Browserbeam from "@browserbeam/sdk";
const client = new Browserbeam({
apiKey: "bb_live_...",
baseUrl: "https://api.browserbeam.com",
timeout: 120_000,
});
| Option | Type | Default | Description |
|---|---|---|---|
| apiKey | string |
BROWSERBEAM_API_KEY env |
Your API key. Falls back to the BROWSERBEAM_API_KEY environment variable. |
| baseUrl | string |
https://api.browserbeam.com |
API base URL. Override for self-hosted or staging environments. |
| timeout | number |
120000 |
Request timeout in milliseconds. |
BROWSERBEAM_API_KEY environment variable and omit apiKey from the constructor. This keeps secrets out of your source code.
Creating Sessions #
Call client.sessions.create() to launch a browser and navigate to a URL.
const session = await client.sessions.create({
url: "https://example.com",
viewport: { width: 1280, height: 720 },
locale: "en-US",
timezone: "America/New_York",
proxy: { kind: "residential", country: "us" },
block_resources: ["image", "font"],
auto_dismiss_blockers: true,
cookies: [
{ name: "session", value: "abc123", domain: ".example.com" }
],
timeout: 30000,
idempotency_key: "unique-request-id",
});
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string |
No | Initial URL to navigate to. |
| viewport | { width?, height? } |
No | Browser viewport dimensions in pixels. |
| locale | string |
No | Browser locale, e.g. "en-US". |
| timezone | string |
No | IANA timezone, e.g. "America/New_York". |
| proxy | string | object |
No | Managed proxy { kind: "datacenter"|"residential", country?: "us"|"auto" } or BYO proxy URL. Default: datacenter, auto. |
| block_resources | string[] |
No | Resource types to block: "image", "font", "media", "stylesheet", "script". |
| auto_dismiss_blockers | boolean |
No | Automatically dismiss cookie banners and popups. |
| cookies | object[] |
No | Cookies to set before navigation. Each object needs name, value, and domain. |
| timeout | number |
No | Session timeout in milliseconds. |
| idempotency_key | string |
No | Unique key to prevent duplicate sessions. Sent as the Idempotency-Key header. |
Session Methods #
Every method returns a Promise<SessionEnvelope> with the updated page state, media, extraction data, and any errors.
| Method | Description |
|---|---|
| goto(url) | Navigate to a URL. |
| observe(opts?) | Get page content and interactive elements. Supports mode: "full" for all page sections. |
| click(opts) | Click an element by ref, text, or label. |
| fill(opts) | Fill a value into an input field. |
| fillForm(opts) | Fill multiple form fields at once. |
| extract(schema) | Extract structured data using a JSON schema. |
| screenshot(opts?) | Capture a screenshot. Returns base64 data. |
| scrollCollect(opts?) | Scroll the page and collect content progressively. |
| close() | Close the browser session. |
goto
#
Navigate to a new URL. Pass a string for simple navigation, or an options object for advanced control.
// Simple
await session.goto("https://example.com/page");
// With wait condition
await session.goto({
url: "https://example.com/page",
wait_for: "networkidle",
wait_timeout: 10000,
});
| Parameter | Type | Description |
|---|---|---|
| url | string |
Target URL. |
| wait_for | string |
Wait condition before returning. |
| wait_timeout | number |
Timeout for the wait condition in ms. |
| wait_until | string |
JavaScript expression that must become truthy after navigation. |
observe
#
Get the current page content and interactive elements. Use scope to limit to a CSS container. Switch to HTML format when you need tag/class names. Use mode: "full" to get content from all page sections (nav, aside, footer, etc.) organized by region. The first observe auto-includes a section map showing available page regions.
const result = await session.observe({
scope: "main",
format: "markdown",
include_links: true,
max_text_length: 5000,
});
console.log(result.page?.markdown?.content);
console.log(result.page?.interactive_elements);
// Page map is auto-included on first observe
result.page?.map?.forEach((entry) => {
console.log(`${entry.section}: ${entry.hint}`);
});
// Re-request the map on subsequent calls
await session.observe({ include_page_map: true });
// Get content from all page sections
const full = await session.observe({ mode: "full", max_text_length: 20_000 });
// full.page?.markdown?.content contains:
// ## [nav]
// Home · Docs · Pricing
// ## [main]
// ...article content...
// ## [aside]
// Related posts · ...
| Parameter | Type | Description |
|---|---|---|
| scope | string |
CSS selector to scope observation to a page section. |
| format | string |
Content format: "markdown" (default) or "html". |
| mode | "main" | "full" |
"main" (default) returns main content only. "full" returns all page sections organized by region headers. |
| include_page_map | boolean |
Include a section map with hints. Auto-included on first observe; set true to request again. |
| include_links | boolean |
Include links in the markdown output. |
| max_text_length | number |
Max content length in chars (default: 12000, or 20000 for mode "full"). |
click
#
Click an element. Target by ref (from observe), visible text, or accessible label.
// By element ref (from observe)
await session.click({ ref: "a7" });
// By visible text
await session.click({ text: "Sign In" });
// By accessible label
await session.click({ label: "Submit form" });
| Parameter | Type | Description |
|---|---|---|
| ref | string |
Element reference from observe(). |
| text | string |
Visible text content of the element. |
| label | string |
Accessible label (aria-label, alt text, etc.). |
fill
#
Fill a value into an input field. Target by ref, text, or label.
await session.fill({ value: "user@example.com", ref: "input3" });
await session.fill({ value: "search query", label: "Search" });
| Parameter | Type | Required | Description |
|---|---|---|---|
| value | string |
Yes | The value to fill into the input. |
| ref | string |
No | Element reference from observe(). |
| text | string |
No | Visible text to match the element. |
| label | string |
No | Accessible label of the input field. |
fillForm
#
Fill multiple form fields in a single step. Optionally submit the form after filling.
await session.fillForm({
fields: {
"Email": "user@example.com",
"Password": "s3cret",
},
submit: true,
});
| Parameter | Type | Required | Description |
|---|---|---|---|
| fields | Record<string, string> |
Yes | Map of field labels to values. |
| submit | boolean |
No | Submit the form after filling. Defaults to false. |
extract
#
Extract structured data from the page. Pass a JSON schema describing the shape of the data you want.
// Mix CSS, JS, and AI selectors in a single extraction
const result = await session.extract({
products: [{
_parent: ".product-card",
_limit: 3,
name: "h2 >> text", // CSS selector
price: ".price >> text", // CSS selector
url: "a >> href", // CSS attribute
rating: "ai >> the star rating out of 5", // AI selector
in_stock: "js >> el.querySelector('.stock')?.textContent.includes('In stock')", // JS selector
}],
});
console.log(result.extraction);
// { products: [{ name: "Widget Pro", price: "$29.99", url: "...", rating: "4.5", in_stock: true }] }
Three selector types work together in the same schema:
- CSS —
"h2 >> text","a >> href",".price >> text" - AI —
"ai >> the star rating"— resolves to a CSS selector via AI, cached after first call - JS —
"js >> expression"— runs JavaScript against each matched element
screenshot
#
Capture a screenshot of the current page. The base64-encoded image is returned in the media array.
const result = await session.screenshot({ full_page: true });
const image = result.media[0];
console.log(image.type); // "screenshot"
console.log(image.format); // "png"
// Save to file
import { writeFileSync } from "fs";
writeFileSync("page.png", Buffer.from(image.data, "base64"));
| Parameter | Type | Description |
|---|---|---|
| full_page | boolean |
Capture the full scrollable page instead of just the viewport. |
| format | string |
Image format: "png" or "jpeg". |
| quality | number |
JPEG quality (1–100). Ignored for PNG. |
| selector | string |
CSS selector to capture a specific element. |
scrollCollect
#
Scroll the page and accumulate content. Useful for infinite-scroll pages or long articles.
const result = await session.scrollCollect({
max_scrolls: 10,
wait_ms: 1000,
timeout_ms: 30000,
max_text_length: 50000,
});
| Parameter | Type | Description |
|---|---|---|
| max_scrolls | number |
Maximum number of scroll actions. |
| wait_ms | number |
Wait time between scrolls in milliseconds. |
| timeout_ms | number |
Total timeout for the scroll operation. |
| max_text_length | number |
Maximum characters of accumulated text. |
close
#
Close the browser session and release resources. Always close sessions when you're done.
await session.close();
type
#
Type text character by character. Useful for inputs with autocomplete or client-side filtering. Target by ref, text, or label.
await session.type({ value: "search query", ref: "e5", delay: 50 });
await session.type({ value: "hello", label: "Search" });
select
#
Select a dropdown option by value. Target the select element by ref, text, or label.
await session.select({ value: "us", label: "Country" });
check
#
Toggle a checkbox or radio button. Target by ref, text, or label.
await session.check({ label: "I agree to the terms" });
await session.check({ ref: "cb3", checked: false });
scroll
#
Scroll the page or scroll an element into view. Target by ref, text, or label.
await session.scroll({ to: "bottom" });
await session.scroll({ direction: "down", amount: 500 });
await session.scroll({ text: "Footer section" });
wait
#
Wait for a duration, CSS selector, visible text, or a JavaScript expression to become truthy.
await session.wait({ ms: 2000 });
await session.wait({ selector: ".loaded", timeout: 10000 });
await session.wait({ until: "document.querySelectorAll('.item').length > 5" });
upload
#
Upload files to a file input. Target by ref, text, or label.
await session.upload({ files: ["https://example.com/file.pdf"], ref: "file1" });
await session.upload({ files: ["https://example.com/photo.jpg"], label: "Upload photo" });
pdf
#
Generate a PDF of the page. Supports format, landscape, background, scale, and margin options.
import { writeFileSync } from "fs";
const result = await session.pdf({
format: "A4",
landscape: true,
scale: 0.8,
margin: { top: "1cm", bottom: "1cm" },
});
writeFileSync("page.pdf", Buffer.from(result.media[0].data, "base64"));
executeJs
#
Run JavaScript code in the browser. The result is stored in the extraction under the specified key.
const result = await session.executeJs("return document.title");
console.log(result.extraction?.js_result);
// With options
const r = await session.executeJs({
code: "return document.querySelectorAll('a').length",
result_key: "link_count",
timeout: 5000,
});
TypeScript Types #
All types are exported from the package. Import them directly for full type safety.
import type {
SessionEnvelope,
PageState,
MapEntry,
InteractiveElement,
MediaItem,
StepError,
} from "@browserbeam/sdk";
SessionEnvelope
Returned by every session method. Contains the full state after each action.
interface SessionEnvelope {
session_id: string;
expires_at: string;
request_id: string;
completed: number;
page: PageState | null;
media: MediaItem[];
extraction: Record<string, unknown> | null;
blockers_dismissed: string[];
error: StepError | null;
}
PageState
interface PageState {
url: string;
title: string;
stable: boolean;
markdown?: MarkdownContent | null;
map?: MapEntry[];
interactive_elements: InteractiveElement[];
forms: Form[];
changes?: Changes | null;
scroll?: ScrollState | null;
}
MapEntry
Structural outline of a page landmark region. Auto-included on first observe, or when include_page_map: true.
interface MapEntry {
section: string; // e.g. "nav", "main", "aside", "footer"
selector: string; // CSS selector for the region
hint: string; // First visible text, truncated
}
InteractiveElement
interface InteractiveElement {
ref: string;
tag: string;
role?: string;
label: string;
value?: string;
in?: string;
near?: string;
form?: string;
}
Form
interface Form {
ref: string;
id: string | null;
action: string;
method: string;
fields: string[];
}
MediaItem
interface MediaItem {
type: "screenshot" | "pdf";
format: string;
data: string; // base64-encoded
}
StepError
interface StepError {
step: number;
action: string;
code:
| "element_not_found"
| "navigation_failed"
| "captcha_detected"
| "captcha_unsolvable"
| "access_denied"
| "action_failed"
| "extract_failed"
| "invalid_request";
message: string;
context?: Record<string, unknown>;
}
Session Management #
List, inspect, and destroy sessions through the client.
List sessions
const { sessions, has_more, next_cursor } = await client.sessions.list({
status: "active",
limit: 10,
});
// Paginate
if (has_more) {
const next = await client.sessions.list({ after: next_cursor ?? undefined });
}
| Parameter | Type | Description |
|---|---|---|
| status | "active" | "closed" | "failed" |
Filter by session status. |
| limit | number |
Maximum sessions to return. |
| after | string |
Cursor for pagination. |
Get session info
const info = await client.sessions.get("ses_abc123");
console.log(info.status); // "active" | "closed" | "failed"
console.log(info.started_at); // ISO 8601 timestamp
console.log(info.duration_seconds); // e.g. 42
if (info.status === "failed") {
console.log(info.error_code, info.error_message);
}
Destroy session
await client.sessions.destroy("ses_abc123");
session.close() for graceful shutdown within a workflow.
Error Handling #
The SDK throws typed errors for different failure scenarios. All errors extend BrowserbeamError.
| Error Class | HTTP Status | When |
|---|---|---|
| AuthenticationError | 401 | Invalid or missing API key. |
| InvalidRequestError | 400 | Malformed request or invalid parameters. |
| SessionNotFoundError | 404 | Session does not exist or has expired. |
| RateLimitError | 429 | Too many requests. Check retryAfter for wait time. |
| QuotaExceededError | 429 | Credit quota exhausted for the billing period. |
| EngineUnavailableError | 503 | Browser engine temporarily unavailable. Retry after retryAfter seconds. |
import Browserbeam, {
BrowserbeamError,
RateLimitError,
AuthenticationError,
QuotaExceededError,
} from "@browserbeam/sdk";
const client = new Browserbeam();
try {
const session = await client.sessions.create({ url: "https://example.com" });
const result = await session.extract({ title: "string" });
console.log(result.extraction);
await session.close();
} catch (error) {
if (error instanceof RateLimitError) {
console.log(`Rate limited. Retry after ${error.retryAfter}s`);
} else if (error instanceof AuthenticationError) {
console.log("Check your API key");
} else if (error instanceof QuotaExceededError) {
console.log("Quota exhausted — upgrade your plan");
} else if (error instanceof BrowserbeamError) {
console.log(`API error: ${error.message} (${error.code})`);
} else {
throw error;
}
}
requestId property. Include it when contacting support for faster debugging.
Full Example #
Extract the top stories from Hacker News, search for a topic, and save a screenshot.
import Browserbeam from "@browserbeam/sdk";
import { writeFileSync } from "fs";
async function main() {
const client = new Browserbeam();
// Navigate to Hacker News
const session = await client.sessions.create({
url: "https://news.ycombinator.com/",
auto_dismiss_blockers: true,
});
// Extract top stories from the front page
const result = await session.extract({
stories: [
{
_parent: ".titleline",
title: "a >> text",
url: "a >> href",
},
],
});
console.log(result.extraction);
// Fill the search form and submit
await session.fillForm({
fields: { q: "browser automation" },
submit: true,
});
// Take a screenshot of search results
const screenshot = await session.screenshot({ full_page: true });
if (screenshot.media.length > 0) {
const img = screenshot.media[0];
writeFileSync("hn-search.png", Buffer.from(img.data, "base64"));
}
// Clean up
await session.close();
}
main().catch(console.error);
Resources #
- GitHub Repository — Source code, issues, and contributions.
- npm Package — Install and version history.
- API Reference — Full REST API documentation.
- All Integrations — Python, Ruby, and MCP server guides.