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

> ## Agent Instructions
> Anchor Browser is cloud browser infrastructure for AI agents and automation: browser sessions you control over CDP or REST, natural-language web tasks, versioned automation tasks, managed authentication into third-party web apps (identities with MFA), persistent volumes and profiles, recordings, live view, batch sessions, webhooks, and network options including residential proxies, extra stealth, and captcha solving for sites that block standard browsers. AI agents should start at https://docs.anchorbrowser.io/for-agents, then get an API key with Agent Access at https://docs.anchorbrowser.io/quickstart/agent-access — no dashboard account required. Read those two pages before authentication or API calls.

# Demonstrations API

> Send a shareable link so someone can demonstrate a task and Anchor generates production-ready automation from it.

Send a shareable link so someone can demonstrate a task in a live browser. Anchor captures every event and compiles it into deterministic, repeatable code with an AI fallback — the same outcome as [creating a task from a demonstration](/tasks/creating-a-task#create-from-a-demonstration) in the UI.

Use this when the person who knows the flow isn't at the keyboard in your Anchor workspace.

## How it works

1. **Create** a demonstration session via API — you get back a `share_url`
2. **Send** the link to the person who will demonstrate the task
3. They open it, see a live browser, and **perform the task**
4. They click **Finish Demonstration** — the demonstration is submitted
5. Anchor **compiles the captured events** into a task
6. **Poll** the status endpoint until it reaches `completed` — you get `task_id` and `tool_id`

## API Endpoints

### Create a demonstration

<CodeGroup>
  ```javascript node.js theme={null}
  import { client } from 'anchorbrowser';

  client.setConfig({ auth: () => process.env.ANCHOR_API_KEY });

  const { data: demo } = await client.post({
    url: '/v1/demonstrations/',
    body: {
      task_name: 'Download invoice report',
      task_description: 'Navigate to Reports, select the monthly invoice report, and download it as PDF',
      user_name: 'John',
    },
  });

  console.log('Share URL:', demo.share_url);
  console.log('Session ID:', demo.session_id);
  console.log('Task ID:', demo.task_id);
  ```

  ```python python theme={null}
  import os
  from anchorbrowser import Anchorbrowser

  anchor_client = Anchorbrowser(api_key=os.getenv('ANCHOR_API_KEY'))

  demo = anchor_client.post(
      '/v1/demonstrations/',
      body={
          'task_name': 'Download invoice report',
          'task_description': 'Navigate to Reports, select the monthly invoice report, and download it as PDF',
          'user_name': 'John',
      },
      cast_to=object,
  )

  print('Share URL:', demo['share_url'])
  print('Session ID:', demo['session_id'])
  print('Task ID:', demo['task_id'])
  ```
</CodeGroup>

**Request body:**

| Field | Type | Required | Description |
| - | - | - | - |
| `task_name` | string | Yes | Name for the task being demonstrated |
| `task_description` | string | Yes | Natural language description of what the task does — helps Anchor interpret the demonstration |
| `identity_id` | string | No | Pre-authenticate the browser with a saved identity |
| `identity_skip_validation` | boolean | No | Skip identity validation (default: `true`) |
| `user_name` | string | No | Display name shown in the demonstration UI ("Thanks, John!") |
| `session_config` | object | No | Override browser session settings (start URL, proxy, timeouts, etc.) |

**Response:**

```json theme={null}
{
  "session_id": "abc123-...",
  "live_view_url": "https://connect.anchorbrowser.io/...",
  "share_url": "https://app.anchorbrowser.io/demonstrate?token=eyJ...",
  "share_token": "eyJ...",
  "share_expires_at": "2026-04-15T09:00:00.000Z",
  "task_id": "task-uuid-..."
}
```

<Note>
  The `share_url` is a signed JWT link valid for 1 hour. The customer does not need an Anchor account — the token contains the session and team context.
</Note>

### Get demonstration status

Poll this endpoint to track progress after the demonstration is submitted.

<CodeGroup>
  ```javascript node.js theme={null}
  const { data: status } = await client.get({ url: `/v1/demonstrations/${sessionId}` });
  console.log(status);
  ```

  ```python python theme={null}
  status = anchor_client.get(f'/v1/demonstrations/{session_id}', cast_to=object)
  print(status)
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "session_id": "abc123-...",
  "status": "completed",
  "hektor_project_id": "proj-uuid-...",
  "task_id": "task-uuid-...",
  "task_version_id": "ver-uuid-...",
  "tool_id": "tool-uuid-...",
  "created_at": "2026-04-15T07:32:12.865Z"
}
```

**Status values:**

| Status | Description |
| - | - |
| `recording` | Browser session is live — demonstration in progress |
| `processing` | Demonstration complete — Anchor is compiling the task |
| `completed` | Task generated — `task_id` and `tool_id` are available |
| `failed` | Task generation failed |
| `stopped` | Session was stopped before completing |

### Complete demonstration

Called automatically when the user clicks **Finish Demonstration**. Can also be called programmatically via `POST .../recording/complete`.

<CodeGroup>
  ```javascript node.js theme={null}
  const { data: result } = await client.post({
    url: `/v1/demonstrations/${sessionId}/recording/complete`,
  });
  console.log(result);
  ```

  ```python python theme={null}
  result = anchor_client.post(f'/v1/demonstrations/{session_id}/recording/complete', cast_to=object)
  print(result)
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "session_id": "abc123-...",
  "status": "processing",
  "hektor_project_id": "proj-uuid-...",
  "task_id": "task-uuid-..."
}
```

This endpoint:

1. Ends the browser session and uploads the captured events
2. Waits for demonstration artifacts to be stored
3. Submits them for task generation
4. Returns immediately with `status: "processing"`

### Stop demonstration

Stop a demonstration without generating a task. Useful for cleanup.

<CodeGroup>
  ```javascript node.js theme={null}
  const { data: result } = await client.post({ url: `/v1/demonstrations/${sessionId}/stop` });
  console.log(result);
  ```

  ```python python theme={null}
  result = anchor_client.post(f'/v1/demonstrations/{session_id}/stop', cast_to=object)
  print(result)
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "success": true
}
```

## End-to-end example

<CodeGroup>
  ```javascript node.js theme={null}
  import { client } from 'anchorbrowser';

  client.setConfig({ auth: () => process.env.ANCHOR_API_KEY });

  // 1. Create demonstration
  const { data: demo } = await client.post({
    url: '/v1/demonstrations/',
    body: {
      task_name: 'Download invoice report',
      task_description: 'Go to Reports > Invoices, select this month, download PDF',
      identity_id: 'your-identity-id',
      user_name: 'Sarah',
    },
  });

  console.log(`Send this link to your customer: ${demo.share_url}`);
  const sessionId = demo.session_id;

  // 2. Poll until completed
  let status;
  while (true) {
    status = (await client.get({ url: `/v1/demonstrations/${sessionId}` })).data;
    console.log(`Status: ${status.status}`);

    if (['completed', 'failed', 'stopped'].includes(status.status)) break;
    await new Promise((r) => setTimeout(r, 5000));
  }

  // 3. Use the generated task
  if (status.status === 'completed') {
    console.log(`Task ID: ${status.task_id}`);
    console.log(`Tool ID: ${status.tool_id}`);
  }
  ```

  ```python python theme={null}
  import os
  import time
  from anchorbrowser import Anchorbrowser

  anchor_client = Anchorbrowser(api_key=os.getenv('ANCHOR_API_KEY'))

  # 1. Create demonstration
  demo = anchor_client.post(
      '/v1/demonstrations/',
      body={
          'task_name': 'Download invoice report',
          'task_description': 'Go to Reports > Invoices, select this month, download PDF',
          'identity_id': 'your-identity-id',
          'user_name': 'Sarah',
      },
      cast_to=object,
  )

  print(f"Send this link to your customer: {demo['share_url']}")
  session_id = demo['session_id']

  # 2. Poll until completed
  while True:
      status = anchor_client.get(f'/v1/demonstrations/{session_id}', cast_to=object)
      print(f"Status: {status['status']}")

      if status['status'] in ('completed', 'failed', 'stopped'):
          break

      time.sleep(5)

  # 3. Use the generated task
  if status['status'] == 'completed':
      print(f"Task ID: {status['task_id']}")
      print(f"Tool ID: {status['tool_id']}")
  ```
</CodeGroup>

## Identity pre-authentication

Pass an `identity_id` to pre-authenticate the browser before the link is opened. The user will see the target application already logged in and can start the demonstration immediately.

```json theme={null}
{
  "task_name": "Export quarterly report",
  "task_description": "Navigate to the reports section and export Q1 data",
  "identity_id": "7f0db4ad-74ca-42e5-896e-3f0daea36c13"
}
```

<Tip>
  If identity authentication fails (expired credentials, site unreachable), the session still starts — the user can log in manually during the demonstration. Set `identity_skip_validation: true` (default) to ensure this behavior.
</Tip>

## Share URL and the demonstration UI

The `share_url` opens a full-screen demonstration interface with:

* **Live browser** — interact with the actual website
* **Live Browser Events panel** — clicks, typing, and navigation as they happen
* **Finish Demonstration** — submits the demonstration and starts task generation

When the user finishes, they see a confirmation screen. If the share URL was opened as a popup (via `window.open`), the parent window receives a `demonstration-complete` postMessage with the `task_id`, `task_version_id`, and `tool_id`.

## Session configuration

Override default session settings:

```json theme={null}
{
  "task_name": "My task",
  "task_description": "Task description",
  "session_config": {
    "browser": {
      "start_url": "https://app.example.com/dashboard"
    },
    "session": {
      "timeout": {
        "max_duration": 60,
        "idle_timeout": 30
      }
    }
  }
}
```

Default demonstration timeouts are `max_duration: 30` minutes and `idle_timeout: 30` minutes.


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