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

# Vercel agent-browser

> Run agent-browser commands on a Notte cloud browser.

<Tip>
  Read [the Notte skill](https://notte.cc/skill.md) and follow its setup instructions when setting up Notte or building browser automation. This is the shared source for CLI setup, authentication, and the browser-to-code workflow.
</Tip>

[agent-browser](https://agent-browser.dev/) is Vercel's browser automation CLI. Connect it to a Notte session over CDP to navigate, inspect pages, and interact with elements.

## Install

Install the CLI with Node.js 24+: `npm install -g agent-browser@0.39.1`.

For Python, use Python 3.11+ and `pip install notte-sdk`. For TypeScript, run `npm install notte-sdk` in a project with `"type": "module"`.

Set your [Notte API key](https://console.notte.cc/apikeys): `export NOTTE_API_KEY=your-notte-api-key`.

## Connect and read a page

Save the example as `notte_agent_browser.py` or `notte_agent_browser.ts`. Run `python notte_agent_browser.py` or `node --experimental-strip-types notte_agent_browser.ts`.

<CodeGroup>
  ```python notte_agent_browser.py theme={null}
  import json
  import os
  import subprocess
  from typing import Any

  from notte_sdk import NotteClient

  client = NotteClient()
  with client.Session() as session:
      command = ["agent-browser", "--session", f"notte-{session.session_id}", "--json"]
      names = (
          "PATH",
          "HOME",
          "TMPDIR",
          "TEMP",
          "TMP",
          "SystemRoot",
          "WINDIR",
          "PATHEXT",
          "USERPROFILE",
          "XDG_RUNTIME_DIR",
      )
      environment = {name: os.environ[name] for name in names if name in os.environ}
      environment["AGENT_BROWSER_CDP"] = session.cdp_url()

      def browser(*args: str) -> dict[str, Any]:
          try:
              completed = subprocess.run(
                  command + list(args), env=environment, capture_output=True, text=True, timeout=120, check=False
              )
              response = json.loads(completed.stdout)
              if (
                  completed.returncode
                  or not isinstance(response, dict)
                  or response.get("success") is not True
                  or not isinstance(response.get("data"), dict)
              ):
                  raise RuntimeError("agent-browser command failed")
              return response["data"]
          except (OSError, subprocess.SubprocessError, ValueError, TypeError, KeyError):
              raise RuntimeError("agent-browser command failed") from None

      failed = False
      try:
          _ = browser("open", "https://example.com")
          title = browser("get", "title")["title"]
          if not isinstance(title, str):
              raise RuntimeError("The title was not returned")
          print(title)
          result = {"title": title, "session_id": session.session_id}
      except BaseException:
          failed = True
          raise
      finally:
          try:
              _ = browser("close")
          except Exception:
              if not failed:
                  raise
  ```

  ```typescript notte_agent_browser.ts theme={null}
  import { execFile } from 'node:child_process';
  import { promisify } from 'node:util';
  import { NotteClient } from 'notte-sdk';

  const execute = promisify(execFile);

  const client = new NotteClient();
  export const result = await client.Session().use(async (session) => {
    const command = ['--session', `notte-${session.getId()!}`, '--json'];
    const names = ['PATH', 'HOME', 'TMPDIR', 'TEMP', 'TMP', 'SystemRoot', 'WINDIR', 'PATHEXT', 'USERPROFILE', 'XDG_RUNTIME_DIR'];
    const env = Object.fromEntries(names.map(name => [name, process.env[name]]));
    env.AGENT_BROWSER_CDP = await session.cdpUrl();
    async function browser(...args: string[]): Promise<Record<string, unknown>> {
      try {
        const { stdout } = await execute('agent-browser', [...command, ...args], { env, timeout: 120_000 });
        const response = JSON.parse(stdout);
        if (!response?.success || typeof response.data !== 'object' || response.data === null) throw new Error('Unsuccessful CLI command');
        return response.data;
      } catch {
        // CLI errors can include the authenticated CDP URL.
        throw new Error('agent-browser command failed');
      }
    }
    let failed = false;
    try {
      await browser('open', 'https://example.com');
      const { title } = await browser('get', 'title');
      if (typeof title !== 'string') throw new Error('The title was not returned');
      console.log(title);
      return { title, session_id: session.getId()! };
    } catch (error) {
      failed = true;
      throw error;
    } finally {
      try { await browser('close'); }
      catch (error) { if (!failed) throw error; }
    }
  });
  ```
</CodeGroup>

Both examples print `Example Domain`. Each uses its own CLI session name, disconnects the CLI in `finally`, and stops the Notte browser through the outer session scope.

Use `snapshot -i` to discover interactive element references, then `click @e1` or `fill @e1 value` to interact. Take a new snapshot after the page changes. See [agent-browser commands](https://agent-browser.dev/commands) and [Notte session lifecycle](/features/sessions/lifecycle).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.