Skip to main content
A quick walkthrough for writing, testing, and deploying Functions. For the full feature reference (agent examples, advanced patterns, and limitations), see the Functions overview.

Overview

Functions let you deploy serverless browser automation workflows directly to Browserbase’s infrastructure. Write your automation code locally, test it instantly, and deploy it as a cloud function that can be invoked via API. Key benefits:
  • 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

Quick start

Ready to deploy? Follow the step-by-step guide to deploy your first Function.
Functions are currently only available in the us-west-2 region.

Getting started

The easiest way to get started is using the CLI to scaffold a new project:
pnpm dlx @browserbasehq/sdk-functions init my-functions-project
cd my-functions-project
This creates a ready-to-use project with:
  • A configured package.json with required dependencies
  • A tsconfig.json for TypeScript support
  • A template .env file for your credentials
  • A starter index.ts file with an example function
Add your Browserbase credentials to the .env file:
BROWSERBASE_PROJECT_ID=your_project_id
BROWSERBASE_API_KEY=your_api_key
Get your API key and Project ID from the Browserbase Dashboard Settings.

Defining Functions

Basic Function

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

defineFn("function-name", async (ctx, params) => {
  const browser = await chromium.connectOverCDP(ctx.session.connectUrl);
  const context = browser.contexts()[0];
  const page = context?.pages()[0];

  // Your automation code here

  return { result: "your data" };
});

Function parameters

  • Function Name - Unique identifier for your function (used in the “invoke function” HTTP request)
  • Handler - Async function that receives:
    • ctx - Context object with session information
    • params - Parameters passed when invoking the function
  • Options - Optional configuration object for session settings
Make sure that you give each function in your codebase a unique name! Function names are unique per project. The name parameter serves as a function’s “Logical ID” (a unique, human-friendly identifier), meaning reusing a name string could lead to overwriting an existing built function with the same name.

Context object

The ctx parameter provides access to the browser session:
{
  session: {
    connectUrl: string;  // CDP connection URL
    id: string;          // Session ID
  }
}

Function response

Return any JSON-serializable data from your function:
return {
  success: true,
  data: { ... },
  message: "Operation complete"
};

Session configuration

Configure browser session settings using the third parameter:
defineFn(
  "verified-function",
  async (ctx, params) => {
    // Your function code
  },
  {
    sessionConfig: {
      browserSettings: {
        verified: true,
        solveCaptchas: true,
      },
      proxies: true,
    },
  }
);
Most session creation options are supported in sessionConfig. See the Create Session API Reference for the full list of available options including proxies, Verified, viewports, contexts, and extensions.

Complete example

Here’s a full example that fills out a contact form:
import { defineFn } from "@browserbasehq/sdk-functions";
import { chromium } from "playwright-core";

defineFn(
  "fill-contact-form",
  async (ctx, params) => {
    const browser = await chromium.connectOverCDP(ctx.session.connectUrl);
    const context = browser.contexts()[0];
    const page = context?.pages()[0];

    if (!page) {
      console.error("Failed to create a page");
      return { error: "No page available" };
    }

    try {
      await page.goto("https://www.browserbase.com/contact");

      await page.locator("#firstName").fill("Browser");
      await page.locator("#lastName").fill("Functions");
      await page.locator("#email-label").fill("demo@browserbase.com");
      await page.locator("#jobTitle-label").fill("Professional robot");
      await page.locator("#companyName-label").fill("Browserbase");

      await page.locator("button#helpOption").click();
      await page.locator("#helpOption-demo").click();

      return { success: true, message: "Form filled successfully" };
    } catch (error: unknown) {
      console.error("Error filling form:", error);
      return { error: "Failed to fill form", details: String(error) };
    }
  },
  {
    sessionConfig: {
      browserSettings: { verified: true },
    },
  }
);

Local development

Before publishing, you can test your functions locally using the development server. This creates real Browserbase sessions using your credentials, ensuring your function behaves the same locally and in production.

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, automatically reloading when you modify your function files.

Invoke Functions locally

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

Pass parameters locally

curl -X POST http://127.0.0.1:14113/v1/functions/my-function/invoke \
  -H "Content-Type: application/json" \
  -d '{"params": {"url": "https://example.com", "selector": "#content"}}'
The local development server runs functions synchronously and returns results directly. Production invocations are async and require polling.

Publishing Functions

Single file

pnpm bb publish index.ts

Multiple files

Import other function files into your entrypoint:
index.ts
import "screenshot-fn.ts"
// All defineFn calls in imported files are included in the build
The publish command requires an entrypoint file. All functions must be defined in or imported by that file.

Invoking Functions

Get build result

curl https://api.browserbase.com/v1/functions/builds/BUILD_ID \
  -H "x-bb-api-key: $BB_API_KEY"

Invoke with parameters

curl -X POST https://api.browserbase.com/v1/functions/FUNCTION_ID/invoke \
  -H "Content-Type: application/json" \
  -H "x-bb-api-key: $BB_API_KEY" \
  -d '{"params": {"url": "https://example.com"}}'

Poll for results

Function invocations are async. Poll the invocation endpoint until status is COMPLETED:
curl https://api.browserbase.com/v1/functions/invocations/INVOCATION_ID \
  -H "x-bb-api-key: $BB_API_KEY"

Best practices

  • Wrap automation code in try/catch and return error shapes rather than letting errors propagate unhandled
  • Use console.log/console.error for debugging — logs are captured in invocation logs
  • Sessions close automatically when your function completes; no manual cleanup needed

Monitoring and debugging

Every invocation creates a browser session you can inspect in the Session Inspector:
  • Session replays
  • Console logs
  • Network activity
  • Performance metrics

Limitations

  • Maximum execution time: 15 minutes
  • No persistent storage between invocations
  • TypeScript only (no Python support)
  • Private NPM packages are not supported

Secrets

Secrets management is coming soon — securely store API keys and credentials without passing them as parameters. Email support@browserbase.com to join the waitlist.