The Search API is currently in private beta.
The Browserbase Search API lets you perform web searches programmatically and receive structured results directly — no browser session required. It’s designed for AI agents, research pipelines, and any workflow that needs real-time web search data.
Send a POST request to /v1/search with your query. Authenticate with the same x-bb-api-key header used across the Browserbase API.
import { Browserbase } from "@browserbasehq/sdk";
const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY! });
const response = await bb.search({
query: "browserbase",
numResults: 10,
});
console.log(`Request ID: ${response.requestId}`);
for (const result of response.results) {
console.log(`${result.title} - ${result.url}`);
}
from browserbase import Browserbase
import os
bb = Browserbase(api_key=os.environ["BROWSERBASE_API_KEY"])
response = bb.search(
query="browserbase",
num_results=5,
)
print(f"Request ID: {response.request_id}")
for result in response.results:
print(f"{result.title} - {result.url}")
curl -X POST https://api.browserbase.com/v1/search \
-H "Content-Type: application/json" \
-H "x-bb-api-key: $BROWSERBASE_API_KEY" \
-d '{
"query": "browserbase",
"numResults": 10
}'
Request Parameters
| Parameter | Type | Required | Description |
|---|
query | string | Yes | The search query (1–200 characters) |
numResults | integer | No | Number of results to return (1–25, default: 10) |
Response
| Field | Type | Description |
|---|
requestId | string | Unique identifier for the request |
query | string | The search query that was executed |
results | array | List of search result objects |
Each result object contains:
| Field | Type | Always present | Description |
|---|
id | string | Yes | Unique identifier for the result |
url | string | Yes | URL of the search result |
title | string | Yes | Title of the search result |
author | string | No | Author of the content |
publishedDate | string | No | Publication date (ISO 8601) |
image | string | No | Image URL |
favicon | string | No | Favicon URL |
Combining Search with Browser Sessions
A common pattern is using the Search API to find relevant URLs, then opening them in browser sessions for deeper interaction — scraping content, filling forms, or taking screenshots.
import { Browserbase } from "@browserbasehq/sdk";
import { chromium } from "playwright-core";
const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY! });
const searchResponse = await bb.search({
query: "browserbase documentation",
numResults: 10,
});
for (const result of searchResponse.results) {
const session = await bb.sessions.create();
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0].pages()[0];
await page.goto(result.url);
const content = await page.textContent("body");
console.log(`Content from ${result.title}:`, content?.slice(0, 200));
await page.close();
await browser.close();
}
from browserbase import Browserbase
from playwright.sync_api import sync_playwright
import os
bb = Browserbase(api_key=os.environ["BROWSERBASE_API_KEY"])
search_response = bb.search(
query="browserbase documentation",
num_results=3,
)
with sync_playwright() as playwright:
for result in search_response.results:
session = bb.sessions.create()
browser = playwright.chromium.connect_over_cdp(session.connect_url)
page = browser.contexts[0].pages[0]
page.goto(result.url)
content = page.text_content("body")
print(f"Content from {result.title}:", content[:200] if content else "")
page.close()
browser.close()
Rate Limits
The Search API is rate limited to 120 requests per minute per project. Exceeding this returns a 429 status code.
For high-volume use cases, space out your requests or implement exponential
backoff in your retry logic.
Error Handling
| Status Code | Meaning |
|---|
200 | Success |
400 | Invalid request (empty query, numResults out of range) |
403 | Search API not enabled for your project |
429 | Rate limit exceeded |
503 | Search service temporarily unavailable |
500 | Internal server error |
try {
const response = await fetch("https://api.browserbase.com/v1/search", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-bb-api-key": process.env.BROWSERBASE_API_KEY!,
},
body: JSON.stringify({ query: "browserbase" }),
});
if (!response.ok) {
if (response.status === 429) {
console.log("Rate limited — retrying after delay");
} else if (response.status === 503) {
console.log("Service temporarily unavailable — retrying");
} else {
console.error(`Search failed: ${response.status}`);
}
return;
}
const data = await response.json();
console.log(data.results);
} catch (error) {
console.error("Request failed:", error);
}
import requests
import os
response = requests.post(
"https://api.browserbase.com/v1/search",
headers={
"Content-Type": "application/json",
"x-bb-api-key": os.environ["BROWSERBASE_API_KEY"],
},
json={"query": "browserbase"},
)
if response.status_code == 429:
print("Rate limited — retrying after delay")
elif response.status_code == 503:
print("Service temporarily unavailable — retrying")
elif not response.ok:
print(f"Search failed: {response.status_code}")
else:
data = response.json()
print(data["results"])