Skip to main content
Browser Functions is currently in open beta! While we don’t intend to make any major changes to the public API, things may still change without notice. If you have any questions or feedback, please reach out to our customer engineering team!

Overview

Browser 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. There are four steps to creating and using Browser Functions:
  1. Set up a functions project in your local environment
  2. Locally develop and verify your functions defined in TypeScript
  3. Publish your functions to Browserbase infrastructure
  4. Invoke your functions via API! 🎉
This document will walk you through the steps to get your first function up and running!

Why Browser Functions?

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
Browser Functions are ideal for webhooks, scheduled tasks, API endpoints, and any automation workflow that benefits from on-demand execution.

Getting Started

Environment Setup

Browser Functions are defined via Infrastructure as Code (IaC)! This means that your functions are defined alongside your automations in TypeScript. This step will walk you through how to set up a functions development environment.
1

Initialize Your Project

Initialize your functions project with the @browserbasehq/sdk-functions NPM package CLI. This will initialize a my-functions-project directory, configure a TypeScript pNPM project, install required packages, create a template .env file, and initialize a starter function in index.ts.
pnpm dlx @browserbasehq/sdk-functions init my-functions-project
Enter the my-functions-project directory created by the CLI:
cd my-functions-project
2

Configure Environment Variables

Populate the .env file with your Browserbase credentials:
BROWSERBASE_PROJECT_ID=your_project_id
BROWSERBASE_API_KEY=your_api_key
Get your API key and Project ID from the Browserbase Dashboard Settings.
3

Create your Function

Now you can create a new Function! The CLI creates a template function "my-function" in index.ts. This function does the following:
  1. Connects to the browser session associated with the function
  2. Navigates to Hacker News
  3. Extracts the top 3 results from the page and returns them
index.ts
import { defineFn } from "@browserbasehq/sdk-functions";
import { chromium } from "playwright-core";

// This is your first Browserbase function!
// You can run it locally with: bb dev index.ts
// Once ready, publish it with: bb publish index.ts

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; // only return 3

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

Start the Development Server

pnpm bb dev index.ts
The local server will start on http://127.0.0.1:14113 and watch for file changes.

Invoke Your Function Locally

Use curl to test your function:
curl -X POST http://127.0.0.1:14113/v1/functions/my-function/invoke \
  -H "Content-Type: application/json"
This will use your Browserbase credentials to create a session, locally run your automation, and return the results from the automation to the cURL request! You can see details on the inner workings of the local development flow in the terminal running the dev server.
The local development server automatically reloads when you modify your function files.
For convenience, you can pipe the cURL output into jq to see a human-readable formatting. The output of a Browser Function is just JSON!

Publishing a Function

To publish all of the functions in your local project to Browserbase’s cloud infrastructure, run the following command. This command does the following:
  1. Bundles your local project while respecting .gitignore. Project root is the directory containing package.json
  2. Uploads this bundle to Browserbase, which builds all functions in the project so that they can be invoked.
  3. Return a build ID and function IDs for each discovered function
pnpm bb publish index.ts
The publish command requires an “entrypoint” parameter. An “entrypoint” file indicates that “all functions in this project are either defined in this file or defined in files directly or indirectly imported into this file”. Multi-file projects in TypeScript use import "other-file.ts" to ensure that defineFn is called in the imported file when the entrpoint file is run.
Your output will look similar to the following:
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
Keep track of your function ID - you’ll need it to invoke your deployed function.

Invoking Functions

Call your deployed function via HTTP POST. Parameters are optional:
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": {}}'
Get your API key and Project ID from the Browserbase Dashboard Settings.
Browser Function invocations are async! While an invocation is running, you can poll for the completion of the invocation using the following cURL request:
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'
Once the invocation completes, fetching the invocation will return the JSON results of the invocation! The response will then look similar to the following:
{
  "id": "00000000-0000-0000-0000-000000000000",
  "projectId": "00000000-0000-0000-0000-000000000000",
  "functionId": "00000000-0000-0000-0000-000000000000",
  "versionId": "00000000-0000-0000-0000-000000000000",
  "sessionId": "00000000-0000-0000-0000-000000000000",
  "status": "COMPLETED",
  "params": {},
  "results": {
    "message": "Successfully fetched top Hacker News stories",
    "results": [
      {
        "url": "https://github.com/anthropics/claude-code/issues/16673",
        "rank": 1,
        "title": "Claude Code CLI Broken"
      },
      {
        "url": "https://www.browserbase.com/",
        "rank": 2,
        "title": "Browserbase launches Browser Functions!"
      },
      {
        "url": "https://www.adammcquilkin.com/",
        "rank": 3,
        "title": "The Best Personal Portfolio Anyone's Ever Seen :)"
      },
    ],
    "timestamp": "2026-01-01T00:00:00.000Z"
  },
  "createdAt": "2026-01-01T00:00:00.000000+00:00",
  "updatedAt": "2026-01-01T00:00:00.000000+00:00",
  "startedAt": "2026-01-01T00:00:00.000000+00:00",
  "endedAt": "2026-01-01T00:00:00.000000+00:00",
  "expiresAt": "2026-01-01T00:00:00.000000+00:00"
}
Congratulations, you’ve now deployed and invoked your first Browser Function! 🎉 You can now go back into your code and repeat the local dev / publish flow until you’re happy with your automation(s). You can define multiple functions in your code! For further reading, see Functions Reference.
For the time being, you will always be invoking the latest version of each function (uniquely identified by name). New versions are created each time you publish a function.

Use Cases

Browser Functions are perfect 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

Notes

  • Functions have a maximum execution time of 15 minutes
  • Invocations automatically create a Browserbase session each time they’re invoked
  • Functions don’t support persistent storage across invocations
  • Custom NPM packages must be bundled with your functions code. We don’t support accessing private NPM packages
For long-running or interactive sessions, consider using standard Browserbase sessions instead of functions.

Next Steps

Functions Reference

Learn more about Functions configuration and best practices