> ## 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.

# Deploy a Function

> Publish a Browserbase Function from the CLI or the Playground.

You can publish a Function from a local TypeScript project or from the Browserbase Playground. Both paths create a Function version that you invoke through the API.

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

## Deploy from the CLI

Use the CLI when you want version control, custom dependencies, or local editor tooling. If you don't have a local project yet, follow the [Functions quickstart](/platform/functions/quickstart).

<Steps>
  <Step title="Define the Function in your entrypoint">
    ```typescript Node.js theme={null}
    // index.ts
    import { defineFn } from "@browserbasehq/sdk-functions";
    import { chromium } from "playwright-core";

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

      await page.goto(params.url);

      return { title: await page.title() };
    });
    ```
  </Step>

  <Step title="Publish the entrypoint">
    ```bash theme={null}
    pnpm bb publish index.ts
    ```

    The command builds the Function and prints its Function ID. Save that ID for [invoke](/platform/functions/invoke).
  </Step>
</Steps>

<Warning>
  Functions don't support pnpm workspaces. Keep `pnpm-lock.yaml` or `package-lock.json` in the Function project directory, not only at a workspace root.
</Warning>

Publishing again with the same Function name creates a new version. Callers keep using the same Function ID.

To ship several Functions from one entrypoint, see [publish multiple Functions](/platform/functions/write#publish-multiple-functions).

## Deploy from the Playground

The Playground lets you write and publish a Function without a local project. Test Stagehand or Playwright code in a live browser, define input parameters, then publish.

<img src="https://mintcdn.com/browserbase/CkBUsVlZA-tSW2IC/images/functions/playground-functions.gif?s=e95211f5c6a405d9a0d5df76603758aa" alt="Deploying Functions from the Playground" width="1532" height="1080" data-path="images/functions/playground-functions.gif" />

<Steps>
  <Step title="Open the Playground">
    Open the [Browserbase dashboard](https://www.browserbase.com/overview), then select **Playground**.
  </Step>

  <Step title="Write the browser script">
    The editor starts with a Stagehand template. Write the browser logic that the Function will run:

    ```javascript Playground theme={null}
    import { localBrowser, Stagehand } from "@browserbasehq/stagehand";

    const browser = await localBrowser.connect({ cdpUrl: connectUrl });
    const stagehand = await Stagehand.create({ browser });
    const page = await browser.context.activePage();

    await page.goto("https://example.com");
    await stagehand.act("Click the More information link");

    return {
      url: page.url(),
      title: await page.title(),
    };
    ```

    The Playground provides `connectUrl`, `sessionId`, `apiKey`, and `z` as globals. Use **Convert to Stagehand** to convert a Playwright script.

    <Note>
      The Playground does not compile TypeScript. Your code runs as JavaScript, so type annotations, interfaces, and casting will throw a SyntaxError. When you publish, the Playground puts your script into an index.ts file.
    </Note>
  </Step>

  <Step title="Test the script">
    Select **Run**. The Playground creates a browser session, runs the script, displays its output, and opens a live browser view.

    Use the console output and live view to fix the script before you publish it.
  </Step>

  <Step title="Define Function parameters">
    Open **Deploy**, then add inputs under **Function Parameters**:

    <img src="https://mintcdn.com/browserbase/CkBUsVlZA-tSW2IC/images/functions/params.gif?s=ff4770698bf1471748521135879c480e" alt="Adding Function parameters" width="1552" height="1080" data-path="images/functions/params.gif" />

    Each parameter has a name and an optional default value. The published Function receives the values through `params`:

    ```javascript Playground theme={null}
    await stagehand.act(`Search for "${params.searchQuery}"`);
    ```

    <Note>
      **Run** doesn't populate `params`. Use a literal value while you test, then replace it with `params.<name>` before you publish. You can define up to eight parameters.
    </Note>
  </Step>

  <Step title="Publish the Function">
    In the **Deploy** panel:

    1. Enter a Function name.
    2. Select **Deploy as Function**.

           <img src="https://mintcdn.com/browserbase/CkBUsVlZA-tSW2IC/images/functions/deploy.gif?s=9c5b536f40b1260faee55258371c55cf" alt="Publishing a Function" width="1532" height="1080" data-path="images/functions/deploy.gif" />

    After the build completes, the Playground shows an invoke command and a link to the Function details.
  </Step>
</Steps>

Publishing the same Function name creates a new version of the existing Function.

Move to a local project and [deploy from the CLI](#deploy-from-the-cli) when you need version control, multiple files, custom dependencies, or local editor tooling.

## After you deploy

Open **Functions** in the dashboard to:

* Copy the Function ID and invoke command.
* Review builds, versions, and invocation history.
* Inspect invocation logs and browser sessions.
* Delete a Function.

<CardGroup cols={2}>
  <Card title="Invoke a Function" icon="terminal" href="/platform/functions/invoke">
    Pass parameters and retrieve asynchronous results.
  </Card>

  <Card title="Write a Function" icon="code" href="/platform/functions/write">
    Configure schemas, browser settings, and multiple Functions.
  </Card>
</CardGroup>
