API Reference
Give LLMs and agents a real browser they can see and control.
https://api.browserbeam.com
Authorization: Bearer sk_live_...
Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /v1/sessions | Create a browser session |
| GET | /v1/sessions/:id | Get session info |
| POST | /v1/sessions/:id/act | Execute steps on a session |
| DELETE | /v1/sessions/:id | Destroy a session |
| GET | /v1/sessions | List active sessions |
Key concepts
Session — an isolated browser tab with its own cookies, storage, and viewport. Billed by runtime (seconds between create and destroy).
Steps — sequential browser actions (click, fill, extract, etc.) sent as a JSON array. On failure, execution stops and the error is returned alongside current page state.
Refs — stable element identifiers (e1, e2, …) assigned during observation. Use refs to target elements in follow-up steps.
Auto-observe — every successful call returns fresh page state automatically: content, interactive elements with refs, scroll position, and a diff of what changed.
Quick Start
Create a session, navigate to a page, and get its content — all in one call:
{
"url": "https://example.com"
}
{
"session_id": "ses_abc123",
"expires_at": "2026-03-18T14:05:00Z",
"completed": 1,
"page": {
"url": "https://example.com",
"title": "Example Domain",
"stable": true,
"markdown": {
"content": "# Example Domain\n\nThis domain is for use in illustrative examples..."
},
"interactive_elements": [
{
"ref": "e1",
"tag": "a",
"role": "link",
"label": "More information..."
}
],
"forms": [],
"changes": null,
"scroll": {
"y": 0,
"height": 600,
"viewport": 720,
"percent": 100
}
},
"screenshots": [],
"blockers_dismissed": ["cookie_consent"],
"error": null
}
Use the element refs to interact with the page:
{
"steps": [
{"click": {"ref": "e1"}}
]
}
{
"completed": 1,
"page": {
"url": "https://www.iana.org/help/example-domains",
"title": "IANA — Example Domains",
"stable": true,
"markdown": {
"content": "# IANA — Example Domains\n\n..."
},
"interactive_elements": [
{"ref": "e1", "tag": "a", "role": "link", "label": "Home"},
{"ref": "e2", "tag": "a", "role": "link", "label": "Domains"}
],
"changes": {
"content_changed": true,
"elements_added": [{"ref": "e1"}, {"ref": "e2"}],
"elements_removed": []
}
},
"screenshots": [],
"blockers_dismissed": [],
"error": null
}
Destroy the session when done:
# No request body
# Empty response
Authentication
Every request requires an API key in the Authorization header:
Authorization: Bearer sk_live_your_api_key
Get your API key from the dashboard. Keys are prefixed sk_live_ for production and sk_test_ for sandbox.
Missing or invalid keys return 401:
{
"error": {
"code": "unauthorized",
"message": "Invalid API key"
}
}
POST /v1/sessions
Create a browser session. Optionally navigate to a URL and execute steps in the same call.
Parameters (all optional)
| Param | Type | Default | Description |
|---|---|---|---|
| url | string | — | Navigate to this URL after creation |
| steps | array | — | Steps to execute after navigation |
| timeout | integer | 300 | Session lifetime in seconds (10–1800) |
| viewport | object | {1280, 720} | {width, height} |
| user_agent | string | — | Custom User-Agent string |
| locale | string | — | Browser locale (e.g. en-US) |
| timezone | string | — | Timezone (e.g. America/New_York) |
| proxy | string | — | Proxy URL (e.g. http://user:pass@proxy:8080) |
| block_resources | array | — | image, font, media, stylesheet, script |
| auto_dismiss_blockers | boolean | true | Auto-dismiss cookie banners and popups |
Behavior
| url | steps | Result |
|---|---|---|
| — | — | Bare session, no page loaded |
| set | — | Navigate → auto-observe → page state returned |
| set | set | Navigate → run steps → auto-observe |
| — | set | Run steps (first should be goto) |
Example — navigate to a page
{
"url": "https://example.com"
}
{
"session_id": "ses_abc123",
"expires_at": "2026-03-18T14:05:00Z",
"completed": 1,
"page": {
"url": "https://example.com",
"title": "Example Domain",
"stable": true,
"markdown": {
"content": "# Example Domain\n\nThis domain is for use in illustrative examples..."
},
"interactive_elements": [
{
"ref": "e1",
"tag": "a",
"role": "link",
"label": "More information..."
}
],
"forms": [],
"changes": null,
"scroll": {
"y": 0,
"height": 600,
"viewport": 720,
"percent": 100
}
},
"screenshots": [],
"blockers_dismissed": ["cookie_consent"],
"error": null
}
Example — navigate + steps in one call
{
"url": "https://example.com/login",
"steps": [
{
"fill_form": {
"fields": {
"Email": "[email protected]",
"Password": "secret"
},
"submit": true
}
},
{"screenshot": {}},
{"close": {}}
]
}
{
"session_id": "ses_def456",
"expires_at": "2026-03-18T14:05:00Z",
"completed": 3,
"page": {
"url": "https://example.com/dashboard",
"title": "Dashboard",
"stable": true,
"markdown": {
"content": "# Welcome back\n\nYou have 3 new notifications..."
},
"interactive_elements": [
{"ref": "e1", "tag": "a", "role": "link", "label": "Notifications"},
{"ref": "e2", "tag": "button", "label": "Logout"}
],
"changes": {
"content_changed": true,
"elements_added": [{"ref": "e1"}, {"ref": "e2"}],
"elements_removed": []
},
"scroll": {
"y": 0,
"height": 1200,
"viewport": 720,
"percent": 60
}
},
"screenshots": [
{
"format": "png",
"data": ""
}
],
"blockers_dismissed": [],
"error": null
}
Example — session with custom options
{
"url": "https://example.com",
"timeout": 600,
"viewport": {
"width": 1920,
"height": 1080
},
"locale": "en-US",
"timezone": "America/New_York",
"block_resources": ["image", "font"],
"auto_dismiss_blockers": true
}
GET /v1/sessions/:id
Get session status and metadata from the database.
# No request body
{
"session_id": "ses_abc123",
"status": "active",
"started_at": "2026-03-18T13:55:00Z",
"ended_at": null,
"duration_seconds": null,
"worker": "81.17.98.100:3001"
}
Response fields
| Field | Type | Description |
|---|---|---|
| session_id | string | Session identifier |
| status | string | active or ended |
| started_at | string | ISO 8601 creation timestamp |
| ended_at | string|null | ISO 8601 end timestamp, or null if active |
| duration_seconds | integer|null | Total runtime in seconds, or null if active |
| worker | string | Engine worker host:port |
POST /v1/sessions/:id/act
Execute steps on an existing session. Steps run sequentially. On failure, execution stops and the error is returned alongside current page state. Auto-observe runs at the end.
{
"steps": [
{
"fill": {
"ref": "e1",
"value": "search query"
}
},
{"click": {"ref": "e3"}},
{"screenshot": {}}
]
}
{
"completed": 3,
"page": {
"url": "https://example.com/results?q=search+query",
"title": "Search Results",
"stable": true,
"markdown": {
"content": "# Search Results\n\n## 1. First result..."
},
"interactive_elements": [
{
"ref": "e1",
"tag": "input",
"role": "search",
"label": "Search",
"value": "search query"
},
{"ref": "e2", "tag": "a", "role": "link", "label": "First result"},
{"ref": "e3", "tag": "a", "role": "link", "label": "Second result"}
],
"forms": [],
"changes": {
"content_changed": true,
"elements_added": [{"ref": "e2"}, {"ref": "e3"}],
"elements_removed": []
},
"scroll": {
"y": 0,
"height": 3000,
"viewport": 720,
"percent": 24
}
},
"screenshots": [
{
"format": "png",
"data": ""
}
],
"blockers_dismissed": [],
"error": null
}
DELETE /v1/sessions/:id
Destroy a session and release browser resources. Runtime is recorded for billing.
# No request body
# Empty response — session destroyed
Always destroy sessions when done. This frees resources and stops the billing clock. Sessions also auto-expire based on their timeout.
GET /v1/sessions
List all your active sessions.
# No request body
{
"sessions": [
{
"session_id": "ses_abc123",
"status": "active",
"started_at": "2026-03-18T13:55:00Z",
"worker": "81.17.98.100:3001"
},
{
"session_id": "ses_def456",
"status": "active",
"started_at": "2026-03-18T14:00:00Z",
"worker": "81.17.98.100:3002"
}
]
}
Step Types
Each step is a JSON object with one key (the step type) and its params as the value. Send steps in the steps array of a create or act call.
Steps execute sequentially. On failure, execution stops and the error is returned. An auto-observe runs at the end of every call.
goto
Navigate to a URL. Waits for page load and stability checks.
| Param | Type | Required | Default | Description |
|---|---|---|---|---|
| url | string | yes | — | URL to navigate to |
| wait_for | string | no | — | CSS selector to wait for |
| wait_timeout | integer | no | 10000 | Max ms to wait for selector |
{"goto": {"url": "https://example.com"}}
{"goto": {"url": "https://example.com", "wait_for": "#main-content", "wait_timeout": 15000}}
On failure (DNS error, timeout, SSL), returns error code navigation_failed.
observe
Force a page observation. Auto-observe runs at the end of every call, so explicit observe is only needed to change format or scope mid-pipeline.
| Param | Type | Default | Description |
|---|---|---|---|
| format | string | markdown | markdown or html |
| scope | string | — | CSS selector to limit observation |
| include_links | boolean | false | Include links as interactive elements |
| max_text_length | integer | 12000 | Content length limit |
{"observe": {}}
{"observe": {"format": "html"}}
{"observe": {"scope": "#content", "include_links": true}}
click
Click an element. Exactly one targeting param required (see Element Targeting).
{"click": {"ref": "e3"}}
{"click": {"text": "Submit"}}
{"click": {"label": "Sign in"}}
fill
Clear and replace the value of an input. For character-by-character typing, use type instead.
{"fill": {"ref": "e1", "value": "hello world"}}
{"fill": {"label": "Email", "value": "[email protected]"}}
type
Type character-by-character with a delay. Use for autocomplete and search-as-you-type inputs.
| Param | Type | Default | Description |
|---|---|---|---|
| value | string | — | Required — text to type |
| delay | integer | 50 | Milliseconds between keystrokes |
{
"type": {
"label": "Search",
"value": "browserbeam api",
"delay": 100
}
}
select
Select an option from a <select> dropdown.
{"select": {"label": "Country", "value": "US"}}
{"select": {"ref": "e4", "value": "option_value"}}
check
Check or uncheck a checkbox/radio button.
{"check": {"label": "Remember me"}}
{"check": {"label": "Terms", "checked": false}}
scroll
Scroll the page or scroll an element into view.
| Param | Type | Default | Description |
|---|---|---|---|
| to | string | — | bottom or top |
| direction | string | — | up or down |
| amount | integer | 500 | Pixels per scroll step |
| times | integer | 1 | Repeat scroll N times |
{"scroll": {"to": "bottom"}}
{"scroll": {"direction": "down", "amount": 500, "times": 3}}
{"scroll": {"ref": "e6"}}
scroll_collect
Scroll through the entire page, wait for lazy-loaded content at each position, and return a unified observation. Ideal for infinite scroll and long pages.
| Param | Type | Default | Description |
|---|---|---|---|
| max_scrolls | integer | 50 | Safety limit on scroll iterations |
| wait_ms | integer | 500 | Pause between scrolls (ms) |
| timeout_ms | integer | 60000 | Total time budget (ms) |
| max_text_length | integer | 100000 | Content length limit |
{"scroll_collect": {}}
{"scroll_collect": {"max_scrolls": 30, "max_text_length": 50000}}
screenshot
Capture a screenshot. Base64 data appears in the screenshots array of the response.
| Param | Type | Default | Description |
|---|---|---|---|
| full_page | boolean | false | Full scrollable page |
| selector | string | — | CSS selector to screenshot a specific element |
| format | string | png | png or jpeg |
| quality | integer | 80 | JPEG quality (1–100) |
{"screenshot": {}}
{"screenshot": {"full_page": true, "format": "jpeg", "quality": 80}}
{"screenshot": {"selector": "#chart"}}
wait
Wait for a condition. Exactly one of ms, selector, or text is required.
{"wait": {"ms": 2000}}
{"wait": {"selector": "#results", "timeout": 10000}}
{"wait": {"text": "Loading complete", "timeout": 5000}}
extract
Structured data extraction. Keys are your field names, values are CSS/XPath selectors. Results appear in the extraction object of the response.
Selector syntax
// Pattern: "selector >> function"
// Functions: text, href (any attr), json, or omit for raw HTML
"title": "h1 >> text"
"link": "a.main >> href"
"image": "img.hero >> src"
"meta": "meta[name=description] >> content"
"html_block": "div.content"
Arrays
// Wrap in [ ] to collect all matches
"all_links": ["a >> href"]
"headings": ["h2 >> text"]
Repeating structures
// Use [{_parent}] for repeating items like product cards
"products": [
{
"_parent": ".product-card",
"name": "h2 >> text",
"price": ".price >> text",
"url": "a >> href"
}
]
Tables
// Tables are auto-parsed into arrays using headers as keys
"people": "table.contacts"
// → [{"Name": "Alice", "Email": "[email protected]"}, ...]
JavaScript expressions
// Use js >> prefix to run JavaScript in the browser
"count": "js >> document.querySelectorAll('.item').length"
"title": "js >> document.querySelector('h1').textContent.trim()"
Full example
{
"url": "https://example.com/products",
"steps": [
{
"extract": {
"page_title": "h1 >> text",
"description": "meta[name=description] >> content",
"nav_links": ["nav a >> text"],
"articles": [
{
"_parent": ".article-card",
"title": "h2 >> text",
"url": "a >> href",
"author": ".byline >> text"
}
],
"stats_table": "table.statistics"
}
},
{"close": {}}
]
}
{
"session_id": "ses_xyz789",
"completed": 2,
"page": { "..." : "..." },
"extraction": {
"page_title": "Our Products",
"description": "Browse our full catalog",
"nav_links": ["Home", "Products", "About", "Contact"],
"articles": [
{
"title": "Widget Pro",
"url": "https://example.com/widget-pro",
"author": "Jane"
},
{
"title": "Gadget X",
"url": "https://example.com/gadget-x",
"author": "John"
}
],
"stats_table": [
{"Product": "Widget Pro", "Sales": "1,234", "Rating": "4.8"},
{"Product": "Gadget X", "Sales": "567", "Rating": "4.5"}
]
},
"screenshots": [],
"error": null
}
fill_form
Fill multiple form fields by label and optionally submit. Auto-detects field types (text, select, checkbox).
| Param | Type | Required | Default | Description |
|---|---|---|---|---|
| fields | object | yes | — | {label: value} pairs |
| submit | boolean | no | false | Auto-click submit button |
{
"fill_form": {
"fields": {
"Email": "[email protected]",
"Password": "secret",
"Country": "US",
"Remember me": true
},
"submit": true
}
}
upload
Upload files to a file input. Downloads from provided URLs and attaches them.
{
"upload": {
"ref": "e5",
"files": ["https://example.com/doc.pdf"]
}
}
{
"upload": {
"label": "Resume",
"files": ["https://example.com/resume.pdf"]
}
}
pdf
Generate a PDF of the current page. Base64 data in screenshots array with format: "pdf".
| Param | Type | Default | Description |
|---|---|---|---|
| format | string | A4 | Paper size (A4, Letter, Legal) |
| landscape | boolean | false | Landscape orientation |
| print_background | boolean | true | Include backgrounds |
| scale | number | 1 | Scale factor (0.1–2) |
| margin | object | — | {top, right, bottom, left} in CSS units |
{"pdf": {}}
{
"pdf": {
"format": "A4",
"landscape": true,
"margin": {
"top": "1cm",
"bottom": "1cm"
}
}
}
close
Destroy the session at the end of step execution. Must be the last step. Useful for fire-and-forget workflows.
{"close": {}}
Element Targeting
Steps that interact with elements (click, fill, type, select, check, scroll, upload) accept exactly one targeting param:
| Key | Example | Best for |
|---|---|---|
| ref | "ref": "e3" | Known elements from prior observe — most precise |
| text | "text": "Submit" | Buttons and links by visible text |
| label | "label": "Email" | Input fields by label/placeholder/aria-label |
Label matching checks (in order): aria-label, placeholder, associated <label>, name attribute, nearby text.
Response Format
Create and act calls return the same response structure. Create also includes session_id and expires_at.
| Field | Type | Description |
|---|---|---|
| session_id | string | Session ID (create only) |
| expires_at | string | ISO 8601 expiry (create only) |
| completed | integer | Number of steps successfully executed |
| page | object|null | Current page state (see below) |
| page.url | string | Current URL |
| page.title | string | Page title |
| page.stable | boolean | Page passed stability checks |
| page.markdown | object | {content, length?} — page content |
| page.interactive_elements | array | Elements with assigned refs |
| page.forms | array | Detected form structures |
| page.changes | object|null | Diff from previous observe. null on first. |
| page.scroll | object | {y, height, viewport, percent} |
| screenshots | array | {format, data} objects (base64) |
| extraction | object | Present when extract steps are used |
| blockers_dismissed | array | Auto-dismissed blockers (e.g. cookie_consent) |
| error | object|null | null on success. On failure: error details. |
Errors
All errors follow a consistent JSON format. On step failure, the response includes both the error and the current page state so you can decide what to do next:
{
"completed": 1,
"page": {
"url": "https://example.com",
"title": "Example Domain",
"interactive_elements": ["..."]
},
"screenshots": [],
"error": {
"step": 1,
"action": "click",
"code": "element_not_found",
"message": "No visible element found matching text \"Submit\"",
"context": {}
}
}
HTTP errors
| Status | Code | When |
|---|---|---|
| 401 | unauthorized | Missing or invalid API key |
| 403 | quota_exceeded | Runtime quota exhausted |
| 404 | session_not_found | Session doesn't exist or expired |
| 429 | rate_limited | Too many requests |
| 503 | engine_unavailable | Browser engine temporarily down |
HTTP error examples
{
"error": {
"code": "quota_exceeded",
"message": "Runtime quota exceeded. Upgrade your plan or wait for the next billing cycle."
}
}
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded. Retry after a moment."
}
}
Step error codes
| Code | Description |
|---|---|
| element_not_found | No visible element matches the target |
| navigation_failed | Goto failed (timeout, DNS, SSL, etc.) |
| captcha_detected | CAPTCHA detected on page |
| action_failed | Element detached, intercepted, etc. |
| extract_failed | Extraction step failed |
| invalid_request | Unknown step type or invalid params |
Rate Limits & Quotas
Limits depend on your plan. Runtime is metered by session duration — the seconds between create and destroy.
| Plan | Runtime / mo | Concurrent | Max Session | Rate Limit |
|---|---|---|---|---|
| Trial | 1 hour | 1 | 5 min | 60 req/min |
| Starter | 100 hours | 25 | 15 min | 600 req/min |
| Pro | 500 hours | 100 | 30 min | 1,200 req/min |
| Scale | 1,500 hours | 200 | 60 min | 3,000 req/min |
Workflows
Common patterns showing how to combine sessions and steps.
Explore then act — 2 calls
Get page state first, then use element refs to interact.
{
"url": "https://example.com"
}
{
"steps": [
{"fill": {"ref": "e1", "value": "search query"}},
{"click": {"ref": "e3"}}
]
}
Login + screenshot — 1 call
Fill a login form, take a screenshot, destroy the session — all at once.
{
"url": "https://example.com/login",
"steps": [
{
"fill_form": {
"fields": {
"Email": "[email protected]",
"Password": "pass"
},
"submit": true
}
},
{"wait": {"ms": 2000}},
{"screenshot": {"full_page": true}},
{"close": {}}
]
}
Full-page scrape — 1 call
Scroll through the entire page, collecting all lazy-loaded content.
{
"url": "https://example.com/long-article",
"steps": [
{"scroll_collect": {"max_text_length": 50000}}
]
}
Structured extraction — 1 call
Extract structured data and close the session in one request.
{
"url": "https://example.com/products",
"steps": [
{
"extract": {
"products": [
{
"_parent": ".product",
"name": "h2 >> text",
"price": ".price >> text",
"url": "a >> href"
}
]
}
},
{"close": {}}
]
}
PDF generation — 1 call
Generate a PDF and close the session.
{
"url": "https://example.com/report",
"steps": [
{
"pdf": {
"format": "A4",
"landscape": true
}
},
{"close": {}}
]
}
Search + extract — 2 calls
Navigate, perform a search, then extract results.
{
"url": "https://example.com",
"steps": [
{"fill": {"label": "Search", "value": "browser automation"}},
{"click": {"text": "Search"}}
]
}
{
"steps": [
{
"extract": {
"results": [
{
"_parent": ".result",
"title": "h3 >> text",
"url": "a >> href"
}
]
}
},
{"close": {}}
]
}