The Browserbase Search API gives your agents fast, token-efficient web search results as a complement to browser sessions. Use it for recon, lead discovery, or RAG pipelines — then hand off to a browser session for interaction.
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 . web ({
query: "browserbase" ,
numResults: 10 , // up to 25 results
});
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.web(
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 querystring Yes The search query (1–200 characters) numResultsinteger No Number of results to return (1–25, default: 10)
Response
Field Type Description requestIdstring Unique identifier for the request querystring The search query that was executed resultsarray List of search result objects
Each result object contains:
Field Type Always present Description idstring Yes Unique identifier for the result urlstring Yes URL of the search result titlestring Yes Title of the search result authorstring No Author of the content publishedDatestring No Publication date (ISO 8601) imagestring No Image URL faviconstring 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 — extracting 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 . web ({
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.web(
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 200Success 400Invalid request (empty query, numResults out of range) 403Search API not enabled for your project 429Rate limit exceeded 503Search service temporarily unavailable 500Internal server error
import { Browserbase } from "@browserbasehq/sdk" ;
const bb = new Browserbase ({ apiKey: process . env . BROWSERBASE_API_KEY ! });
try {
const response = await bb . search . web ({ query: "browserbase" });
console . log ( response . results );
} catch ( error ) {
if ( error . status === 429 ) {
console . log ( "Rate limited — retrying after delay" );
} else if ( error . status === 503 ) {
console . log ( "Service temporarily unavailable — retrying" );
} else {
console . error ( "Search failed:" , error );
}
}
from browserbase import Browserbase
import os
bb = Browserbase( api_key = os.environ[ "BROWSERBASE_API_KEY" ])
try :
response = bb.search.web( query = "browserbase" )
print (response.results)
except Exception as error:
print ( f "Search failed: { error } " )
When to use Search
Use Search when your browser agent doesn’t yet know where the information lives. In other words, it will give you the best starting points on the web for some task.
Think about Search -> Fetch -> Browsers
Search: Find relevant sources (website, news, docs).
Fetch: Quickly extract content from most pages, and filter out low-value results.
Browsers: Log in to portals with agent identity , navigate complex pages, and extract the hard-to-reach data.
Need more help deciding which API? Read our full guide breaking down which API to use with examples.