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

# Custom MFA

> Inject MFA codes from your own systems during browser automation using event coordination.

# Custom MFA

Use **event coordination** to pass MFA codes from external systems — your mobile app, webhook, or backend — into an active browser session during automation.

## Overview

The system provides two operations:

* **Signal Event**: Send data to an event channel
* **Wait for Event**: Listen for data on an event channel with timeout

Events are user-scoped and work across multiple browser instances.

<Expandable title="API Endpoints">
  ## API Endpoints

  ### Signal an Event

  ```http theme={null}
  POST https://api.anchorbrowser.io/api/v1/events/{eventName}
  ```

  ### Wait for an Event

  ```http theme={null}
  POST https://api.anchorbrowser.io/api/v1/events/{eventName}/wait
  ```

  Both endpoints require `anchor-api-key` header and accept JSON payloads.

  ####
</Expandable>

## Custom MFA flow

Handle MFA codes during automated login flows:

```javascript theme={null}
// In your browser automation script
async function handleMFAFlow() {
  await page.fill('#username', 'user@example.com');
  await page.fill('#password', 'password');
  await page.click('#login-button');
  
  // Wait for MFA code from external system
  const mfaEvent = await waitForEvent('mfa_code', 30000);
  
  if (mfaEvent?.data?.code) {
    await page.fill('#mfa-code', mfaEvent.data.code);
    await page.click('#verify-button');
  }
}
```

```javascript theme={null}
// In your external system (mobile app, webhook, etc.)
async function sendMFACode(code) {
  await signalEvent('mfa_code', { code });
}
```

## Implementation

### Helper Functions

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

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

  async function signalEvent(eventName, data) {
    try {
      const response = await Events.signalEvent({
        path: { event_name: eventName },
        body: { data: data || {} },
      });
      return response;
    } catch (error) {
      throw new Error(`Failed to signal event: ${error.message}`);
    }
  }

  async function waitForEvent(eventName, timeoutMs = 60000) {
    try {
      const response = await Events.waitForEvent({
        path: { event_name: eventName },
        body: { timeoutMs },
      });
      return response;
    } catch (error) {
      if (error.message.includes("408")) return null; // Timeout
      throw new Error(`Failed to wait for event: ${error.message}`);
    }
  }
  ```

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

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

  def signal_event(event_name, data):
      try:
          response = anchor_client.events.signal_event(event_name, data=data or {})
          return response
      except Exception as error:
          raise Exception(f"Failed to signal event: {error}")

  def wait_for_event(event_name, timeout_ms=60000):
      try:
          response = anchor_client.events.wait_for_event(event_name, timeout_ms=timeout_ms)
          return response
      except Exception as error:
          if "408" in str(error):
              return None  # Timeout
          raise Exception(f"Failed to wait for event: {error}")
  ```
</CodeGroup>

## Event Flow Patterns

**Signal First, Wait Later** (immediate consumption):

```javascript theme={null}
await signalEvent("data", { value: "preloaded" });
const data = await waitForEvent("data", 1000); // Short timeout
```

**Wait First, Signal Later** (typical MFA flow):

```javascript theme={null}
const waitPromise = waitForEvent("mfa_code", 60000);
// ... other operations ...
const mfaData = await waitPromise;
```

## Best Practices

* Use descriptive event names: `mfa_code_login`, `mfa_code_transfer`
* Always set appropriate timeouts
* Validate received event data
* Handle timeout scenarios gracefully


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