> ## Documentation Index
> Fetch the complete documentation index at: https://docs.browserbase.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploying a browser session

> Learn how to deploy existing browser automation scripts as Functions

Functions let you deploy your existing browser automation scripts to Browserbase's serverless infrastructure. Instead of running scripts on your own servers, publish them as cloud functions invocable via API.

This guide shows you how to take an existing automation script and deploy it as a Function.

<Warning>
  Functions are currently only available in the **us-west-2** region.
</Warning>

## Prerequisites

Before deploying, ensure you have:

1. An existing TypeScript browser automation script using Stagehand, Playwright, or Puppeteer
2. A Browserbase account with your API key and Project ID (available in [Settings](https://www.browserbase.com/settings))

## Create Function scaffolding

Initialize a new Functions project. This creates the directory structure, installs dependencies, and sets up the required configuration files.

<Steps>
  <Step title="Initialize your project">
    Run the following command to create a new Functions project:

    ```bash theme={null}
    pnpm dlx @browserbasehq/sdk-functions init my-functions-project
    ```

    This creates a `my-functions-project` directory 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
  </Step>

  <Step title="Enter the project directory">
    ```bash theme={null}
    cd my-functions-project
    ```
  </Step>

  <Step title="Configure environment variables">
    Open the `.env` file and add your Browserbase credentials:

    ```bash theme={null}
    BROWSERBASE_PROJECT_ID=your_project_id
    BROWSERBASE_PROJECT_ID=your_project_id
    BROWSERBASE_API_KEY=your_api_key
    ```

    <Info>
      Get your API key and Project ID from the [Browserbase Dashboard Settings](https://www.browserbase.com/settings).
    </Info>
  </Step>
</Steps>

## Adapting your script

The key difference between running locally and deploying as a Function is how you connect to the browser. In a Function, Browserbase automatically creates a session and provides the connection details through the `context` parameter.

### Using the Function context

Every Function receives a `context` object containing session information:

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

  // session.id - The session ID
  // session.connectUrl - CDP connection URL for Playwright/Puppeteer
});
```

## Framework integration

Choose your framework below to see how to adapt your existing script for deployment.

<Tabs>
  <Tab title="Stagehand">
    Stagehand is the recommended SDK for Functions. Use `env: "LOCAL"` mode and pass the CDP connection URL from `context.session.connectUrl` via `localBrowserLaunchOptions`.

    **Local Script:**

    ```typescript theme={null}
    import { Stagehand } from "@browserbasehq/stagehand";

    const stagehand = new Stagehand({
      env: "BROWSERBASE",
    });

    await stagehand.init();
    await stagehand.page.goto("https://example.com");
    // Your automation logic...
    ```

    **Function:**

    ```typescript theme={null}
    import { defineFn } from "@browserbasehq/sdk-functions";
    import { Stagehand } from "@browserbasehq/stagehand";

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

      const stagehand = new Stagehand({
        env: "LOCAL",
        localBrowserLaunchOptions: {
          cdpUrl: session.connectUrl,
        },
      });

      await stagehand.init();
      await stagehand.page.goto("https://example.com");
      // Your automation logic...

      return { success: true };
    });
    ```

    <Info>
      Using `env: "LOCAL"` with `localBrowserLaunchOptions.cdpUrl` connects Stagehand directly to the browser session via CDP. You can still use other Stagehand options alongside this configuration. See the [Stagehand documentation](https://docs.stagehand.dev/v3/references/stagehand) for all available configuration options.
    </Info>
  </Tab>

  <Tab title="Playwright">
    Connect to the browser session using Playwright's CDP connection with the `session.connectUrl`.

    **Local Script:**

    ```typescript theme={null}
    import { chromium } from "playwright-core";
    import { Browserbase } from "@browserbasehq/sdk";

    const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY });
    const session = await bb.sessions.create();

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

    await page.goto("https://example.com");
    // Your automation logic...
    ```

    **Function:**

    ```typescript theme={null}
    import { defineFn } from "@browserbasehq/sdk-functions";
    import { chromium } from "playwright-core";

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

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

      await page.goto("https://example.com");
      // Your automation logic...

      return { success: true };
    });
    ```
  </Tab>

  <Tab title="Puppeteer">
    Connect to the browser session using Puppeteer's WebSocket endpoint with the `session.connectUrl`.

    **Local Script:**

    ```typescript theme={null}
    import puppeteer from "puppeteer-core";
    import { Browserbase } from "@browserbasehq/sdk";

    const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY });
    const session = await bb.sessions.create();

    const browser = await puppeteer.connect({
      browserWSEndpoint: session.connectUrl,
    });

    const page = (await browser.pages())[0]!;
    await page.goto("https://example.com");
    // Your automation logic...
    ```

    **Function:**

    ```typescript theme={null}
    import { defineFn } from "@browserbasehq/sdk-functions";
    import puppeteer from "puppeteer-core";

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

      const browser = await puppeteer.connect({
        browserWSEndpoint: session.connectUrl,
      });

      const page = (await browser.pages())[0]!;
      await page.goto("https://example.com");
      // Your automation logic...

      return { success: true };
    });
    ```
  </Tab>
</Tabs>

## Testing locally

Before deploying, test your Function locally using the development server.

### Start the development server

```bash theme={null}
pnpm bb dev index.ts
```

The server starts on `http://127.0.0.1:14113` and watches for file changes, automatically reloading when you modify your Function files.

### Invoke your Function locally

Use curl to invoke your Function against the local development server:

```bash theme={null}
curl -X POST http://127.0.0.1:14113/v1/functions/my-function/invoke \
  -H "Content-Type: application/json"
```

Replace `my-function` with the name you passed to `defineFn`.

### Pass parameters

If your Function accepts parameters, include them in the request body:

```bash theme={null}
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"}}'
```

<Tip>
  Pipe the output to [jq](https://github.com/jqlang/jq) for formatted JSON:

  ```bash theme={null}
  curl -X POST http://127.0.0.1:14113/v1/functions/my-function/invoke \
    -H "Content-Type: application/json" | jq
  ```
</Tip>

<Info>
  The local development server creates real Browserbase sessions using your credentials. This ensures your Function behaves the same locally and in production.
</Info>

## Deploying to production

Once your Function works locally, deploy it to Browserbase:

```bash theme={null}
pnpm bb publish index.ts
```

You'll receive a Function ID that you can use to invoke your deployed Function:

```bash theme={null}
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": {}}'
```

## Learn more

For detailed information on passing parameters, best practices, and limitations, see the [Functions feature documentation](/platform/runtime/overview).

## Next steps

<CardGroup>
  <Card title="Browserbase Functions" icon="code" iconType="sharp-solid" href="/platform/runtime/overview">
    Learn about defining, publishing, and invoking Functions
  </Card>

  <Card title="Functions Reference" icon="gear" iconType="sharp-solid" href="/platform/runtime/reference">
    Detailed API reference and configuration options
  </Card>

  <Card title="Session configuration" icon="sliders" iconType="sharp-solid" href="/platform/browser/getting-started/create-browser-session">
    Learn about session creation options
  </Card>
</CardGroup>
