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

# Async Session

> Create browser sessions without blocking and poll until they are ready

## Overview

`POST /v1/sessions/async` is the non-blocking variant of `POST /v1/sessions`. Instead of
waiting for the underlying browser pod to provision, it returns a `request_id` immediately
and provisions the session in the background. You then poll
`GET /v1/sessions/async/{request_id}/status` until the request reaches the `ready` status,
at which point the response includes the resolved `session_id`, `cdp_url` and `live_view_url`.

This pattern is useful when you want to:

* Kick off many sessions in parallel without holding open long-lived HTTP requests.
* Avoid request timeouts while large or proxied sessions are being provisioned.
* Decouple session creation from session consumption (for example, queue the work and connect later).

## How It Works

<Steps>
  <Step title="Create the async request">
    Send a `POST` to `/v1/sessions/async` with your browser configuration. The response
    returns immediately with a `request_id` and `status: "pending"`.
  </Step>

  <Step title="Poll for readiness">
    Call `GET /v1/sessions/async/{request_id}/status` on an interval. The request moves
    through the provisioning phases until `status` becomes `ready`.
  </Step>

  <Step title="Connect to the session">
    Once ready, read `session_id`, `cdp_url` and `live_view_url` from the embedded
    `session` object and connect over CDP as you would for a standard session.
  </Step>
</Steps>

## Create an Async Session

<CodeGroup>
  ```javascript node.js theme={null}
  const API_BASE = 'https://api.anchorbrowser.io';

  const headers = {
    'anchor-api-key': process.env.ANCHOR_API_KEY,
    'Content-Type': 'application/json',
  };

  const browserConfiguration = {
    session: {
      proxy: { active: true },
      timeout: { idle_timeout: 5, max_duration: 25 },
      recording: { active: true },
    },
  };

  const response = await fetch(`${API_BASE}/v1/sessions/async`, {
    method: 'POST',
    headers,
    body: JSON.stringify(browserConfiguration),
  });

  const { data } = await response.json();
  console.log('request_id:', data.request_id, 'status:', data.status);
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.anchorbrowser.io/v1/sessions/async \
    -H "anchor-api-key: $ANCHOR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "browser": {
        "headless": { "active": false },
        "adblock": { "active": true },
        "captcha_solver": { "active": true }
      },
      "session": {
        "proxy": { "active": true, "free_roam": false },
        "recording": { "active": true }
      }
    }'
  ```
</CodeGroup>

The request body is identical to the standard [Start Browser Session](/api-reference) request,
so any configuration you can pass to `POST /v1/sessions` is also accepted here.

A successful response is returned immediately:

```json theme={null}
{
  "data": {
    "request_id": "b1f9e0a2-7c3d-4f5a-9b2e-1d6c8a4f0e21",
    "status": "pending",
    "session_id": null
  }
}
```

## Poll for Readiness

Poll the status endpoint using the `request_id` until `status` becomes `ready`.

<CodeGroup>
  ```javascript node.js theme={null}
  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

  async function pollUntilReady(requestId) {
    while (true) {
      const response = await fetch(`${API_BASE}/v1/sessions/async/${requestId}/status`, { headers });
      const { data } = await response.json();

      if (data.status === 'ready') return data;
      if (data.status === 'failed' || data.status === 'cancelled') {
        throw new Error(`Async request reached terminal status: ${data.status}`);
      }

      await sleep(3_000);
    }
  }
  ```

  ```bash cURL theme={null}
  curl https://api.anchorbrowser.io/v1/sessions/async/{request_id}/status \
    -H "anchor-api-key: $ANCHOR_API_KEY"
  ```
</CodeGroup>

A response while provisioning looks like:

```json theme={null}
{
  "data": {
    "request_id": "b1f9e0a2-7c3d-4f5a-9b2e-1d6c8a4f0e21",
    "status": "processing",
    "created_at": "2026-06-04T11:00:00.000Z",
    "progress": { "current_phase": "provisioning" }
  }
}
```

Once ready, the embedded `session` object is populated:

```json theme={null}
{
  "data": {
    "request_id": "b1f9e0a2-7c3d-4f5a-9b2e-1d6c8a4f0e21",
    "status": "ready",
    "created_at": "2026-06-04T11:00:00.000Z",
    "progress": { "current_phase": "ready" },
    "session": {
      "session_id": "9c0d1e2f-3a4b-5c6d-7e8f-9a0b1c2d3e4f",
      "status": "running",
      "cdp_url": "wss://connect.anchorbrowser.io?...",
      "live_view_url": "https://live.anchorbrowser.io/..."
    }
  }
}
```

### Request Statuses

| Status       | Description                                                                                    |
| ------------ | ---------------------------------------------------------------------------------------------- |
| `pending`    | Request accepted, not yet picked up for provisioning.                                          |
| `processing` | The browser pod is being provisioned and configured.                                           |
| `ready`      | The session is connectable. `session.session_id`, `cdp_url` and `live_view_url` are available. |
| `completed`  | The session has finished its lifecycle.                                                        |
| `failed`     | Provisioning failed. No session was produced.                                                  |
| `cancelled`  | The request was cancelled before a session was produced.                                       |

### Provisioning Phases

The `progress.current_phase` field reports finer-grained progress while `status` is `pending` or `processing`:

| Phase          | Description                                      |
| -------------- | ------------------------------------------------ |
| `queued`       | Waiting for capacity.                            |
| `provisioning` | The browser pod is starting up.                  |
| `configuring`  | Applying your browser and session configuration. |
| `ready`        | The session is up and connectable.               |

## Complete Example

The following script spawns multiple async sessions in parallel, polls each one until it is
ready, and prints the connection details. Set `ANCHOR_API_KEY` in your environment before running.

```javascript node.js theme={null}
#!/usr/bin/env node

const ANCHOR_API_KEY = process.env.ANCHOR_API_KEY;

const SESSION_COUNT = 2;
const POLL_INTERVAL_MS = 3_000;

const API_BASE = 'https://api.anchorbrowser.io';

const browserConfiguration = {
  session: {
    proxy: { active: true },
    timeout: { idle_timeout: 5, max_duration: 25 },
    recording: { active: true },
  },
};

const headers = {
  'anchor-api-key': ANCHOR_API_KEY,
  'Content-Type': 'application/json',
};

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function createAsyncSession(label) {
  const response = await fetch(`${API_BASE}/v1/sessions/async`, {
    method: 'POST',
    headers,
    body: JSON.stringify(browserConfiguration),
  });
  const json = await response.json();
  console.log(`[${label}] create response:`, JSON.stringify(json, null, 2));
  return json.data;
}

async function pollUntilReady(requestId, label) {
  while (true) {
    const response = await fetch(`${API_BASE}/v1/sessions/async/${requestId}/status`, { headers });
    const json = await response.json();
    console.log(`[${label}] poll response:`, JSON.stringify(json, null, 2));

    const status = json.data ?? {};
    if (status.status === 'ready') return status;
    if (status.status === 'failed' || status.status === 'cancelled') {
      throw new Error(`[${label}] async request reached terminal status: ${status.status}`);
    }

    await sleep(POLL_INTERVAL_MS);
  }
}

async function runOne(label) {
  const created = await createAsyncSession(label);
  const status = await pollUntilReady(created.request_id, label);
  const session = status.session;

  console.log(`\n[${label}] READY — session info:`);
  console.log(`  request_id    : ${created.request_id}`);
  console.log(`  session_id    : ${session.session_id}`);
  console.log(`  cdp_url       : ${session.cdp_url}`);
  console.log(`  live_view_url : ${session.live_view_url}`);
  console.log(`  status        : ${session.status}`);
  console.log(`  full session  :`, JSON.stringify(session, null, 2));
}

(async () => {
  const labels = Array.from({ length: SESSION_COUNT }, (_, i) => `s${i + 1}`);
  console.log(`Spawning ${SESSION_COUNT} async session(s) on ${API_BASE}\n`);
  await Promise.all(labels.map(runOne));
})();
```

<Note>
  Once a session is `ready`, connect to it over CDP using the returned `cdp_url`, exactly as you
  would for a standard session. The session honors the same `idle_timeout` and `max_duration`
  settings you passed in the configuration, so make sure to connect before the idle timeout
  elapses.
</Note>
