865★by pkiv
browserbase-functions – OpenClaw Skill
browserbase-functions is an OpenClaw Skills integration for coding workflows. Guide Claude through deploying serverless browser automation using the official bb CLI
Skill Snapshot
| name | browserbase-functions |
| description | Guide Claude through deploying serverless browser automation using the official bb CLI OpenClaw Skills integration. |
| owner | pkiv |
| repository | pkiv/browsepath: skills/functions |
| language | Markdown |
| license | MIT |
| topics | |
| security | L1 |
| install | openclaw add @pkiv/browse:skills/functions |
| last updated | Feb 7, 2026 |
Maintainer

name: browserbase-functions description: Guide Claude through deploying serverless browser automation using the official bb CLI
Browserbase Functions Skill
Guide Claude through deploying serverless browser automation using the official bb CLI.
When to Use
Use this skill when:
- User wants to deploy automation to run on a schedule
- User needs a webhook endpoint for browser automation
- User wants to run automation in the cloud (not locally)
- User asks about Browserbase Functions
Prerequisites
1. Get Credentials
Get API key and Project ID from: https://browserbase.com/settings
2. Set Environment Variables
Either store for reuse:
stagehand fn auth login
# Enter API key and Project ID when prompted
Then export for the current session:
eval "$(stagehand fn auth export)"
Or set directly:
export BROWSERBASE_API_KEY="your_api_key"
export BROWSERBASE_PROJECT_ID="your_project_id"
Creating a Function Project
1. Initialize with Official CLI
pnpm dlx @browserbasehq/sdk-functions init my-function
cd my-function
This creates:
my-function/
├── package.json
├── index.ts # Your function code
└── .env # Add credentials here
2. Add Credentials to .env
# Copy from stored credentials
echo "BROWSERBASE_API_KEY=$BROWSERBASE_API_KEY" >> .env
echo "BROWSERBASE_PROJECT_ID=$BROWSERBASE_PROJECT_ID" >> .env
Or manually edit .env:
BROWSERBASE_API_KEY=your_api_key
BROWSERBASE_PROJECT_ID=your_project_id
3. Install Dependencies
pnpm install
Function Structure
import { defineFn } from "@browserbasehq/sdk-functions";
import { chromium } from "playwright-core";
defineFn("my-function", async (context) => {
const { session, params } = context;
// Connect to browser
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
// Your automation
await page.goto(params.url || "https://example.com");
const title = await page.title();
// Return JSON-serializable result
return { success: true, title };
});
Key objects:
context.session.connectUrl- CDP endpoint to connect Playwrightcontext.params- Input parameters from invocation
Development Workflow
1. Start Dev Server
pnpm bb dev index.ts
Server runs at http://127.0.0.1:14113
2. Test Locally
curl -X POST http://127.0.0.1:14113/v1/functions/my-function/invoke \
-H "Content-Type: application/json" \
-d '{"params": {"url": "https://news.ycombinator.com"}}'
3. Iterate
The dev server auto-reloads on file changes. Use console.log() for debugging - output appears in the terminal.
Deploying
Publish to Browserbase
pnpm bb publish index.ts
Output:
Function published successfully
Build ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Function ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Save the Function ID - you need it to invoke.
Invoking Deployed Functions
Via curl
# Start invocation
curl -X POST "https://api.browserbase.com/v1/functions/FUNCTION_ID/invoke" \
-H "Content-Type: application/json" \
-H "x-bb-api-key: $BROWSERBASE_API_KEY" \
-d '{"params": {"url": "https://example.com"}}'
# Response: {"id": "INVOCATION_ID"}
# Poll for result
curl "https://api.browserbase.com/v1/functions/invocations/INVOCATION_ID" \
-H "x-bb-api-key: $BROWSERBASE_API_KEY"
Via Code
async function invokeFunction(functionId: string, params: object) {
// Start invocation
const invokeRes = await fetch(
`https://api.browserbase.com/v1/functions/${functionId}/invoke`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-bb-api-key': process.env.BROWSERBASE_API_KEY!,
},
body: JSON.stringify({ params }),
}
);
const { id: invocationId } = await invokeRes.json();
// Poll until complete
while (true) {
await new Promise(r => setTimeout(r, 5000));
const statusRes = await fetch(
`https://api.browserbase.com/v1/functions/invocations/${invocationId}`,
{ headers: { 'x-bb-api-key': process.env.BROWSERBASE_API_KEY! } }
);
const result = await statusRes.json();
if (result.status === 'COMPLETED') return result.results;
if (result.status === 'FAILED') throw new Error(result.error);
}
}
Common Patterns
Parameterized Scraping
defineFn("scrape", async ({ session, params }) => {
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
await page.goto(params.url);
await page.waitForSelector(params.selector);
const items = await page.$$eval(params.selector, els =>
els.map(el => el.textContent?.trim())
);
return { url: params.url, items };
});
With Authentication
defineFn("authenticated-action", async ({ session, params }) => {
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
// Login
await page.goto("https://example.com/login");
await page.fill('[name="email"]', params.email);
await page.fill('[name="password"]', params.password);
await page.click('button[type="submit"]');
await page.waitForURL('**/dashboard');
// Do authenticated work
const data = await page.textContent('.user-data');
return { data };
});
Error Handling
defineFn("safe-scrape", async ({ session, params }) => {
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
try {
await page.goto(params.url, { timeout: 30000 });
await page.waitForSelector(params.selector, { timeout: 10000 });
const data = await page.textContent(params.selector);
return { success: true, data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
});
CLI Reference
| Command | Description |
|---|---|
pnpm dlx @browserbasehq/sdk-functions init <name> | Create new project |
pnpm bb dev <file> | Start local dev server |
pnpm bb publish <file> | Deploy to Browserbase |
Troubleshooting
"Missing API key"
# Check credentials
stagehand fn auth status
# Set for current shell
eval "$(stagehand fn auth export)"
# Or add to .env in project directory
Dev server won't start
# Make sure SDK is installed
pnpm add @browserbasehq/sdk-functions
# Or use npx
npx @browserbasehq/sdk-functions dev index.ts
Function times out
- Max execution time is 15 minutes
- Add specific timeouts to page operations
- Use
waitForSelectorinstead of sleep
Can't connect to browser
- Check
session.connectUrlis being used correctly - Ensure you're using
chromium.connectOverCDP()notchromium.launch()
No README available.
Permissions & Security
Security level L1: Low-risk skills with minimal permissions. Review inputs and outputs before running in production.
Requirements
### 1. Get Credentials Get API key and Project ID from: https://browserbase.com/settings ### 2. Set Environment Variables Either store for reuse: ```bash stagehand fn auth login
FAQ
How do I install browserbase-functions?
Run openclaw add @pkiv/browse:skills/functions in your terminal. This installs browserbase-functions into your OpenClaw Skills catalog.
Does this skill run locally or in the cloud?
OpenClaw Skills execute locally by default. Review the SKILL.md and permissions before running any skill.
Where can I verify the source code?
The source repository is available at https://github.com/openclaw/skills/tree/main/skills/pkiv/browse. Review commits and README documentation before installing.
