functions

star 0

Deploy serverless browser automation to Browserbase cloud using the bb CLI. Use when the user wants scheduled, webhook-triggered, or cloud-hosted automation.

peytoncasper By peytoncasper schedule Updated 1/27/2026

name: functions description: Deploy serverless browser automation to Browserbase cloud using the bb CLI. Use when the user wants scheduled, webhook-triggered, or cloud-hosted automation.

Browserbase Functions Skill

Deploy serverless browser automation using the official @browserbasehq/sdk-functions CLI.

Note: Browser Functions is currently in open beta. Things may change without notice.

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

Why Browser Functions?

  • Zero Infrastructure - No servers to manage or containers to configure
  • Instant Testing - Local development server for rapid iteration
  • Playwright Native - Use familiar Playwright APIs for browser automation
  • Built-in Session Management - Sessions are automatically created and configured
  • API-First - Invoke functions via simple HTTP requests

Prerequisites

Get Credentials

Get your API key and Project ID from: https://browserbase.com/settings

Setup Check

bash scripts/setup-functions.sh

Getting Started

1. Initialize Your Project

pnpm dlx @browserbasehq/sdk-functions init my-functions-project
cd my-functions-project

This creates:

  • package.json - Project configuration
  • .env - Environment variables template
  • index.ts - Starter function template

2. Configure Environment Variables

Edit .env with your Browserbase credentials:

BROWSERBASE_PROJECT_ID=your_project_id
BROWSERBASE_API_KEY=your_api_key

3. Install Dependencies

pnpm install

Function Structure

The CLI creates a template function in index.ts:

import { defineFn } from "@browserbasehq/sdk-functions";
import { chromium } from "playwright-core";

type HNSubmission = {
  title: string | null;
  url: string | null;
  rank: number;
};

defineFn("my-function", async (context) => {
  const { session } = context;

  console.log("Connecting to browser session:", session.id);

  // Connect to the browser instance
  const browser = await chromium.connectOverCDP(session.connectUrl);
  const browserContext = browser.contexts()[0]!;
  const page = browserContext.pages()[0]!;

  // Navigate to Hacker News
  console.log("Navigating to Hacker News...");
  await page.goto("https://news.ycombinator.com");

  // Wait for the content to load
  await page.waitForSelector(".athing", { timeout: 30000 });

  // Extract the first three submission titles
  const titles = await page.evaluate(() => {
    const results: HNSubmission[] = [];

    document.querySelectorAll(".athing").forEach((submission, idx) => {
      if (idx >= 3) return;

      const titleElement = submission.querySelector(".titleline > a");

      if (titleElement) {
        results.push({
          title: titleElement.textContent ?? null,
          url: titleElement.getAttribute("href"),
          rank: idx + 1,
        });
      }
    });

    return results;
  });

  console.log(`Successfully extracted ${titles.length} titles`);

  // Return the results
  return {
    message: "Successfully fetched top Hacker News stories",
    timestamp: new Date().toISOString(),
    results: titles,
  };
});

Key objects:

  • context.session.id - Session ID
  • context.session.connectUrl - CDP endpoint to connect Playwright
  • context.params - Input parameters from invocation

Development Workflow

Start the Development Server

pnpm bb dev index.ts

The local server starts on http://127.0.0.1:14113 and watches for file changes.

Test Your Function Locally

curl -X POST http://127.0.0.1:14113/v1/functions/my-function/invoke \
  -H "Content-Type: application/json"

This uses your Browserbase credentials to create a session, runs your automation locally, and returns the results.

Tip: Pipe output to jq for readable JSON:

curl -X POST http://127.0.0.1:14113/v1/functions/my-function/invoke \
  -H "Content-Type: application/json" | jq

Publishing

Publish all functions in your project to Browserbase:

pnpm bb publish index.ts

The publish command:

  1. Bundles your local project (respects .gitignore)
  2. Uploads the bundle to Browserbase
  3. Returns build ID and function IDs

Output:

Function published successfully
Build ID: 00000000-0000-0000-0000-000000000000
Function ID: 00000000-0000-0000-0000-000000000000

Your function is available at:
https://api.browserbase.com/v1/functions/00000000-0000-0000-0000-000000000000/invoke

Save the Function ID - you need it to invoke your deployed function.

Invoking Deployed Functions

Start an Invocation

curl --request POST \
  --url https://api.browserbase.com/v1/functions/YOUR_FUNCTION_ID/invoke \
  --header 'Content-Type: application/json' \
  --header 'x-bb-api-key: YOUR_API_KEY' \
  --data '{"params": {}}'

Response:

{"id": "INVOCATION_ID"}

Poll for Completion

Browser Function invocations are async. Poll for completion:

curl --request GET \
  --url https://api.browserbase.com/v1/functions/invocations/YOUR_INVOCATION_ID \
  --header 'Content-Type: application/json' \
  --header 'x-bb-api-key: YOUR_API_KEY'

Response when complete:

{
  "id": "00000000-0000-0000-0000-000000000000",
  "functionId": "00000000-0000-0000-0000-000000000000",
  "sessionId": "00000000-0000-0000-0000-000000000000",
  "status": "COMPLETED",
  "params": {},
  "results": {
    "message": "Successfully fetched top Hacker News stories",
    "results": [
      {"url": "...", "rank": 1, "title": "..."},
      {"url": "...", "rank": 2, "title": "..."},
      {"url": "...", "rank": 3, "title": "..."}
    ],
    "timestamp": "2026-01-01T00:00:00.000Z"
  },
  "createdAt": "...",
  "startedAt": "...",
  "endedAt": "..."
}

Invoke 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, 2000));
    
    const statusRes = await fetch(
      `https://api.browserbase.com/v1/functions/invocations/${invocationId}`,
      { 
        headers: { 
          'Content-Type': 'application/json',
          '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);
  }
}

Multi-File Projects

For larger projects, use imports to include multiple function files:

// index.ts (entrypoint)
import "./scraper.ts";
import "./monitor.ts";

// scraper.ts
import { defineFn } from "@browserbasehq/sdk-functions";
defineFn("scraper", async (context) => { ... });

// monitor.ts  
import { defineFn } from "@browserbasehq/sdk-functions";
defineFn("monitor", async (context) => { ... });

All functions defined in imported files will be discovered and published.

Common Patterns

With Parameters

defineFn("scrape-url", 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 data = await page.$$eval(params.selector, els => 
    els.map(el => el.textContent?.trim())
  );
  
  return { url: params.url, data };
});

Invoke with:

curl -X POST .../invoke \
  -H "Content-Type: application/json" \
  -d '{"params": {"url": "https://example.com", "selector": ".item"}}'

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' 
    };
  }
});

Use Cases

Browser Functions are ideal for:

  • Webhooks - Trigger browser automation from external services
  • Scheduled Tasks - Run periodic scraping or monitoring jobs
  • API Endpoints - Expose browser automation via REST APIs
  • CI/CD Pipelines - Automate testing and validation workflows
  • Data Collection - Extract structured data from websites
  • Form Submissions - Automate repetitive form-filling tasks

CLI Reference

Command Description
pnpm dlx @browserbasehq/sdk-functions init <name> Create new project
pnpm bb dev <entrypoint> Start local dev server
pnpm bb publish <entrypoint> Deploy to Browserbase

Limitations

  • Max execution time: 15 minutes
  • No persistent storage across invocations
  • Custom NPM packages must be bundled (no private NPM registry support)
  • Always invokes the latest version of each function

For long-running or interactive sessions, use standard Browserbase sessions instead of functions.

Troubleshooting

"Missing API key"

# Check .env file exists and has credentials
cat .env

# Or set environment variables
export BROWSERBASE_API_KEY="your_api_key"
export BROWSERBASE_PROJECT_ID="your_project_id"

Dev server won't start

# Make sure dependencies are installed
pnpm install

# Check you're in the project directory (has package.json)
ls package.json

Function times out

  • Max execution time is 15 minutes
  • Add specific timeouts to page operations
  • Use waitForSelector instead of arbitrary delays

Can't connect to browser

  • Ensure you're using chromium.connectOverCDP(session.connectUrl)
  • Don't use chromium.launch() - the session is pre-created

Further Reading

Install via CLI
npx skills add https://github.com/peytoncasper/browserbase-skill-test --skill functions
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator
peytoncasper
peytoncasper Explore all skills →