# Embedded Browser Live UI
Source: https://docs.anchorbrowser.io/advanced/browser-live-view
Embed interactive browser sessions directly into your application
## Overview
Anchor Browser offers a live view feature that allows you to embed an interactive frame of a website as a web element. The `live_view_url` is received when creating a session with `headless: false` (which is the default mode).
## Headful Mode (Default)
Headful mode provides a single URL to view the full chrome view, including the address bar. This ensures the presented tab is always the active tab and provides the best user experience.
To create a browser in headful mode, set the `headless` parameter to `false` when [creating a session](/api-reference/sessions/create-session):
```javascript node.js
const axios = require('axios');
const ANCHOR_API_KEY = process.env.ANCHOR_API_KEY;
(async () => {
const response = await axios.post("https://api.anchorbrowser.io/v1/sessions", {
browser: {
headless: {
active: false
}
}
}, {
headers: {
"anchor-api-key": ANCHOR_API_KEY,
"Content-Type": "application/json",
},
});
const session = response.data.data;
const liveViewUrl = session.live_view_url;
})().catch(console.error);
```
```python python
import os
import requests
ANCHOR_API_KEY = os.getenv("ANCHOR_API_KEY")
response = requests.post(
"https://api.anchorbrowser.io/v1/sessions",
json={ "browser": {
"headless": {"active": False}
}
},
headers={
"anchor-api-key": ANCHOR_API_KEY,
"Content-Type": "application/json",
},
)
response.raise_for_status()
session = response.json()["data"]
live_view_url = session["live_view_url"]
```
Then, use the `live_view_url` from the response to embed the live view directly into an iframe:
```html
```
## Advanced Embedding Configuration
### Embed in Fullscreen View (Hide Navigation Bar)
To use the fullscreen view, replace the live view URL with the following:
```html
```
### Disable Browser Interactivity
To prevent the end user from interacting with the browser, add the `style="pointer-events: none;"` attribute to the iframe:
```html
```
This feature is available for both headful and headless modes. In headless mode, you would use the `session_url` instead of `live_view_url`.
## Headless Mode (Legacy)
Headless mode is being deprecated and will be removed in a future version. We recommend using headful mode for all new implementations.
To obtain the browser live session URL in headless mode, start by [creating a session](/api-reference/sessions/create-session) with `headless: true`:
The session\_url points to the browser default first page. If your browser process involves creating a **new page**, collect the corresponding URL by using the [live view URLs](/api-reference/sessions/get-pages-for-a-session) endpoint.
Then, use the **create-session** response to embed the live view URL directly into an iframe:
```html
```
# Captcha Solving
Source: https://docs.anchorbrowser.io/advanced/captcha-solving
### Visual CAPTCHA solving
Anchor browser solves CAPTCHA challenges using a vision-based approach, along with extension-based fallbacks. The vision-based approach imitates human behavior to solve any CAPTCHA (including Cloudflare) without mulitple challenges.
CAPTCHA solving works best with proxy enabled. Bot detectors would likely fail CAPTCHA solving attempts that are performed without Proxy.
For the full list of available options, view the [interactive api documentation](/api-reference)
### Code Example
```bash
curl --request POST \
--url https://api.anchorbrowser.io/v1/sessions \
--header 'Content-Type: application/json' \
--header 'anchor-api-key: ' \
--data '{
"browser": {
"captcha_solver": {
"active": true
}
}
}'
```
# Dedicated Sticky IP
Source: https://docs.anchorbrowser.io/advanced/dedicated-sticky-ip
Reserve a fixed IP address for a specific profile.
A **Dedicated Sticky IP** ensures that a specific profile uses by default the same IP address, reserved exclusively for that profile. This is helpful when IP consistency is required across sessions.
Use the [Create Profile API](https://docs.anchorbrowser.io/api-reference/profiles/create-profile?playground=open) to create a profile with a dedicated sticky IP by setting:
```json
{
"dedicated_sticky_ip": true
}
```
This allocates a dedicated IP that is not shared with other profiles.
Any browser session started using this profile will automatically use the reserved sticky IP.
To override the default sticky IP, set the `proxy` field when using the [Start Browser Session API](https://docs.anchorbrowser.io/api-reference/browser-sessions/start-browser-session).
# Browser Extensions
Source: https://docs.anchorbrowser.io/advanced/extensions
Upload and use custom browser extensions in your sessions
Anchor allows you to upload and use Chrome extensions in your browser sessions. This lets you add ad blockers, privacy tools, or any other extension to enhance your browsing automation.
For uploading, listing, and managing extensions, see the [interactive API documentation](/api-reference/extensions).
## Getting Extensions from Chrome Web Store
To use extensions from the Chrome Web Store, you'll need to download and inspect their files:
### Download Extension Files
1. **Install CRX Extractor/Downloader** - Add this extension to your browser to download .crx files
2. **Navigate to the extension** you want on the Chrome Web Store
3. **Click the CRX Extractor icon** and download the .crx file
4. **Rename the file** from `.crx` to `.zip`
5. **Extract the ZIP** to inspect the contents
### Inspect Extension Contents
Once extracted, you'll see the extension's files:
* `manifest.json` - Contains extension metadata and permissions
* `background.js` or `service_worker.js` - Background scripts
* `content_scripts/` - Scripts that run on web pages
* `popup.html` - Extension popup interface
* `icons/` - Extension icons
### Repackage for Upload
After inspecting (and optionally modifying) the files:
1. **Select all files and folders** in the extracted directory
2. **Create a new ZIP file** containing all the extension files
3. **Upload this ZIP** to AnchorBrowser using the API
## Extension Requirements
Your extension ZIP file must contain a valid `manifest.json` with basic extension information like name and version.
### Example Manifest
```json
{
"manifest_version": 3,
"name": "My Extension",
"version": "1.0.0",
"description": "Extension description",
"permissions": ["activeTab", "storage"],
"background": {
"service_worker": "background.js"
},
"content_scripts": [{
"matches": [""],
"js": ["content.js"]
}]
}
```
## Code Examples
### JavaScript/Node.js
```tsx node.js
import fs from 'fs';
import FormData from 'form-data';
async function uploadExtension() {
const form = new FormData();
form.append('name', 'My Custom Extension');
form.append('file', fs.createReadStream('./my-extension.zip'));
const response = await fetch('https://api.anchorbrowser.io/v1/extensions', {
method: 'POST',
headers: {
'anchor-api-key': 'your_api_key_here',
...form.getHeaders()
},
body: form
});
const result = await response.json();
return result.data.id;
}
// Use the extension in a session
async function createSessionWithExtension(extensionId) {
const response = await fetch('https://api.anchorbrowser.io/v1/sessions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'anchor-api-key': 'your_api_key_here'
},
body: JSON.stringify({
browser: {
extensions: [extensionId]
}
})
});
return response.json();
}
```
```python python
import requests
def upload_extension(api_key, extension_path, name):
with open(extension_path, 'rb') as f:
files = {'file': f}
data = {'name': name}
response = requests.post(
'https://api.anchorbrowser.io/v1/extensions',
headers={'anchor-api-key': api_key},
files=files,
data=data
)
return response.json()
# Use the extension in a session
def create_session_with_extension(api_key, extension_id):
response = requests.post(
'https://api.anchorbrowser.io/v1/sessions',
headers={
'anchor-api-key': api_key,
'Content-Type': 'application/json'
},
json={
'browser': {
'extensions': [extension_id]
}
}
)
return response.json()
# Usage
result = upload_extension('your_api_key', './my-extension.zip', 'My Extension')
extension_id = result['data']['id']
# Create session with the extension
session = create_session_with_extension('your_api_key', extension_id)
```
## Limitations
* Maximum extension size: 50MB per ZIP file
* Extensions must be valid Chrome extensions
# File Download
Source: https://docs.anchorbrowser.io/advanced/file-download
Anchor Browser supports two methods for downloading files during your browser sessions:
1. **Traditional Downloads**: Files are downloaded to the browser instance and then uploaded to S3 for retrieval
2. **P2P Downloads**: Files are captured directly in the browser using peer-to-peer technology, bypassing S3 storage
## Traditional File Downloads
The following examples demonstrate how to download a file using the traditional method and retrieve it from the browser session.
Use the [create session](api-reference/browser-sessions/start-browser-session) API to create a new browser session.
Use the following example to perform a file download
```tsx node.js
await page.goto("https://browser-tests-alpha.vercel.app/api/download-test");
await Promise.all([page.waitForEvent("download"), page.locator("#download").click()]); // The download has completed
```
```python python
await page.goto("https://browser-tests-alpha.vercel.app/api/download-test")
async with page.expect_download() as download_info:
await page.locator("#download").click()
download = await download_info.value
```
You can retrieve the downloaded file from the browser session using the [get session downloads](/api-reference/browser-sessions/list-session-downloads) API
## P2P Downloads
For enhanced performance and direct file capture without S3 storage, see our [P2P Download Guide](/advanced/p2p-downloads) which provides complete implementation examples and best practices.
# File Upload
Source: https://docs.anchorbrowser.io/advanced/file-upload
Anchor Browser allows you to upload files during your browser sessions, enabling you to interact with web applications/forms that require files as input.
The following examples demonstrate how to upload a file, either from your local development environment or one downloaded during the browser session.
## Using a local file
### Playwright example
```tsx node.js
await page.goto('https://browser-tests-alpha.vercel.app/api/upload-test')
const input = await page.$("#fileUpload")
await input.setInputFiles('/tmp/my-files/google.png'); // Reference the local file path
```
```python python
page.goto('https://browser-tests-alpha.vercel.app/api/upload-test')
input = page.locator("#fileUpload")
input.set_input_files('/tmp/my-files/google.png') # Reference the local file path
```
# MCP - Hosted Version
Source: https://docs.anchorbrowser.io/advanced/mcp
Use Anchor with Model Context Protocol (MCP) in your preferred agentic tools via our hosted service
## Overview
Anchor provides a **hosted** Model Context Protocol (MCP) integration, allowing you to use browser automation directly from your preferred AI tools without any local setup. Our hosted MCP server runs on our infrastructure and is available to all users with an Anchor API key.
This enables seamless browser control from Cursor, VS Code, Claude, ChatGPT, and other MCP-compatible tools without managing any local dependencies.
## What is MCP?
Model Context Protocol (MCP) is an open standard that allows AI assistants to interact with external tools and data sources.
In our case, it enables AI-powered tools to access and control our browser automation capabilities directly within your IDE, agent apps, or CI/CD pipelines.
## Hosted vs Self-Hosted
Our **hosted MCP service** provides:
* ✅ Zero setup - just add your API key
* ✅ Always up-to-date with latest features
* ✅ Managed infrastructure and updates
* ✅ Built-in scaling and reliability
* ✅ Direct integration with Anchor's cloud browsers
For advanced customization needs, see our [Open Source MCP Server](/advanced/mcp-open-source) documentation.
## Setup in Cursor
Other MCP-compatible tools follow about the same pattern.
The MCP server runs on our servers ([https://api.anchorbrowser.io/mcp](https://api.anchorbrowser.io/mcp)), and is available to all users providing their Anchor API Key.
### Configure MCP in Cursor
Press Command+Shift+P (Mac) or Ctrl+Shift+P (Linux/Windows) and select "Open MCP Configuration File"
Click on "Add Custom MCP" or "New MCP Server" if you already have some preconfigured.
Add inside the `mcpServers` object the following:
```json
"Anchor Browser Agent": {
"url": "https://api.anchorbrowser.io/mcp",
"headers": {
"anchor-api-key": "YOUR_ANCHOR_API_KEY"
}
}
```
If you don't have your Anchor API key yet, you can get it from [Anchor UI](https://app.anchorbrowser.io/api-key).
You should now see Anchor MCP server in the list of MCP servers in Cursor. It should say '24 tools enabled'. If you don't see it, disable and re-enable Anchor MCP server, or wait a little longer.
## Setup in VS Code
Install the MCP extension for VS Code from the marketplace.
Add to your VS Code MCP configuration file:
```json
{
"mcpServers": {
"anchor-browser": {
"url": "https://api.anchorbrowser.io/mcp",
"headers": {
"anchor-api-key": "YOUR_ANCHOR_API_KEY"
}
}
}
}
```
Restart VS Code to load the new MCP server configuration.
## Setup in Claude Desktop
Open Claude Desktop's configuration file (`claude_desktop_config.json`).
Add the following to your configuration:
```json
{
"mcpServers": {
"anchor-browser": {
"url": "https://api.anchorbrowser.io/mcp",
"headers": {
"anchor-api-key": "YOUR_ANCHOR_API_KEY"
}
}
}
}
```
Restart Claude Desktop to apply the configuration.
# Usage
Once configured, you can use Anchor Browser directly in your conversations with your AI assistant.
## Available Tools
The hosted MCP integration provides access to all main Anchor capabilities:
### Test Generator Example
```
- You are a playwright test generator.
- You are given a scenario and you need to generate a playwright test for it.
- DO NOT generate test code based on the scenario alone.
- DO run steps one by one using the tools provided by the Anchor Browser Agent MCP.
- Only after all steps are completed, emit a Playwright TypeScript test that uses @playwright/test based on message history
- Save generated test file in the tests directory
- Execute the test file and iterate until the test passes
Generate a Playwright test for the following scenario:
1. Navigate to https://www.imdb.com/
2. search for 'Garfield'
3. return the director of the last movie
```
That is the generated test file:
```js
import { test, expect } from '@playwright/test';
test('Find director of the last Garfield movie', async ({ page }) => {
// Step 1: Navigate to IMDB
await page.goto('https://www.imdb.com/');
// Verify we're on the IMDB homepage
await expect(page).toHaveTitle(/IMDb/);
// Step 2: Search for 'Garfield'
// Click on the search box
await page.getByTestId('suggestion-search').click();
// Type 'Garfield' into the search box
await page.getByTestId('suggestion-search').fill('Garfield');
// Submit the search
await page.getByRole('button', { name: 'Submit search' }).click();
// Verify we're on the search results page
await expect(page).toHaveURL(/\/find\/\?q=Garfield/);
await expect(page).toHaveTitle(/Find - IMDb/);
// Step 3: Click on the most recent Garfield movie (The Garfield Movie 2024)
await page.getByRole('link', { name: 'The Garfield Movie' }).click();
// Verify we're on the movie page
await expect(page).toHaveURL(/\/title\/tt5779228/);
await expect(page).toHaveTitle(/The Garfield Movie \(2024\)/);
// Step 4: Extract the director information
// The director information is displayed in the main content area
const directorElement = page.locator('text=Director').locator('..').locator('a').first();
// Verify the director is Mark Dindal
await expect(directorElement).toHaveText('Mark Dindal');
// Log the director name for verification
const directorName = await directorElement.textContent();
console.log(`Director of The Garfield Movie (2024): ${directorName}`);
// Assert the expected result
expect(directorName).toBe('Mark Dindal');
});
```
## Programmatic Usage (Python SDK)
You can also use the hosted MCP service programmatically in your Python applications using the MCP client library:
### Installation
```bash
pip install mcp
```
### Basic Example
```python
import asyncio
from mcp.client.streamable_http import streamablehttp_client
from mcp import ClientSession
async def list_tools():
async with streamablehttp_client(
url="https://api.anchorbrowser.io/mcp",
headers={"anchor-api-key": "sk-your-key"}
) as (
read_stream,
write_stream,
_,
):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()
tools = await session.list_tools()
for tool in tools.tools:
print(f"{tool.name}: {getattr(tool, 'description', '')}")
asyncio.run(list_tools())
```
## CI/CD Integration
The hosted MCP service works in CI/CD environments without requiring local browser installations:
```yaml
# GitHub Actions example
name: AI Browser Testing
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run AI tests
env:
ANCHOR_API_KEY: ${{ secrets.ANCHOR_API_KEY }}
run: |
python ai_test_runner.py
```
## Getting Help
If you encounter issues with the hosted MCP integration:
1. **Check API Key**: Ensure your API key is valid
2. **Restart MCP Client**: Disable and re-enable the MCP server in your client
3. **Contact Support**: Reach out at [support@anchorbrowser.io](mailto:support@anchorbrowser.io)
## Migration from Self-Hosted
Moving from a self-hosted MCP server to our hosted service:
1. **Update Configuration**: Change your MCP client to use `https://api.anchorbrowser.io/mcp`
2. **Add API Key**: Include your Anchor API key in the headers
3. **Remove Local Dependencies**: Uninstall local MCP server and dependencies
4. **Test Integration**: Verify all your existing MCP workflows still work
# MCP - Open Source
Source: https://docs.anchorbrowser.io/advanced/mcp-open-source
Self-host Anchor MCP server with customizable Playwright integration for your specific needs
# Anchor MCP Server (Open Source)
A Model Context Protocol (MCP) server that provides browser automation capabilities using [Anchor Browser](https://anchorbrowser.io)'s remote browser service with [Playwright](https://playwright.dev). This server enables LLMs to interact with web pages through Anchor's cloud-based browsers with built-in proxies, stealth features, and advanced capabilities.
This is based on the open source repository at [browsermcp-com/mcp](https://github.com/browsermcp-com/mcp), which extends Microsoft's Playwright MCP with Anchor Browser's cloud infrastructure.
Looking for our hosted MCP service? Check out [MCP - Hosted Version](/advanced/mcp) for zero-setup integration.
## When to Use Open Source MCP
Choose the open source version when you need:
* **Custom tool modifications** - Modify browser automation tools for specific use cases
* **Advanced configuration** - Fine-tune browser settings and behaviors
* **Local development** - Test MCP integrations during development
* **Compliance requirements** - Run MCP server within your infrastructure
* **Integration with existing systems** - Connect MCP to your internal tools and workflows
## Key Features
* **Remote Browser Execution**: Uses Anchor Browser's cloud infrastructure instead of local browsers
* **Built-in Proxies**: Automatic residential proxy rotation and geo-targeting
* **Stealth & Anti-Detection**: Advanced browser fingerprinting and anti-bot detection
* **Fast and lightweight**: Uses Playwright's accessibility tree, not pixel-based input
* **LLM-friendly**: No vision models needed, operates purely on structured data
* **Deterministic tool application**: Avoids ambiguity common with screenshot-based approaches
* **Customizable**: Modify and extend tools for your specific needs
## Requirements
* Node.js 18 or newer
* **Anchor Browser API Key** ([Get one here](https://anchorbrowser.io))
* VS Code, Cursor, Windsurf, Claude Desktop, Goose or any other MCP client
## Getting Started
### 1. Clone and Build
Since this is a custom Anchor MCP server, you need to build it locally:
```bash
# Clone the repository
git clone https://github.com/browsermcp-com/mcp.git
cd mcp
# Install dependencies and build
npm install
npm run build
```
### 2. Get Your Anchor API Key
1. Sign up at [anchorbrowser.io](https://anchorbrowser.io)
2. Get your API key from the dashboard
3. Copy your API key (starts with `sk-`)
### 3. Configure MCP Client
#### Cursor
Add to your `~/.cursor/mcp.json`:
```json
{
"mcpServers": {
"anchor-browser": {
"command": "node",
"args": [
"/path/to/mcp/cli.js"
],
"env": {
"ANCHOR_API_KEY": "sk-your-api-key-here"
}
}
}
}
```
#### VS Code
Add to your MCP configuration:
```json
{
"mcpServers": {
"anchor-browser": {
"command": "node",
"args": [
"/path/to/mcp/cli.js"
],
"env": {
"ANCHOR_API_KEY": "sk-your-api-key-here"
}
}
}
}
```
#### Claude Desktop
Add to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"anchor-browser": {
"command": "node",
"args": [
"/path/to/mcp/cli.js"
],
"env": {
"ANCHOR_API_KEY": "sk-your-api-key-here"
}
}
}
}
```
### 4. Restart Your MCP Client
After updating the configuration, restart your MCP client (Cursor, VS Code, etc.) to load the new server.
## Configuration Options
The Anchor MCP server supports essential configuration options:
```bash
node cli.js --help
```
### Available Options:
* `--host ` - Host to bind server to (default: localhost, use 0.0.0.0 for all interfaces)
* `--port ` - Port to listen on for HTTP transport (Docker/server mode)
### Example with Options:
```json
{
"mcpServers": {
"anchor-browser": {
"command": "node",
"args": [
"/path/to/mcp/cli.js"
],
"env": {
"ANCHOR_API_KEY": "sk-your-api-key-here"
}
}
}
}
```
## How It Works
1. **Browser Session Creation**: When you use browser tools, the MCP server calls Anchor's API to create a remote browser session
2. **Remote Connection**: Connects to the remote browser via WebSocket using Chrome DevTools Protocol (CDP)
3. **Tool Execution**: All browser automation happens in Anchor's cloud infrastructure
4. **Proxy & Stealth**: Automatic residential proxy rotation and advanced anti-detection features
5. **Session Management**: Each session is isolated and can be viewed live via Anchor's dashboard
## Production & CI/CD Usage
### Self-Hosted in Production
The open source MCP server can be deployed in production environments:
* **Docker Containers** - Run in containerized environments
* **CI/CD Pipelines** - Integrate with Jenkins, GitHub Actions, GitLab CI
* **Serverless Functions** - Deploy as microservices or serverless functions
* **Kubernetes** - Scale horizontally in Kubernetes clusters
### CI/CD Integration Example
```yaml
# GitHub Actions with self-hosted MCP
name: E2E Testing
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
anchor-mcp:
image: your-registry/anchor-mcp:latest
env:
ANCHOR_API_KEY: ${{ secrets.ANCHOR_API_KEY }}
ports:
- 8931:8931
steps:
- uses: actions/checkout@v3
- name: Run AI tests against MCP server
run: |
python ai_test_runner.py --mcp-url http://localhost:8931/mcp
```
## Benefits Over Local Browsers
### 🌐 **Global Proxy Network**
* Automatic residential proxy rotation
* Geo-targeting for different regions
* No proxy configuration needed
### 🛡️ **Advanced Stealth**
* Browser fingerprinting protection
* Anti-bot detection bypass
* Real browser environments
### ☁️ **Cloud Infrastructure**
* No local browser dependencies
* Consistent browser versions
* Scalable execution
### 📊 **Monitoring & Debugging**
* Live view of browser sessions
* Session recordings and traces
* Network request logging
# MFA
Source: https://docs.anchorbrowser.io/advanced/mfa
Real-time event signaling and coordination between external systems and browser instances
# Event Coordination
Event coordination allows you to send real-time messages between external systems and active browser instances. This is particularly useful for **multi-factor authentication (MFA)** where you need to inject authentication codes during browser 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.
## API Endpoints
### Signal an Event
```http
POST https://api.anchorbrowser.io/api/v1/events/{eventName}
```
### Wait for an Event
```http
POST https://api.anchorbrowser.io/api/v1/events/{eventName}/wait
```
Both endpoints require `anchor-api-key` header and accept JSON payloads.
## MFA Use Case
Handle MFA codes during automated login flows:
```javascript
// 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
// In your external system (mobile app, webhook, etc.)
async function sendMFACode(code) {
await signalEvent('mfa_code', { code });
}
```
## Implementation
### JavaScript Helper Functions
```javascript
const apiKey = 'your-api-key';
const apiBase = 'https://api.anchorbrowser.io';
async function signalEvent(eventName, data) {
const response = await fetch(`${apiBase}/api/v1/events/${eventName}`, {
method: 'POST',
headers: {
'anchor-api-key': apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({ data: data || {} }),
});
if (!response.ok) throw new Error(`Failed to signal event: ${response.status}`);
return await response.json();
}
async function waitForEvent(eventName, timeoutMs = 60000) {
const response = await fetch(`${apiBase}/api/v1/events/${eventName}/wait`, {
method: 'POST',
headers: {
'anchor-api-key': apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({ timeoutMs }),
});
if (response.status === 408) return null; // Timeout
if (!response.ok) throw new Error(`Failed to wait for event: ${response.status}`);
return await response.json();
}
```
## Event Flow Patterns
**Signal First, Wait Later** (immediate consumption):
```javascript
await signalEvent("data", { value: "preloaded" });
const data = await waitForEvent("data", 1000); // Short timeout
```
**Wait First, Signal Later** (typical MFA flow):
```javascript
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
```javascript
const mfaEvent = await waitForEvent('mfa_code', 30000);
if (mfaEvent?.data?.code && /^\d{6}$/.test(mfaEvent.data.code)) {
// Use validated MFA code
} else {
throw new Error('Invalid or missing MFA code');
}
```
# OS-Level Control
Source: https://docs.anchorbrowser.io/advanced/os-level-control
Direct operating system control for precise browser automation and AI agent interactions
# OS-Level Control
OS-level control provides direct access to operating system primitives like mouse movements, keyboard input, and screen interactions within your browser sessions. This approach offers more precise control than traditional web automation methods and is particularly powerful when combined with AI agents and vision-based models.
## Why OS-Level Control?
### Superior AI Agent Performance
**Vision-based AI models perform significantly better** when they can interact with the browser using the same primitives humans use:
* **Keyboard shortcuts work naturally**: `Ctrl+F` for searching, `Ctrl+L` for browser navbar interaction, `Ctrl+T` for new tabs
* **OS-level UI elements**: Dropdowns, context menus, and system dialogs that aren't part of the webpage DOM
* **Visual coordinate targeting**: AI agents can directly click on elements they see in screenshots
### Beyond Traditional Web Automation
## Core Capabilities
### Mouse Operations
Control mouse interactions with pixel-level precision:
```javascript Basic Click
// Single click at coordinates
const response = await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/mouse/click`, {
x: 400,
y: 300,
button: 'left' // 'left', 'middle', 'right'
}, {
headers: {
'anchor-api-key': 'your-api-key',
'Content-Type': 'application/json'
}
});
```
```javascript Advanced Mouse Control
// Double-click for text selection
await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/mouse/doubleClick`, {
x: 500,
y: 200
}, {
headers: {
'anchor-api-key': 'your-api-key',
'Content-Type': 'application/json'
}
});
// Mouse down and up for custom gestures
await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/mouse/down`, {
x: 100,
y: 100,
button: 'left'
}, {
headers: {
'anchor-api-key': 'your-api-key',
'Content-Type': 'application/json'
}
});
// Move while holding down (drag)
await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/mouse/move`, {
x: 300,
y: 300
}, {
headers: {
'anchor-api-key': 'your-api-key',
'Content-Type': 'application/json'
}
});
// Release
await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/mouse/up`, {
x: 300,
y: 300
}, {
headers: {
'anchor-api-key': 'your-api-key',
'Content-Type': 'application/json'
}
});
```
### Drag and Drop
Perform complex drag and drop operations in a single command:
```javascript
// Drag file from desktop to upload area
const response = await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/drag-and-drop`, {
startX: 200,
startY: 150,
endX: 600,
endY: 400,
button: 'left'
}, {
headers: {
'anchor-api-key': 'your-api-key',
'Content-Type': 'application/json'
}
});
```
### Keyboard Input
Send text and keyboard shortcuts with human-like timing:
```javascript Text Input
// Type text with optional delay between keystrokes
const response = await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/keyboard/type`, {
text: "Hello, world!",
delay: 50 // milliseconds between keystrokes
}, {
headers: {
'anchor-api-key': 'your-api-key',
'Content-Type': 'application/json'
}
});
```
```javascript Keyboard Shortcuts
// Execute keyboard shortcuts
const response = await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/keyboard/shortcut`, {
keys: ['Ctrl', 'a'], // Select all
holdTime: 100 // Hold keys for 100ms
}, {
headers: {
'anchor-api-key': 'your-api-key',
'Content-Type': 'application/json'
}
});
// Common shortcuts
const shortcuts = {
selectAll: ['Ctrl', 'a'],
copy: ['Ctrl', 'c'],
paste: ['Ctrl', 'v'],
undo: ['Ctrl', 'z'],
newTab: ['Ctrl', 't'],
closeTab: ['Ctrl', 'w'],
focusAddressBar: ['Ctrl', 'l']
};
```
### Scrolling
Control page scrolling with precision:
```javascript
// Scroll at specific coordinates
const response = await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/scroll`, {
x: 400, // Where to perform scroll (cursor position)
y: 300, // Where to perform scroll (cursor position)
deltaX: 0, // Horizontal scroll amount (does not correlate with pixels)
deltaY: 200, // Vertical scroll amount (does not correlate with pixels, positive = down)
steps: 5 // Number of steps for smooth scrolling
}, {
headers: {
'anchor-api-key': 'your-api-key',
'Content-Type': 'application/json'
}
});
```
### Screenshots
Capture visual state for AI analysis:
```javascript
// Take screenshot of current browser state
const response = await axios.get(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/screenshot`, {
headers: {
'anchor-api-key': 'your-api-key'
},
responseType: 'arraybuffer'
});
const imageBuffer = response.data;
// Process screenshot with vision AI model
```
### Clipboard Operations
Manage clipboard content programmatically:
```javascript Reading Clipboard
// Get current clipboard content
const response = await axios.get(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/clipboard`, {
headers: {
'anchor-api-key': 'your-api-key'
}
});
const { data } = response.data;
console.log('Clipboard content:', data.text);
```
```javascript Setting Clipboard
// Set clipboard content
await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/clipboard`, {
text: "Content to copy"
}, {
headers: {
'anchor-api-key': 'your-api-key',
'Content-Type': 'application/json'
}
});
// Trigger copy operation (copies selected text)
const copyResponse = await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/copy`, {}, {
headers: {
'anchor-api-key': 'your-api-key'
}
});
// Trigger paste operation
await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/paste`, {
text: "Text to paste"
}, {
headers: {
'anchor-api-key': 'your-api-key',
'Content-Type': 'application/json'
}
});
```
### Navigation
Direct URL navigation at the OS level on the currently selected tab:
```javascript
// Navigate to a specific URL (completely OS-level, operates on selected tab)
const response = await axios.post(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/goto`, {
url: "https://example.com"
}, {
headers: {
'anchor-api-key': 'your-api-key',
'Content-Type': 'application/json'
}
});
```
## AI Agent Integration Patterns
### OpenAI Computer Use Integration
Anchor includes an integrated **OpenAI Computer Use agent** that leverages OS-level control for enhanced AI interactions. This agent can perform complex tasks by combining vision models with precise OS-level operations.
```python
class AnchorBrowser(BasePlaywrightComputer):
"""
Computer implementation for Anchor browser (https://anchorbrowser.io)
Uses OS-level control endpoints for browser automation within the container.
IMPORTANT: The `goto` and navigation tools are already implemented and recommended
when using the Anchor computer to help the agent navigate more effectively.
"""
def __init__(self, width: int = 1024, height: int = 900, session_id: str = None):
"""Initialize the Anchor browser session"""
super().__init__()
self.dimensions = (width, height)
self.session_id = session_id
self.base_url = "http://localhost:8484/api/os-control"
def screenshot(self) -> str:
"""
Capture a screenshot using OS-level control API.
Returns:
str: A base64 encoded string of the screenshot for AI model consumption.
"""
try:
response = requests.get(f"{self.base_url}/screenshot")
if not response.ok:
print(f"OS-level screenshot failed, falling back to standard screenshot")
return super().screenshot()
# OS-level API returns binary PNG data, encoded for AI models
return base64.b64encode(response.content).decode('utf-8')
except Exception as error:
print(f"OS-level screenshot failed, falling back: {error}")
return super().screenshot()
def click(self, x: int, y: int, button: str = "left") -> None:
"""
Click at the specified coordinates using OS-level control.
Args:
x: The x-coordinate to click.
y: The y-coordinate to click.
button: The mouse button to use ('left', 'right').
"""
try:
response = requests.post(
f"{self.base_url}/mouse/click",
json={"x": x, "y": y, "button": button}
)
if not response.ok:
print(f"OS-level click failed, falling back to standard click")
super().click(x, y, button)
except Exception as error:
print(f"OS-level click failed, falling back: {error}")
super().click(x, y, button)
def type(self, text: str) -> None:
"""
Type text using OS-level control with realistic delays.
"""
try:
response = requests.post(
f"{self.base_url}/keyboard/type",
json={"text": text, "delay": 30}
)
if not response.ok:
print(f"OS-level type failed, falling back to standard type")
super().type(text)
except Exception as error:
print(f"OS-level type failed, falling back: {error}")
super().type(text)
def keypress(self, keys: List[str]) -> None:
"""
Press keyboard shortcut using OS-level control.
Args:
keys: List of keys to press simultaneously (e.g., ['Ctrl', 'c']).
"""
try:
response = requests.post(
f"{self.base_url}/keyboard/shortcut",
json={"keys": keys, "holdTime": 100}
)
if not response.ok:
print(f"OS-level keyboard shortcut failed, falling back")
# Fallback to standard implementation
for key in keys:
self._page.keyboard.down(key)
for key in reversed(keys):
self._page.keyboard.up(key)
except Exception as error:
print(f"OS-level keyboard shortcut failed: {error}")
```
### Usage with OpenAI Models
The integrated computer use agent works seamlessly with OpenAI's vision models:
```python
# Initialize the agent with your session
agent = AnchorBrowser(width=1440, height=900, session_id="your-session-id")
# The agent can now:
# 1. Take screenshots for AI analysis
screenshot = agent.screenshot()
# 2. Perform precise clicks based on AI vision
agent.click(x=400, y=300)
# 3. Type text naturally
agent.type("Hello from AI agent!")
# 4. Execute keyboard shortcuts
agent.keypress(['Ctrl', 'l']) # Focus address bar
agent.keypress(['Ctrl', 'f']) # Open search
```
The computer use integration provides **automatic fallbacks** to standard browser automation if OS-level operations aren't available, ensuring reliability across different environments.
## Limitations and Considerations
### Session Requirements
* **Headful Sessions Only**: OS-level control requires a visible desktop environment
* **Performance Impact**: Screenshots and precise positioning may be slower than DOM-based automation
***
OS-level control opens up powerful possibilities for AI-driven browser automation, enabling more natural and effective interactions that mirror human behavior while providing the precision needed for reliable automation workflows.
# P2P Download
Source: https://docs.anchorbrowser.io/advanced/p2p-downloads
Capture files directly in the browser without cloud storage
## What is P2P Download?
P2P (Peer-to-Peer) downloads capture files directly in the browser memory without ever uploading them to cloud storage. When a user downloads a file in your browser session, instead of the file going to Anchor's servers, it's intercepted and made available to you immediately through browser hooks.
## How It Works
Traditional downloads follow this path:
* User clicks download → File goes to browser → File uploads to Anchor's servers → You fetch from Anchor's servers
P2P downloads work differently:
* User clicks download → File captured in browser memory → You fetch from the browser
The browser intercept download events, allowing you to extract the file data directly without any cloud storage involved.
## Implementation Example
```tsx node.js
import { promises as fs, existsSync } from "node:fs";
import { chromium } from "playwright";
const { ANCHOR_API_KEY } = process.env;
/**
* Save a download to disk.
* Handles three possible formats:
* 1. Playwright Download object
* 2. Base‑64 string
* 3. Fallback text scraped from the page
*/
async function saveDownload(download, filePath, page) {
// 1. Playwright Download object
if (download && typeof download.path === "function") {
try {
const tmpPath = await download.path();
if (tmpPath && existsSync(tmpPath)) {
await download.saveAs(filePath);
return filePath;
}
} catch {
/* ignore and fall through */
}
}
// 2. Raw base64 string
if (typeof download === "string") {
try {
await fs.writeFile(filePath, Buffer.from(download, "base64"));
return filePath;
} catch {
/* ignore and fall through */
}
}
// 3. Fallback – ask the page for data or capture visible text
if (page) {
try {
const blob = await page.evaluate(() => window._anchorExtractDownloadData());
return saveDownload(blob, filePath);
} catch {
/* ignore and fall through */
}
const fallbackText = await page.evaluate(() => {
const el = document.querySelector("main") || document.body;
return el.innerText || "";
});
await fs.writeFile(filePath, fallbackText, "utf8");
return filePath;
}
throw new Error("Failed to save download");
}
const downloadHandler = (filePath) => async (page, info) => {
if (info?.value) {
try {
return await saveDownload(info.value, filePath);
} catch {
/* ignore and fall through */
}
}
return saveDownload(null, filePath, page);
};
async function createSession() {
const res = await fetch("https://api.anchorbrowser.io/v1/sessions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"anchor-api-key": ANCHOR_API_KEY,
},
body: JSON.stringify({ browser: { p2p_download: { active: true } } }),
});
if (!res.ok) throw new Error(`Anchor API error ${res.status}: ${await res.text()}`);
const { data } = await res.json();
return data;
}
(async () => {
const session = await createSession();
if (!session?.cdp_url) throw new Error("No CDP URL in session");
const browser = await chromium.connectOverCDP(session.cdp_url);
const context = browser.contexts()[0];
const page = context.pages()[0];
await page.goto("https://v0-download-and-upload-text.vercel.app/");
await page.waitForSelector("button");
const [download] = await Promise.all([
page.waitForEvent("download", { timeout: 5000 }),
page.click("button"),
page.waitForTimeout(500), // allow JS to finish
]);
const filename = download.suggestedFilename();
await downloadHandler(filename)(page, { value: download });
const content = await fs.readFile(filename, "utf8");
console.log(`Downloaded '${filename}', content:\n${content}`);
await browser.close();
})();
```
```python python
import os, base64, json, requests
from playwright.sync_api import sync_playwright
ANCHOR_API_KEY = os.getenv("ANCHOR_API_KEY")
def save_download(src, path, page=None):
"""Persist a Playwright Download object or base‑64 string to *path*.
Falls back to blob extraction or page text when needed.
"""
if hasattr(src, "path"):
try:
tmp = src.path()
if tmp and os.path.exists(tmp):
src.save_as(path)
return path
except Exception:
pass
if isinstance(src, str):
try:
with open(path, "wb") as f:
f.write(base64.b64decode(src))
return path
except Exception:
pass
if page:
try:
blob = page.evaluate("() => window._anchorExtractDownloadData()")
return save_download(blob, path)
except Exception:
# As a last resort, dump visible page text
text = page.evaluate(
"() => (document.querySelector('main')||document.body).innerText"
)
with open(path, "w") as f:
f.write(text)
return path
raise RuntimeError("Failed to save download")
def download_handler(path):
"""Return a function (page, download_info) that writes to *path*."""
def _handle(page, info=None):
if info and hasattr(info, "value"):
try:
return save_download(info.value, path)
except Exception:
pass
# Fallback to blob extraction
return save_download(None, path, page)
return _handle
def create_session():
resp = requests.post(
"https://api.anchorbrowser.io/v1/sessions",
headers={
"Content-Type": "application/json",
"anchor-api-key": ANCHOR_API_KEY,
},
json={
"browser": {
"p2p_download": {
"active": True
}
}
}
)
if resp.status_code != 200:
raise Exception(f"Anchor API error {resp.status_code}: {resp.text}")
return resp.json().get("data")
with sync_playwright() as p:
session = create_session()
if not session or "cdp_url" not in session:
print("Could not obtain a valid browser session – exiting.")
raise SystemExit(1)
browser = p.chromium.connect_over_cdp(session["cdp_url"])
page = browser.contexts[0].pages[0]
page.goto("https://v0-download-and-upload-text.vercel.app/")
page.wait_for_selector("button", state="visible")
with page.expect_download(timeout=5000) as dl:
page.click("button")
page.wait_for_timeout(500) # allow JS to finish
filename = dl.value.suggested_filename
handler = download_handler(filename)
handler(page, dl)
with open(filename) as f:
snippet = f.read()
print(f"Downloaded '{filename}', content:\n{snippet}")
```
# Proxy
Source: https://docs.anchorbrowser.io/advanced/proxy
Anchor provides 4 types of proxy configurations:
* [Anchor Residential Proxy](/advanced/proxy#use-anchor-residential-proxy) - anchor\_residential
* [Anchor Mobile Proxy](/advanced/proxy#use-anchor-mobile-proxy) - anchor\_mobile
* [Anchor Gov Proxy](/advanced/proxy#use-anchor-gov-proxy) - anchor\_gov
* [Custom Proxy](/advanced/proxy#use-a-custom-proxy) - custom
To experiment with different proxy types, visit our [Interactive API Reference](/api-reference/browser-sessions/start-browser-session)
### Use Anchor Residential Proxy
Create your session with a residential proxy to access websites as if you're browsing from a computer in that country.
```bash curl
curl --request POST \
--url https://api.anchorbrowser.io/v1/sessions \
--header 'Content-Type: application/json' \
--header 'anchor-api-key: ' \
--data '{
"session": {
"proxy": {
"type": "anchor_residential",
"country_code": "us",
"active": true
}
}
}'
```
```javascript node.js
const axios = require('axios');
(async () => {
const response = await axios.post('https://api.anchorbrowser.io/v1/sessions', {
session: {
proxy: {
type: 'anchor_residential',
country_code: 'us',
active: true
}
}
}, {
headers: {
'anchor-api-key': process.env.ANCHOR_API_KEY,
'Content-Type': 'application/json'
}
});
console.log('Session created:', response.data);
})().catch(console.error);
```
```python python
import os
import requests
import json
ANCHOR_API_KEY = os.getenv('ANCHOR_API_KEY')
response = requests.post(
'https://api.anchorbrowser.io/v1/sessions',
json={
'session': {
'proxy': {
'type': 'anchor_residential',
'country_code': 'us',
'active': True
}
}
},
headers={
'anchor-api-key': ANCHOR_API_KEY,
'Content-Type': 'application/json'
}
)
response.raise_for_status()
print('Session created:')
print(json.dumps(response.json()['data'], indent=2))
```
### Use Anchor Mobile Proxy
Create your session with a mobile proxy to access websites as if you're browsing from a mobile device in that country.
```bash curl
curl --request POST \
--url https://api.anchorbrowser.io/v1/sessions \
--header 'Content-Type: application/json' \
--header 'anchor-api-key: ' \
--data '{
"session": {
"proxy": {
"type": "anchor_mobile",
"country_code": "us",
"active": true
}
}
}'
```
```javascript node.js
const axios = require('axios');
(async () => {
const response = await axios.post('https://api.anchorbrowser.io/v1/sessions', {
session: {
proxy: {
type: 'anchor_mobile',
country_code: 'us',
active: true
}
}
}, {
headers: {
'anchor-api-key': process.env.ANCHOR_API_KEY,
'Content-Type': 'application/json'
}
});
console.log('Session created:', response.data);
})().catch(console.error);
```
```python python
import os
import requests
import json
ANCHOR_API_KEY = os.getenv('ANCHOR_API_KEY')
response = requests.post(
'https://api.anchorbrowser.io/v1/sessions',
json={
'session': {
'proxy': {
'type': 'anchor_mobile',
'country_code': 'us',
'active': True
}
}
},
headers={
'anchor-api-key': ANCHOR_API_KEY,
'Content-Type': 'application/json'
}
)
response.raise_for_status()
print('Session created:')
print(json.dumps(response.json()['data'], indent=2))
```
### Use Anchor Gov Proxy
Create your session with a residential proxy to access websites as if you're browsing from a computer in that country. This option reduces the chance of being blocked by governmental websites.
```bash curl
curl --request POST \
--url https://api.anchorbrowser.io/v1/sessions \
--header 'Content-Type: application/json' \
--header 'anchor-api-key: ' \
--data '{
"session": {
"proxy": {
"type": "anchor_gov",
"country_code": "us",
"active": true
}
}
}'
```
```javascript node.js
const axios = require('axios');
(async () => {
const response = await axios.post('https://api.anchorbrowser.io/v1/sessions', {
session: {
proxy: {
type: 'anchor_gov',
country_code: 'us',
active: true
}
}
}, {
headers: {
'anchor-api-key': process.env.ANCHOR_API_KEY,
'Content-Type': 'application/json'
}
});
console.log('Session created:', response.data);
})().catch(console.error);
```
```python python
import os
import requests
import json
ANCHOR_API_KEY = os.getenv('ANCHOR_API_KEY')
response = requests.post(
'https://api.anchorbrowser.io/v1/sessions',
json={
'session': {
'proxy': {
'type': 'anchor_gov',
'country_code': 'us',
'active': True
}
}
},
headers={
'anchor-api-key': ANCHOR_API_KEY,
'Content-Type': 'application/json'
}
)
response.raise_for_status()
print('Session created:')
print(json.dumps(response.json()['data'], indent=2))
```
### Use a Custom Proxy
```bash curl
curl --request POST \
--url https://api.anchorbrowser.io/v1/sessions \
--header 'Content-Type: application/json' \
--header 'anchor-api-key: ' \
--data '{
"session": {
"proxy": {
"type": "custom",
"server": "proxy.example.com",
"username": "myUser",
"password": "myPassword",
"active": true
}
}
}'
```
```javascript node.js
const axios = require('axios');
(async () => {
const response = await axios.post('https://api.anchorbrowser.io/v1/sessions', {
session: {
proxy: {
type: 'custom',
server: 'proxy.example.com',
username: 'myUser',
password: 'myPassword',
active: true
}
}
}, {
headers: {
'anchor-api-key': process.env.ANCHOR_API_KEY,
'Content-Type': 'application/json'
}
});
console.log('Session created:', response.data);
})().catch(console.error);
```
```python python
import os
import requests
import json
ANCHOR_API_KEY = os.getenv('ANCHOR_API_KEY')
response = requests.post(
'https://api.anchorbrowser.io/v1/sessions',
json={
'session': {
'proxy': {
'type': 'custom',
'server': 'proxy.example.com',
'username': 'myUser',
'password': 'myPassword',
'active': True
}
}
},
headers={
'anchor-api-key': ANCHOR_API_KEY,
'Content-Type': 'application/json'
}
)
response.raise_for_status()
print('Session created:')
print(json.dumps(response.json()['data'], indent=2))
```
## Localization
You can specify a country code for your proxy to route traffic through a specific geographic location. This is useful for accessing region-specific content or testing localized experiences.
The `country_code` parameter accepts the following country codes in lowercase:
### Supported Countries with their Country Codes
| | | | | | |
| ---------------------- | -- | ------------- | -- | ------------------------ | -- |
| Afghanistan | af | Gambia | gm | Oman | om |
| Albania | al | Georgia | ge | Pakistan | pk |
| Algeria | dz | Germany | de | Panama | pa |
| Andorra | ad | Ghana | gh | Papua New Guinea | pg |
| Angola | ao | Greece | gr | Paraguay | py |
| Antigua and Barbuda | ag | Grenada | gd | Peru | pe |
| Argentina | ar | Guatemala | gt | Philippines | ph |
| Armenia | am | Guinea | gn | Poland | pl |
| Aruba | aw | Guyana | gy | Portugal | pt |
| Australia | au | Haiti | ht | Puerto Rico | pr |
| Austria | at | Honduras | hn | Qatar | qa |
| Azerbaijan | az | Hong Kong | hk | Romania | ro |
| Bahamas | bs | Hungary | hu | Russia | ru |
| Bahrain | bh | Iceland | is | Rwanda | rw |
| Bangladesh | bd | India | in | Saint Lucia | lc |
| Barbados | bb | Indonesia | id | Samoa | ws |
| Belarus | by | Iran | ir | San Marino | sm |
| Belgium | be | Iraq | iq | Saudi Arabia | sa |
| Belize | bz | Ireland | ie | Senegal | sn |
| Benin | bj | Israel | il | Serbia | rs |
| Bermuda | bm | Italy | it | Sierra Leone | sl |
| Bolivia | bo | Jamaica | jm | Singapore | sg |
| Bosnia and Herzegovina | ba | Japan | jp | Slovakia | sk |
| Botswana | bw | Jordan | jo | Slovenia | si |
| Brazil | br | Kazakhstan | kz | Somalia | so |
| Brunei Darussalam | bn | Kenya | ke | South Africa | za |
| Bulgaria | bg | Kuwait | kw | South Korea | kr |
| Burkina Faso | bf | Kyrgyzstan | kg | South Sudan | ss |
| Burundi | bi | Laos | la | Spain | es |
| Cambodia | kh | Latvia | lv | Sri Lanka | lk |
| Cameroon | cm | Lebanon | lb | Sudan | sd |
| Canada | ca | Lesotho | ls | Suriname | sr |
| Cape Verde | cv | Liberia | lr | Sweden | se |
| Chad | td | Libya | ly | Switzerland | ch |
| Chile | cl | Lithuania | lt | Syria | sy |
| China | cn | Luxembourg | lu | São Tomé and Príncipe | st |
| Colombia | co | Macedonia | mk | Taiwan | tw |
| Congo | cg | Madagascar | mg | Tajikistan | tj |
| Costa Rica | cr | Malawi | mw | Tanzania | tz |
| Côte d’Ivoire | ci | Malaysia | my | Thailand | th |
| Croatia | hr | Maldives | mv | Timor Leste (East Timor) | tl |
| Cuba | cu | Mali | ml | Turkey | tr |
| Cyprus | cy | Malta | mt | Togo | tg |
| Czech Republic | cz | Mauritania | mr | Trinidad and Tobago | tt |
| Denmark | dk | Mexico | mx | Tunisia | tn |
| Djibouti | dj | Moldova | md | Turkmenistan | tm |
| Dominica | dm | Mongolia | mn | Uganda | ug |
| Dominican Republic | do | Montenegro | me | Ukraine | ua |
| Ecuador | ec | Morocco | ma | United Kingdom | gb |
| Egypt | eg | Mozambique | mz | United States | us |
| El Salvador | sv | Myanmar | mm | Uruguay | uy |
| Equatorial Guinea | gq | Namibia | na | Uzbekistan | uz |
| Estonia | ee | Nepal | np | Vanuatu | vu |
| Eswatini | sz | Netherlands | nl | Venezuela | ve |
| Ethiopia | et | New Caledonia | nc | Vietnam | vn |
| Fiji | fj | New Zealand | nz | Yemen | ye |
| Finland | fi | Nicaragua | ni | Zambia | zm |
| France | fr | Niger | ne | Zimbabwe | zw |
| French Polynesia | pf | Nigeria | ng | | |
| Gabon | ga | Norway | no | | |
| | | | | | |
| ---------------------- | -- | ------------- | -- | -------------------- | -- |
| Afghanistan | af | Georgia | ge | Nigeria | ng |
| Albania | al | Germany | de | Norway | no |
| Algeria | dz | Ghana | gh | Oman | om |
| Angola | ao | Greece | gr | Pakistan | pk |
| Antigua and Barbuda | ag | Guatemala | gt | Panama | pa |
| Argentina | ar | Guinea-Bissau | gw | Paraguay | py |
| Armenia | am | Guyana | gy | Peru | pe |
| Australia | au | Haiti | ht | Philippines | ph |
| Austria | at | Honduras | hn | Poland | pl |
| Azerbaijan | az | Hungary | hu | Portugal | pt |
| Bahamas | bs | Iceland | is | Qatar | qa |
| Bahrain | bh | India | in | Romania | ro |
| Bangladesh | bd | Indonesia | id | Russia | ru |
| Barbados | bb | Iraq | iq | Rwanda | rw |
| Belgium | be | Ireland | ie | Saudi Arabia | sa |
| Belize | bz | Israel | il | Senegal | sn |
| Benin | bj | Italy | it | Serbia | rs |
| Bhutan | bt | Jamaica | jm | Sierra Leone | sl |
| Bolivia | bo | Japan | jp | Singapore | sg |
| Bosnia and Herzegovina | ba | Jordan | jo | Slovakia | sk |
| Botswana | bw | Kazakhstan | kz | Slovenia | si |
| Brazil | br | Kenya | ke | South Africa | za |
| Bulgaria | bg | Kuwait | kw | South Korea | kr |
| Burkina Faso | bf | Kyrgyzstan | kg | Spain | es |
| Cambodia | kh | Laos | la | Sri Lanka | lk |
| Cameroon | cm | Latvia | lv | Sudan | sd |
| Canada | ca | Lebanon | lb | Sweden | se |
| Cape Verde | cv | Liberia | lr | Switzerland | ch |
| Chile | cl | Libya | ly | Syria | sy |
| China | cn | Lithuania | lt | Taiwan | tw |
| Colombia | co | Macedonia | mk | Tajikistan | tj |
| Congo | cg | Malawi | mw | Tanzania | tz |
| Côte d’Ivoire | ci | Malaysia | my | Thailand | th |
| Croatia | hr | Maldives | mv | Togo | tg |
| Cuba | cu | Mali | ml | Trinidad and Tob | |
| Cyprus | cy | Malta | mt | Tunisia | tn |
| Czech Republic | cz | Mauritius | mu | Turkey | tr |
| Denmark | dk | Mexico | mx | Uganda | ug |
| Dominican Republic | do | Moldova | md | Ukraine | ua |
| Ecuador | ec | Mongolia | mn | United Arab Emirates | ae |
| Egypt | eg | Montenegro | me | United Kingdom | gb |
| El Salvador | sv | Morocco | ma | United States | us |
| Estonia | ee | Mozambique | mz | Uruguay | uy |
| Ethiopia | et | Nepal | np | Uzbekistan | uz |
| Fiji | fj | Netherlands | nl | Venezuela | ve |
| Finland | fi | New Caledonia | nc | Vietnam | vn |
| France | fr | New Zealand | nz | Yemen | ye |
| Gabon | ga | Namibia | na | Zambia | zm |
| Gambia | gm | Nicaragua | ni | Zimbabwe | zw |
| | | | | | |
| ---------------------- | -- | ---------------- | -- | ------------------------ | -- |
| Afghanistan | af | France | fr | Netherlands | nl |
| Albania | al | French Guiana | gf | New Zealand | nz |
| Algeria | dz | French Polynesia | pf | Nicaragua | ni |
| Andorra | ad | Gabon | ga | Nigeria | ng |
| Angola | ao | Gambia | gm | Norway | no |
| American Samoa | as | Georgia | ge | Pakistan | pk |
| Antigua and Barbuda | ag | Germany | de | Panama | pa |
| Argentina | ar | Ghana | gh | Paraguay | py |
| Armenia | am | Gibraltar | gi | Peru | pe |
| Aruba | aw | Greece | gr | Philippines | ph |
| Australia | au | Grenada | gd | Poland | pl |
| Austria | at | Guadeloupe | gp | Portugal | pt |
| Azerbaijan | az | Guatemala | gt | Puerto Rico | pr |
| Bahamas | bs | Guernsey | gg | Qatar | qa |
| Bahrain | bh | Guinea | gn | Romania | ro |
| Barbados | bb | Guinea-Bissau | gw | Saint Lucia | lc |
| Belarus | by | Guyana | gy | San Marino | sm |
| Belgium | be | Haiti | ht | Saudi Arabia | sa |
| Belize | bz | Honduras | hn | Senegal | sn |
| Benin | bj | Hungary | hu | Serbia | rs |
| Bermuda | bm | Iceland | is | Seychelles | sc |
| Bolivia | bo | India | in | Sierra Leone | sl |
| Bosnia and Herzegovina | ba | Iran | ir | Slovakia | sk |
| Brazil | br | Iraq | iq | Slovenia | si |
| Bulgaria | bg | Ireland | ie | Somalia | so |
| Burkina Faso | bf | Israel | il | South Africa | za |
| Cameroon | cm | Italy | it | South Korea | kr |
| Canada | ca | Jamaica | jm | Spain | es |
| Cape Verde | cv | Japan | jp | Suriname | sr |
| Chad | td | Jordan | jo | Sweden | se |
| Chile | cl | Kazakhstan | kz | Switzerland | ch |
| Colombia | co | Kuwait | kw | Syria | sy |
| Congo | cg | Kyrgyzstan | kg | São Tomé and Príncipe | st |
| Costa Rica | cr | Latvia | lv | Taiwan | tw |
| Côte d’Ivoire | ci | Lebanon | lb | Tajikistan | tj |
| Croatia | hr | Libya | ly | Togo | tg |
| Cuba | cu | Liechtenstein | li | Trinidad and Tobago | tt |
| Cyprus | cy | Lithuania | lt | Tunisia | tn |
| Czech Republic | cz | Luxembourg | lu | Turkey | tr |
| Denmark | dk | Macedonia | mk | Turks and Caicos Islands | tc |
| Dominica | dm | Mali | ml | Ukraine | ua |
| Dominican Republic | do | Malta | mt | United Arab Emirates | ae |
| Ecuador | ec | Martinique | mq | United States | us |
| Egypt | eg | Mauritania | mr | Uruguay | uy |
| El Salvador | sv | Mexico | mx | Uzbekistan | uz |
| Estonia | ee | Moldova | md | Venezuela | ve |
| Ethiopia | et | Monaco | mc | Yemen | ye |
| Faroe Islands | fo | Montenegro | me | | |
| Finland | fi | Morocco | ma | | |
{/* # Gov Proxy
|Afghanistan|af|
|Albania|al|
|Algeria|dz|
|Andorra|ad|
|Angola|ao|
|American Samoa|as|
|Antigua and Barbuda|ag|
|Argentina|ar|
|Armenia|am|
|Aruba|aw|
|Australia|au|
|Austria|at|
|Azerbaijan|az|
|Bahamas|bs|
|Bahrain|bh|
|Barbados|bb|
|Belarus|by|
|Belgium|be|
|Belize|bz|
|Benin|bj|
|Bermuda|bm|
|Bolivia|bo|
|Bosnia and Herzegovina|ba|
|Brazil|br|
|Bulgaria|bg|
|Burkina Faso|bf|
|Cameroon|cm|
|Canada|ca|
|Cape Verde|cv|
|Chad|td|
|Chile|cl|
|Colombia|co|
|Congo|cg|
|Costa Rica|cr|
|Côte d’Ivoire|ci|
|Croatia|hr|
|Cuba|cu|
|Cyprus|cy|
|Czech Republic|cz|
|Denmark|dk|
|Dominica|dm|
|Dominican Republic|do|
|Ecuador|ec|
|Egypt|eg|
|El Salvador|sv|
|Estonia|ee|
|Ethiopia|et|
|Faroe Islands|fo|
|Finland|fi|
|France|fr|
|French Guiana|gf|
|French Polynesia|pf|
|Gabon|ga|
|Gambia|gm|
|Georgia|ge|
|Germany|de|
|Ghana|gh|
|Gibraltar|gi|
|Greece|gr|
|Grenada|gd|
|Guadeloupe|gp|
|Guatemala|gt|
|Guernsey|gg|
|Guinea|gn|
|Guinea-Bissau|gw|
|Guyana|gy|
|Haiti|ht|
|Honduras|hn|
|Hungary|hu|
|Iceland|is|
|India|in|
|Iran|ir|
|Iraq|iq|
|Ireland|ie|
|Israel|il|
|Italy|it|
|Jamaica|jm|
|Japan|jp|
|Jordan|jo|
|Kazakhstan|kz|
|Kuwait|kw|
|Kyrgyzstan|kg|
|Latvia|lv|
|Lebanon|lb|
|Libya|ly|
|Liechtenstein|li|
|Lithuania|lt|
|Luxembourg|lu|
|Macedonia|mk|
|Mali|ml|
|Malta|mt|
|Martinique|mq|
|Mauritania|mr|
|Mexico|mx|
|Moldova|md|
|Monaco|mc|
|Montenegro|me|
|Morocco|ma|
|Netherlands|nl|
|New Zealand|nz|
|Nicaragua|ni|
|Nigeria|ng|
|Norway|no|
|Pakistan|pk|
|Panama|pa|
|Paraguay|py|
|Peru|pe|
|Philippines|ph|
|Poland|pl|
|Portugal|pt|
|Puerto Rico|pr|
|Qatar|qa|
|Romania|ro|
|Saint Lucia|lc|
|San Marino|sm|
|Saudi Arabia|sa|
|Senegal|sn|
|Serbia|rs|
|Seychelles|sc|
|Sierra Leone|sl|
|Slovakia|sk|
|Slovenia|si|
|Somalia|so|
|South Africa|za|
|South Korea|kr|
|Spain|es|
|Suriname|sr|
|Sweden|se|
|Switzerland|ch|
|Syria|sy|
|São Tomé and Príncipe|st|
|Taiwan|tw|
|Tajikistan|tj|
|Togo|tg|
|Trinidad and Tobago|tt|
|Tunisia|tn|
|Turkey|tr|
|Turks and Caicos Islands|tc|
|Ukraine|ua|
|United Arab Emirates|ae|
|United States|us|
|Uruguay|uy|
|Uzbekistan|uz|
|Venezuela|ve|
|Yemen|ye| */}
{/*
#### Mobile Proxy
|Afghanistan|af|
|Albania|al|
|Algeria|dz|
|Angola|ao|
|Antigua and Barbuda|ag|
|Argentina|ar|
|Armenia|am|
|Australia|au|
|Austria|at|
|Azerbaijan|az|
|Bahamas|bs|
|Bahrain|bh|
|Bangladesh|bd|
|Barbados|bb|
|Belgium|be|
|Belize|bz|
|Benin|bj|
|Bhutan|bt|
|Bolivia|bo|
|Bosnia and Herzegovina|ba|
|Botswana|bw|
|Brazil|br|
|Bulgaria|bg|
|Burkina Faso|bf|
|Cambodia|kh|
|Cameroon|cm|
|Canada|ca|
|Cape Verde|cv|
|Chile|cl|
|China|cn|
|Colombia|co|
|Congo|cg|
|Côte d’Ivoire|ci|
|Croatia|hr|
|Cuba|cu|
|Cyprus|cy|
|Czech Republic|cz|
|Denmark|dk|
|Dominican Republic|do|
|Ecuador|ec|
|Egypt|eg|
|El Salvador|sv|
|Estonia|ee|
|Ethiopia|et|
|Fiji|fj|
|Finland|fi|
|France|fr|
|Gabon|ga|
|Gambia|gm|
|Georgia|ge|
|Germany|de|
|Ghana|gh|
|Greece|gr|
|Guatemala|gt|
|Guinea-Bissau|gw|
|Guyana|gy|
|Haiti|ht|
|Honduras|hn|
|Hungary|hu|
|Iceland|is|
|India|in|
|Indonesia|id|
|Iraq|iq|
|Ireland|ie|
|Israel|il|
|Italy|it|
|Jamaica|jm|
|Japan|jp|
|Jordan|jo|
|Kazakhstan|kz|
|Kenya|ke|
|Kuwait|kw|
|Kyrgyzstan|kg|
|Laos|la|
|Latvia|lv|
|Lebanon|lb|
|Liberia|lr|
|Libya|ly|
|Lithuania|lt|
|Macedonia|mk|
|Malawi|mw|
|Malaysia|my|
|Maldives|mv|
|Mali|ml|
|Malta|mt|
|Mauritius|mu|
|Mexico|mx|
|Moldova|md|
|Mongolia|mn|
|Montenegro|me|
|Morocco|ma|
|Mozambique|mz|
|Nepal|np|
|Netherlands|nl|
|New Caledonia|nc|
|New Zealand|nz|
|Namibia|na|
|Nicaragua|ni|
|Nigeria|ng|
|Norway|no|
|Oman|om|
|Pakistan|pk|
|Panama|pa|
|Paraguay|py|
|Peru|pe|
|Philippines|ph|
|Poland|pl|
|Portugal|pt|
|Qatar|qa|
|Romania|ro|
|Russia|ru|
|Rwanda|rw|
|Saudi Arabia|sa|
|Senegal|sn|
|Serbia|rs|
|Sierra Leone|sl|
|Singapore|sg|
|Slovakia|sk|
|Slovenia|si|
|South Africa|za|
|South Korea|kr|
|Spain|es|
|Sri Lanka|lk|
|Sudan|sd|
|Sweden|se|
|Switzerland|ch|
|Syria|sy|
|Taiwan|tw|
|Tajikistan|tj|
|Tanzania|tz|
|Thailand|th|
|Togo|tg|
|Trinidad and Tobago|tt|
|Tunisia|tn|
|Turkey|tr|
|Uganda|ug|
|Ukraine|ua|
|United Arab Emirates|ae|
|United Kingdom|gb|
|United States|us|
|Uruguay|uy|
|Uzbekistan|uz|
|Venezuela|ve|
|Vietnam|vn|
|Yemen|ye|
|Zambia|zm|
|Zimbabwe|zw|
#### Residential Proxy
|Afghanistan|af|
|Albania|al|
|Algeria|dz|
|Andorra|ad|
|Angola|ao|
|Antigua and
|Argentina|ar|
|Armenia|am|
|Aruba|aw|
|Australia|au|
|Austria|at|
|Azerbaijan|az|
|Bahamas|bs|
|Bahrain|bh|
|Bangladesh|bd|
|Barbados|bb|
|Belarus|by|
|Belgium|be|
|Belize|bz|
|Benin|bj|
|Bermuda|bm|
|Bolivia|bo|
|Bosnia and Herzegovina|ba|
|Botswana|bw|
|Brazil|br|
|Brunei Darussalam|bn|
|Bulgaria|bg|
|Burkina Faso|bf|
|Burundi|bi|
|Cambodia|kh|
|Cameroon|cm|
|Canada|ca|
|Cape Verde|cv|
|Chad|td|
|Chile|cl|
|China|cn|
|Colombia|co|
|Congo|cg|
|Costa Rica|cr|
|Côte d’Ivoire|ci|
|Croatia|hr|
|Cuba|cu|
|Cyprus|cy|
|Czech Republic|cz|
|Denmark|dk|
|Djibouti|dj|
|Dominica|dm|
|Dominican Republic|do|
|Ecuador|ec|
|Egypt|eg|
|El Salvador|sv|
|Equatorial Guinea|gq|
|Estonia|ee|
|Eswatini|sz|
|Ethiopia|et|
|Fiji|fj|
|Finland|fi|
|France|fr|
|French Polynesia|pf|
|Gabon|ga|
|Gambia|gm|
|Georgia|ge|
|Germany|de|
|Ghana|gh|
|Greece|gr|
|Grenada|gd|
|Guatemala|gt|
|Guinea|gn|
|Guyana|gy|
|Haiti|ht|
|Honduras|hn|
|Hong Kong|hk|
|Hungary|hu|
|Iceland|is|
|India|in|
|Indonesia|id|
|Iran|ir|
|Iraq|iq|
|Ireland|ie|
|Israel|il|
|Italy|it|
|Jamaica|jm|
|Japan|jp|
|Jordan|jo|
|Kazakhstan|kz|
|Kenya|ke|
|Kuwait|kw|
|Kyrgyzstan|kg|
|Laos|la|
|Latvia|lv|
|Lebanon|lb|
|Lesotho|ls|
|Liberia|lr|
|Libya|ly|
|Lithuania|lt|
|Luxembourg|lu|
|Macedonia|mk|
|Madagascar|mg|
|Malawi|mw|
|Malaysia|my|
|Maldives|mv|
|Mali|ml|
|Malta|mt|
|Mauritania|mr|
|Mexico|mx|
|Moldova|md|
|Mongolia|mn|
|Montenegro|me|
|Morocco|ma|
|Mozambique|mz|
|Myanmar|mm|
|Namibia|na|
|Nepal|np|
|Netherlands|nl|
|New Caledonia|nc|
|New Zealand|nz|
|Nicaragua|ni|
|Niger|ne|
|Nigeria|ng|
|Norway|no|
|Oman|om|
|Pakistan|pk|
|Panama|pa|
|Papua New Guinea|pg|
|Paraguay|py|
|Peru|pe|
|Philippines|ph|
|Poland|pl|
|Portugal|pt|
|Puerto Rico|pr|
|Qatar|qa|
|Romania|ro|
|Russia|ru|
|Rwanda|rw|
|Saint Lucia|lc|
|Samoa|ws|
|San Marino|sm|
|Saudi Arabia|sa|
|Senegal|sn|
|Serbia|rs|
|Sierra Leone|sl|
|Singapore|sg|
|Slovakia|sk|
|Slovenia|si|
|Somalia|so|
|South Africa|za|
|South Korea|kr|
|South Sudan|ss|
|Spain|es|
|Sri Lanka|lk|
|Sudan|sd|
|Suriname|sr|
|Sweden|se|
|Switzerland|ch|
|Syria|sy|
|São Tomé and Príncipe|st|
|Taiwan|tw|
|Tajikistan|tj|
|Tanzania|tz|
|Thailand|th|
|Timor Leste (East Timor)|tl|
|Turkey|tr|
|Togo|tg|
|Trinidad and Tobago|tt|
|Tunisia|tn|
|Turkmenistan|tm|
|Uganda|ug|
|Ukraine|ua|
|United Kingdom|gb|
|United States|us|
|Uruguay|uy|
|Uzbekistan|uz|
|Vanuatu|vu|
|Venezuela|ve|
|Vietnam|vn|
|Yemen|ye|
|Zambia|zm|
|Zimbabwe|zw| */}
# Session Timeout
Source: https://docs.anchorbrowser.io/advanced/session-timeout
### Managing Browser Session Lifetime
Anchor provides multiple ways to control and terminate browser sessions. In addition to manually stopping sessions via the [stop session API](/api-reference/browser-sessions/end-browser-session), you can configure two types of automatic timeout mechanisms to manage session lifetime effectively.
For the full list of available options, view the [interactive api documentation](/api-reference/browser-sessions).
### Timeout Configuration Options
The API offers two distinct timeout parameters through the `session.timeout` object to automatically manage browser session termination.
#### Idle Timeout
The `idle_timeout` parameter automatically terminates sessions after a period of inactivity. This timer starts after the last connection to the browser has disconnected, and any new connection will restart the timer. This includes live view sessions, CDP (Chrome DevTools Protocol) connections, and OS-level control connections.
The idle timeout is particularly useful for sessions with unknown length, allowing users to interact with browsers for as long as they need without keeping stale browsers alive unnecessarily. When set to `3` minutes for example, the session will terminate after 3 minutes with no active connections. The default value is `5` minutes, and you can disable automatic termination for idle sessions by setting it to `-1`.
#### Maximum Duration
The `max_duration` parameter sets a hard limit on total session lifetime. Unlike the idle timeout, this will automatically terminate the session after the specified duration regardless of activity level. This acts as a safety mechanism to ensure sessions don't run indefinitely.
The default maximum duration is `180` minutes (3 hours), but you can adjust this based on your needs. Setting `max_duration` to `10` will terminate the session after exactly 10 minutes, whether the browser is actively being used or not. There is no upper limit on how long you can set the maximum duration.
### Implementation Example
```bash
curl --request POST \
--url https://api.anchorbrowser.io/v1/sessions \
--header 'Content-Type: application/json' \
--header 'anchor-api-key: your_api_key_here' \
--data '{
"session": {
"timeout": {
"max_duration": 10,
"idle_timeout": 3
}
}
}'
```
In this example, replace `"your_api_key_here"` with your actual API key. The configuration sets a 10-minute hard session limit with `max_duration`, while `idle_timeout` ensures the session terminates after 3 minutes of no active connections. These two timeout mechanisms work independently, so the session will end when whichever condition is met first.
# CrewAI
Source: https://docs.anchorbrowser.io/agent-frameworks/crewai
AI agents can leverage browser sessions to complete tasks in the web. The ways to use the browser in CrewAI agent platform are:
* **As a Flexible Browser Tool**: Enable the CrewAI agent to explore the web freely using a general-purpose browser tool.
* **As a Specific-Flow Tool Defined in CrewAI**: Create custom tools by writing CrewAI code to define specific workflows tailored to your needs.
* **As a Specific-Flow Tool Defined in Anchor Browser**: Define tools using the Anchor platform, which CrewAI agents can then use through the Official Anchor Tool.
## Quick start - Use Anchor Browser as a flexible browser tool
You can connect your CrewAI agent directly to Anchor Browser, allowing it to use browser sessions for various tasks, leveraging the power of browser automation without the need for complex integration code. Below is a quick guide to setting up and using Anchor Browser as a tool for your CrewAI agent.
```python python
import crewai
from playwright.sync_api import sync_playwright
ANCHOR_API_KEY = "YOUR_ANCHOR_API_KEY" # Replace with your actual API key
# Register Anchor Browser as a tool in CrewAI
class AnchorBrowserTool(crewai.Tool):
name = "AnchorBrowser"
description = "Use Anchor Browser to perform web-based tasks."
def __init__(self):
super().__init__()
def run(self, command):
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(
f"wss://connect.anchorbrowser.io?apiKey={ANCHOR_API_KEY}"
)
page = browser.new_page()
page.goto(command['url'])
# Perform specific actions as needed
if command.get('action') == 'search':
page.fill(command['search_box'], command['search_text'])
page.click(command['search_button'])
# Extract and return data if needed
result = page.content()
browser.close()
return result
# Add AnchorBrowserTool to CrewAI agent
my_agent = crewai.Agent(name="Web Agent")
my_agent.add_tool(AnchorBrowserTool())
# Use the agent to perform actions on the web
result = my_agent.act({
'tool': 'AnchorBrowser',
'command': {
'url': 'https://example.com',
'action': 'search',
'search_box': 'input[name="q"]',
'search_text': 'Anchor Browser',
'search_button': 'button[type="submit"]'
}
})
print(result)
```
```jsx node.js
import crewai from 'crewai';
import { chromium } from 'playwright-core';
const ANCHOR_API_KEY = process.env.ANCHOR_API_KEY; // Replace with your actual API key stored in environment variables
// Define a custom tool in CrewAI that uses Anchor Browser
class AnchorBrowserTool {
name = "AnchorBrowser";
description = "Use Anchor Browser to perform web-based tasks.";
async run(command) {
// Connect to Anchor Browser session
const browser = await chromium.connectOverCDP(
`wss://connect.anchorbrowser.io?apiKey=${ANCHOR_API_KEY}`
);
const page = await browser.newPage();
await page.goto(command.url);
// Perform specific actions as needed
if (command.action === 'search') {
await page.fill(command.search_box, command.search_text);
await page.click(command.search_button);
}
// Extract and return data if needed
const result = await page.content();
await browser.close();
return result;
}
}
// Create a CrewAI agent a
```
## Use Anchor Browser as a specific-flow tool defined in CrewAI
CrewAI can integrate closely with Anchor Browser to define tools for particular workflows. For example, if you need a customized process to interact with an authenticated application, you can create that flow as a reusable tool that CrewAI agents can use for automation.
Here is an example of creating a specific workflow tool using Anchor Browser that can be utilized by CrewAI to automate targeted tasks.
```python python
import crewai
from playwright.sync_api import sync_playwright
ANCHOR_API_KEY = "YOUR_ANCHOR_API_KEY" # Replace with your actual API key
# Register Anchor Browser as a specific application tool in CrewAI
class AnchorSpecificTool(crewai.Tool):
name = "SpecificAnchorTool"
description = "Custom tool for interacting with a specific application."
def __init__(self):
super().__init__()
def run(self, command):
with sync_playwright() as p:
# Connect to Anchor Browser session
browser = p.chromium.connect_over_cdp(
f"wss://connect.anchorbrowser.io?apiKey={ANCHOR_API_KEY}"
)
page = browser.new_page()
page.goto(command['url'])
# Perform specific actions based on command
if command.get('action') == 'extract':
result = page.text_content(command['selector'])
browser.close()
return result
browser.close()
# Add custom AnchorBrowserTool to CrewAI agent
my_agent = crewai.Agent(name="Web Automation Agent")
my_agent.add_tool(AnchorSpecificTool())
# Use the agent to perform a specific task
result = my_agent.act({
'tool': 'SpecificAnchorTool',
'command': {
'url': 'https://example.com',
'action': 'extract',
'selector': '#data'
}
})
print(result)
```
```jsx node.js
import crewai from 'crewai';
import { chromium } from 'playwright-core';
const ANCHOR_API_KEY = process.env.ANCHOR_API_KEY; // Replace with your actual API key stored in environment variables
// Define a custom specific-flow tool in CrewAI that uses Anchor Browser
class AnchorSpecificTool {
name = "SpecificAnchorTool";
description = "Custom tool for interacting with a specific application.";
async run(command) {
// Connect to Anchor Browser session
const browser = await chromium.connectOverCDP(
`wss://connect.anchorbrowser.io?apiKey=${ANCHOR_API_KEY}`
);
const page = await browser.newPage();
await page.goto(command.url);
// Perform specific actions based on the command
if (command.action === 'extract') {
const result = await page.textContent(command.selector);
await browser.close();
return result;
}
await browser.close();
}
}
// Create a CrewAI agent and add the custom specific-flow Anchor Browser tool
const agent = new crewai.Agent({ name: "Web Automation Agent" });
const anchorSpecificTool = new AnchorSpecificTool();
agent.addTool(anchorSpecificTool);
// Use the tool through the CrewAI agent
const result = await agent.act({
tool: 'SpecificAnchorTool',
command: {
url: 'https://example.com',
action: 'extract',
selector: '#data'
}
});
console.log(result);
```
# Custom Integration
Source: https://docs.anchorbrowser.io/agent-frameworks/custom-agent-framework
Anchor Browser enables integration with custom AI frameworks to empower agents with the ability to navigate and interact with the web effectively. You can leverage browser sessions within your own custom AI framework to automate workflows, explore the web, or interact with web content dynamically.
The integration methods for a custom AI framework include:
* **As a Flexible Browser Tool**: Utilize Anchor Browser as a general-purpose browser tool that allows your AI agent to freely explore the web and perform dynamic interactions.
* **As a Specific-Flow Tool Defined in Your Custom Framework**: Create reusable, custom tools in your AI framework to handle specific workflows or sequences of interactions.
* **As a Specific-Flow Tool Defined in Anchor Browser**: Define tools on the Anchor platform and invoke them using your custom AI framework through the Anchor API, allowing your agent to use predefined browser sessions and tools.
## Quick Start - Use Anchor Browser as a Flexible Browser Tool
Your custom AI framework can directly integrate with Anchor Browser, allowing your agent to interact with the web dynamically. Below is an example of how you can connect your custom AI framework to Anchor Browser, enabling the agent to perform various tasks.
```python python
import requests
from playwright.sync_api import sync_playwright
ANCHOR_API_KEY = "YOUR_ANCHOR_API_KEY" # Replace with your actual API key
# Define a function to use Anchor Browser as a tool for web-based tasks
def use_anchor_browser(command):
with sync_playwright() as p:
# Connect to Anchor Browser session
browser = p.chromium.connect_over_cdp(
f"wss://connect.anchorbrowser.io?apiKey={ANCHOR_API_KEY}"
)
page = browser.new_page()
page.goto(command['url'])
# Perform specific actions as needed
if command.get('action') == 'search':
page.fill(command['search_box'], command['search_text'])
page.click(command['search_button'])
# Extract and return data if needed
result = page.content()
browser.close()
return result
# Example usage in your custom AI framework
command = {
'url': 'https://example.com',
'action': 'search',
'search_box': 'input[name="q"]',
'search_text': 'Anchor Browser',
'search_button': 'button[type="submit"]'
}
result = use_anchor_browser(command)
print(result)
```
```jsx node.js
import { chromium } from 'playwright-core';
const ANCHOR_API_KEY = process.env.ANCHOR_API_KEY; // Replace with your actual API key stored in environment variables
// Define a function to use Anchor Browser as a tool for web-based tasks
async function useAnchorBrowser(command) {
// Connect to Anchor Browser session
const browser = await chromium.connectOverCDP(
`wss://connect.anchorbrowser.io?apiKey=${ANCHOR_API_KEY}`
);
const page = await browser.newPage();
await page.goto(command.url);
// Perform specific actions as needed
if (command.action === 'search') {
await page.fill(command.search_box, command.search_text);
await page.click(command.search_button);
}
// Extract and return data if needed
const result = await page.content();
await browser.close();
return result;
}
// Example usage in your custom AI framework
const command = {
url: 'https://example.com',
action: 'search',
search_box: 'input[name="q"]',
search_text: 'Anchor Browser',
search_button: 'button[type="submit"]'
};
const result = await useAnchorBrowser(command);
console.log(result);
```
## Use Anchor Browser as a Specific-Flow Tool Defined in a Custom Framework
Anchor Browser can also be integrated into your custom AI framework to create specific workflow tools. These tools can handle specialized tasks that your agent needs to perform repeatedly, providing consistency and reducing the need for writing duplicate code.
Here is an example of creating a specific tool using Anchor Browser that can be utilized by your custom AI framework for automating targeted tasks.
```python python
import requests
from playwright.sync_api import sync_playwright
ANCHOR_API_KEY = "YOUR_ANCHOR_API_KEY" # Replace with your actual API key
# Define a custom tool for interacting with a specific web application
def specific_anchor_tool(command):
with sync_playwright() as p:
# Connect to Anchor Browser session
browser = p.chromium.connect_over_cdp(
f"wss://connect.anchorbrowser.io?apiKey={ANCHOR_API_KEY}"
)
page = browser.new_page()
page.goto(command['url'])
# Perform specific actions based on the command
if command.get('action') == 'extract':
result = page.text_content(command['selector'])
browser.close()
return result
browser.close()
# Example usage in your custom AI framework
command = {
'url': 'https://example.com',
'action': 'extract',
'selector': '#data'
}
result = specific_anchor_tool(command)
print(result)
```
```jsx node.js
import { chromium } from 'playwright-core';
const ANCHOR_API_KEY = process.env.ANCHOR_API_KEY; // Replace with your actual API key stored in environment variables
// Define a custom specific-flow tool for interacting with a specific web application
async function specificAnchorTool(command) {
// Connect to Anchor Browser session
const browser = await chromium.connectOverCDP(
`wss://connect.anchorbrowser.io?apiKey=${ANCHOR_API_KEY}`
);
const page = await browser.newPage();
await page.goto(command.url);
// Perform specific actions based on the command
if (command.action === 'extract') {
const result = await page.textContent(command.selector);
await browser.close();
return result;
}
await browser.close();
}
// Example usage in your custom AI framework
const command = {
url: 'https://example.com',
action: 'extract',
selector: '#data'
};
const result = await specificAnchorTool(command);
console.log(result);
```
# Langchain
Source: https://docs.anchorbrowser.io/agent-frameworks/langchain
AI agents can leverage browser sessions to complete tasks on the web using Langchain, a framework that provides easy integration for AI-driven workflows. The ways to use Anchor Browser in the Langchain platform are:
* **As a Flexible Browser Tool**: Enable the Langchain agent to explore the web freely using a general-purpose browser tool.
* **As a Specific-Flow Tool Defined in Langchain**: Create custom tools by writing Langchain code to define specific workflows tailored to your needs.
* **As a Specific-Flow Tool Defined in Anchor Browser**: Define tools using the Anchor platform, which Langchain agents can then use through the Official Anchor Tool.
## Quick Start - Use Anchor Browser as a Flexible Browser Tool
You can connect your Langchain agent directly to Anchor Browser, allowing it to use browser sessions for various tasks, leveraging the power of browser automation without the need for complex integration code. Below is a quick guide to setting up and using Anchor Browser as a tool for your Langchain agent.
```python python
from langchain.tools import Tool
from playwright.sync_api import sync_playwright
ANCHOR_API_KEY = "YOUR_ANCHOR_API_KEY" # Replace with your actual API key
# Register Anchor Browser as a tool in Langchain
class AnchorBrowserTool(Tool):
name = "AnchorBrowser"
description = "Use Anchor Browser to perform web-based tasks."
def __init__(self):
super().__init__()
def _run(self, command):
with sync_playwright() as p:
# Connect to Anchor Browser session
browser = p.chromium.connect_over_cdp(
f"wss://connect.anchorbrowser.io?apiKey={ANCHOR_API_KEY}"
)
page = browser.new_page()
page.goto(command['url'])
# Perform specific actions as needed
if command.get('action') == 'search':
page.fill(command['search_box'], command['search_text'])
page.click(command['search_button'])
# Extract and return data if needed
result = page.content()
browser.close()
return result
# Use the AnchorBrowserTool in a Langchain agent
my_agent = LangchainAgent()
my_agent.add_tool(AnchorBrowserTool())
# Use the agent to perform actions on the web
result = my_agent.run({
'tool': 'AnchorBrowser',
'command': {
'url': 'https://example.com',
'action': 'search',
'search_box': 'input[name="q"]',
'search_text': 'Anchor Browser',
'search_button': 'button[type="submit"]'
}
})
print(result)
```
```jsx node.js
import { Tool } from 'langchain';
import { chromium } from 'playwright-core';
const ANCHOR_API_KEY = process.env.ANCHOR_API_KEY; // Replace with your actual API key stored in environment variables
// Define a custom tool in Langchain that uses Anchor Browser
class AnchorBrowserTool extends Tool {
constructor() {
super();
this.name = "AnchorBrowser";
this.description = "Use Anchor Browser to perform web-based tasks.";
}
async _run(command) {
// Connect to Anchor Browser session
const browser = await chromium.connectOverCDP(
`wss://connect.anchorbrowser.io?apiKey=${ANCHOR_API_KEY}`
);
const page = await browser.newPage();
await page.goto(command.url);
// Perform specific actions as needed
if (command.action === 'search') {
await page.fill(command.search_box, command.search_text);
await page.click(command.search_button);
}
// Extract and return data if needed
const result = await page.content();
await browser.close();
return result;
}
}
// Use the AnchorBrowserTool in a Langchain agent
const agent = new LangchainAgent();
agent.addTool(new AnchorBrowserTool());
// Use the agent to perform actions on the web
const result = await agent.run({
tool: 'AnchorBrowser',
command: {
url: 'https://example.com',
action: 'search',
search_box: 'input[name="q"]',
search_text: 'Anchor Browser',
search_button: 'button[type="submit"]'
}
});
console.log(result);
```
## Use Anchor Browser as a Specific-Flow Tool Defined in Langchain
Langchain can integrate closely with Anchor Browser to define tools for particular workflows. For example, if you need a customized process to interact with an authenticated application, you can create that flow as a reusable tool that Langchain agents can use for automation.
Here is an example of creating a specific workflow tool using Anchor Browser that can be utilized by Langchain to automate targeted tasks.
```python python
from langchain.tools import Tool
from playwright.sync_api import sync_playwright
ANCHOR_API_KEY = "YOUR_ANCHOR_API_KEY" # Replace with your actual API key
# Register Anchor Browser as a specific application tool in Langchain
class AnchorSpecificTool(Tool):
name = "SpecificAnchorTool"
description = "Custom tool for interacting with a specific application."
def __init__(self):
super().__init__()
def _run(self, command):
with sync_playwright() as p:
# Connect to Anchor Browser session
browser = p.chromium.connect_over_cdp(
f"wss://connect.anchorbrowser.io?apiKey={ANCHOR_API_KEY}"
)
page = browser.new_page()
page.goto(command['url'])
# Perform specific actions based on command
if command.get('action') == 'extract':
result = page.text_content(command['selector'])
browser.close()
return result
browser.close()
# Use the AnchorSpecificTool in a Langchain agent
my_agent = LangchainAgent()
my_agent.add_tool(AnchorSpecificTool())
# Use the agent to perform a specific task
result = my_agent.run({
'tool': 'SpecificAnchorTool',
'command': {
'url': 'https://example.com',
'action': 'extract',
'selector': '#data'
}
})
print(result)
```
```jsx node.js
import { Tool } from 'langchain';
import { chromium } from 'playwright-core';
const ANCHOR_API_KEY = process.env.ANCHOR_API_KEY; // Replace with your actual API key stored in environment variables
// Define a custom specific-flow tool in Langchain that uses Anchor Browser
class AnchorSpecificTool extends Tool {
constructor() {
super();
this.name = "SpecificAnchorTool";
this.description = "Custom tool for interacting with a specific application.";
}
async _run(command) {
// Connect to Anchor Browser session
const browser = await chromium.connectOverCDP(
`wss://connect.anchorbrowser.io?apiKey=${ANCHOR_API_KEY}`
);
const page = await browser.newPage();
await page.goto(command.url);
// Perform specific actions based on the command
if (command.action === 'extract') {
const result = await page.textContent(command.selector);
await browser.close();
return result;
}
await browser.close();
}
}
// Use the AnchorSpecificTool in a Langchain agent
const agent = new LangchainAgent();
agent.addTool(new AnchorSpecificTool());
// Use the tool through the Langchain agent
const result = await agent.run({
tool: 'SpecificAnchorTool',
command: {
url: 'https://example.com',
action: 'extract',
selector: '#data'
}
});
console.log(result);
```
# Agentic File Usage
Source: https://docs.anchorbrowser.io/agentic-browser-control/agentic-file-usage
Upload ZIP files to browser sessions for AI agents to use
**Compatibility Note**: Only works with the `browser-use` agent framework. Not supported with OpenAI CUA.
## Quick Start
Upload a ZIP file containing resources that your AI agent can use to complete tasks. The ZIP file is automatically extracted and made available to the agent.
## Example: Upload ZIP File
```javascript
import { chromium } from 'playwright';
// 1. Create a test ZIP file with content
const testContent = 'Hello from Anchor!\nThis is a test file for the agent.';
const blob = new Blob([testContent], { type: 'text/plain' });
const formData = new FormData();
formData.append('file', blob, 'test-data.zip');
// 2. Upload to browser session
const response = await fetch(`https://api.anchorbrowser.io/v1/sessions/${sessionId}/agent/files`, {
method: 'POST',
headers: {
'anchor-api-key': apiKey
},
body: formData
});
const result = await response.json();
console.log('Upload result:', result);
// 3. Connect to the browser session and use uploaded files with AI agent
const browser = await chromium.connectOverCDP(
`wss://connect.anchorbrowser.io?apiKey=${apiKey}&sessionId=${sessionId}`
);
const context = browser.contexts()[0];
const page = context.pages()[0];
// Navigate to a website where you want to use the uploaded files
await page.goto('https://v0-download-and-upload-text.vercel.app/');
// Use AI agent to interact with the page using uploaded files
const ai = context.serviceWorkers()[0];
const aiResult = await ai.evaluate("upload a file to the server");
console.log('AI agent result:', aiResult);
```
That's it! The agent can now access all uploaded files and use them to complete web tasks.
# AI Task Completion
Source: https://docs.anchorbrowser.io/agentic-browser-control/ai-task-completion
Anchor Browser delivers a state-of-the-art 89% Score on the industry-standard benchmark WebVoyager, leveraging browser-use as a core component of the automation capability.
## The browser AI object
Anchor Browser comes with an embedded AI component, that allows to control the browser or extract data using natural language.
This capability allows to use the browser without any coding.
**For basic usage**, the [Perform Web Task Tool](/api-reference/ai-tools/perform-web-task) exposes these capabilities through a single API request.
**For advanced usage**, use it through the playwright CDP connection (all languages supported by PW are supported)
#### Available Models
gpt-4o
gpt-4o-mini
gpt-4.1
gpt-4.1-mini
gemini-2.0-flash
gemini-2.0-flash-exp
gemini-2.0-flash-lite-preview-02-05
gemini-2.5-flash
meta-llama/llama-4-maverick-17b-128e-instruct
meta-llama/llama-4-scout-17b-16e-instruct
moonshotai/kimi-k2-instruct
o4-mini
o3
o3-mini
o1
### Code Example
```tsx node.js
import { chromium } from "playwright-core";
const browserSession = await chromium.connectOverCDP(`wss://connect.anchorbrowser.io?apiKey=ANCHOR-API-KEY`);
const context = browser.contexts()[0];
const ai = context.serviceWorkers()[0];
const page = context.pages()[0];
// Combine regular playwright and AI actions to benefit from both options
await page.goto("http://docs.anchorbrowser.io/", {waitUntil:'domcontentloaded'});
// Use the embedded 'ai' object
const result = await ai.evaluate('Find the last game played by Milwaukee in the NBA and return the result')
console.log(result);
```
```python python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp("wss://connect.anchorbrowser.io?apiKey=ANCHOR-API-KEY")
context = browser.contexts[0]
target_url = "chrome-extension://bppehibnhionalpjigdjdilknbljaeai/background.js"
ai = next((sw for sw in context.service_workers if sw.url == target_url), None)
# Use the embedded 'ai' object
result = ai.evaluate('Find the last game played by Milwaukee in the NBA and return the result')
print(result)
```
## Structured Output
The AI object can also be used to extract structured data from the browser. This is done by providing a **JSON schema** to the AI object, which will then return the structured data.
The following demonstrates using **Zod** and **Pydantic** to utilize the structured output capability.
```tsx node.js
import { chromium } from 'playwright';
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
const browser = await chromium.connectOverCDP("wss://connect.anchorbrowser.io?apiKey=ANCHOR-API-KEY");
const context = browser.contexts()[0];
const ai = context.serviceWorkers()[0];
const page = context.pages()[0];
const outputSchema = z.object({
nodes_cpu_usage: z.array(
z.object({
node: z.string(),
cluster: z.string(),
cpu_avg_percentage: z.number(),
})
)
});
const jsonSchema = zodToJsonSchema(outputSchema);
const taskPayload = {
output_schema: jsonSchema,
prompt: 'Collect the node names and their CPU average %',
};
await page.goto("https://play.grafana.org/a/grafana-k8s-app/navigation/nodes?from=now-1h&to=now&refresh=1m");
const result = await ai.evaluate(JSON.stringify(taskPayload));
console.info(result);
```
```python python
from playwright.sync_api import sync_playwright
from pydantic import BaseModel
from typing import List
import json
class NodeCpuUsage(BaseModel):
node: str
cluster: str
cpu_avg_percentage: float
class OutputSchema(BaseModel):
nodes_cpu_usage: List[NodeCpuUsage]
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp("wss://connect.anchorbrowser.io?apiKey=ANCHOR-API-KEY")
context = browser.contexts[0]
ai = next((sw for sw in context.service_workers if sw.url == "chrome-extension://bppehibnhionalpjigdjdilknbljaeai/background.js"), None)
page = context.pages[0]
task_payload = {
'prompt': 'Collect the node names and their CPU average %',
'output_schema': json.loads(NodeCpuUsage.schema_json())
}
page.goto("https://play.grafana.org/a/grafana-k8s-app/navigation/nodes?from=now-1h&to=now&refresh=1m")
result = ai.evaluate(json.dumps(task_payload))
print(result)
browser.close()
```
# Browser Profiles (Authenticated sessions)
Source: https://docs.anchorbrowser.io/essentials/authentication-and-identity
Anchor allows you to save an existing browser state as "profiles" for use in future browser sessions. This feature enables users to:
* Store authenticated sessions and identities, allowing to stay logged in to websites
* Improve overall speed and performance
The following guide explains how to create and use Identity Profiles in Anchor Browser.
## Quick start - Create and use a profile
Through the Anchor playground, create a profile on the configuration area. Then, click to start a session.
Start a new session in Anchor playground, and authenticate to the target service to create a browser context with the required cookies and session data.
Save the profile using the 'Save Profile' button in the Anchor Browser Playground.
This operation will end the current playground browser session
Now, when using the [create session](/api-reference/sessions/create-session) API, pass the `profile` parameter with the name of the profile you created to load the saved browser context.
For additional capabilities and advanced use cases, refer to the API documentation for [profiles](/api-reference/profiles).
## Alternative approaches
### Method 1 - Mounting a Browser Context
In this method, Anchor Browser uses a pre-authenticated browser context to access protected resources. This approach is recommended because it maintains a secure, isolated environment for authentication without exposing sensitive data.
Start by logging into the target service in a dedicated browser session. This creates a browser context with the required cookies and session data.
Once authenticated, export the browser context (including cookies and session data) and save it securely.
You can also export the browser context manually from your local browser by saving cookies and session data, using tools like browser devtools or extensions. - [How to manually collect the context object](https://chatgpt.com/share/6728a581-2030-800a-8f1b-9afd8297e0f1)
```jsx node.js
import { chromium } from 'playwright-core';
import fs from 'fs';
// Authenticate and save browser context
(async () => {
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com/login');
// Perform authentication actions
await page.fill('#username', 'your-username');
await page.fill('#password', 'your-password');
await page.click('#login-button');
// Save browser context
const storageState = await context.storageState();
fs.writeFileSync('browser_context.json', JSON.stringify(storageState));
await browser.close();
})();
```
```python python
from playwright.sync_api import sync_playwright
import json
# Authenticate and save browser context
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context()
page = context.new_page()
page.goto('https://example.com/login')
# Perform authentication actions (fill username/password and login)
page.fill('#username', 'your-username')
page.fill('#password', 'your-password')
page.click('#login-button')
# Save browser context
context_storage = context.storage_state()
with open('browser_context.json', 'w') as f:
f.write(json.dumps(context_storage))
browser.close()
```
Use the saved browser context within Anchor Browser to access authenticated services seamlessly.
```jsx node.js
import { chromium } from 'playwright-core';
import fs from 'fs';
(async () => {
const storageState = JSON.parse(fs.readFileSync('browser_context.json', 'utf-8'));
const browser = await chromium.connectOverCDP(`wss://connect.anchorbrowser.io?apiKey=${ANCHOR_API_KEY}`);
// Mount the browser context in Anchor Browser
const context = await browser.newContext({ storageState });
const page = await context.newPage();
// Use the authenticated session
await page.goto('https://example.com/protected');
await browser.close();
})();
```
```python python
import json
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
with open('browser_context.json') as f:
context_storage = json.load(f)
browser = p.chromium.connect_over_cdp(f"wss://connect.anchorbrowser.io?apiKey={ANCHOR_API_KEY}")
# Mount the browser context in Anchor Browser:
context = browser.new_context(storage_state=context_storage)
page = context.new_page()
# Use the authenticated session:
page.goto('https://example.com/protected')
browser.close()
```
### Method 2 - Playwright-Based Cookie Injection
For cases where browser context mounting isn’t feasible, Playwright allows direct injection of cookies into a browser session, enabling access to authenticated resources.
Authenticate manually or programmatically to capture the required cookies.
Use Playwright’s API to inject cookies into the browser session before navigating to the authenticated page.
With the cookies injected, the AI agent can interact with the protected service as if logged in.
### Code example
```jsx node.js
import { chromium } from 'playwright-core';
import fs from 'fs';
// Load cookies securely from a file
const cookies = JSON.parse(fs.readFileSync('cookies.json', 'utf-8'));
(async () => {
const browser = await chromium.connectOverCDP(`wss://connect.anchorbrowser.io?apiKey=${ANCHOR_API_KEY}`);
const context = await browser.newContext();
// Inject cookies for authenticated access:
await context.addCookies(cookies);
const page = await context.newPage();
// Use the authenticated session:
await page.goto('https://example.com/protected');
await browser.close();
})();
```
```python python
import json
from playwright.sync_api import sync_playwright
# Load cookies securely from a file or environment variable:
with open('cookies.json', 'r') as f:
cookies = json.load(f)
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(f"wss://connect.anchorbrowser.io?apiKey={ANCHOR_API_KEY}")
context = browser.new_context()
# Inject cookies for authenticated access:
context.add_cookies(cookies)
page = context.new_page()
# Use the authenticated session:
page.goto('https://example.com/protected')
browser.close()
```
## Secure Storage of Secrets
To maintain the security of your credentials, API keys, and sensitive data, **do not store secrets directly in plaintext within your code**. Instead, consider these best practices:
1. Environment Variables: Store secrets in environment variables. You can use libraries such as dotenv for Node.js to load variables from a .env file.
2. Secrets Management Services: Use secure storage solutions like AWS Secrets Manager, Azure Key Vault, or HashiCorp Vault to manage sensitive data securely.
# Session Recording
Source: https://docs.anchorbrowser.io/essentials/recording
Record browser sessions for debugging, analysis, and documentation
## Overview
Anchor Browser provides built-in session recording that allows you to capture and review browser sessions. This feature is invaluable for debugging automation workflows, analyzing user behavior, and creating documentation.
## How It Works
Anchor Browser automatically records browser sessions and creates an MP4 video file that captures the complete visual experience.
Recordings are accessible both through our API and the web UI (see below).
# API Usage
## Record a Session
Recording is enabled by default when creating a session.
Start a session using the [API](/api-reference/sessions/create-session), you can enable recording by setting `recording: true` in the request body.
```javascript node.js
const axios = require('axios');
(async () => {
const response = await axios.post("https://api.anchorbrowser.io/v1/sessions", {
session: {
recording: true // Enable recording (default)
}
}, {
headers: {
"anchor-api-key": process.env.ANCHOR_API_KEY,
"Content-Type": "application/json",
},
});
console.log("Session created:", response.data);
})().catch(console.error);
```
```python python
import os
import requests
ANCHOR_API_KEY = os.getenv("ANCHOR_API_KEY")
response = requests.post(
"https://api.anchorbrowser.io/v1/sessions",
json={
"session": {
"recording": True # Enable recording (default)
}
},
headers={
"anchor-api-key": ANCHOR_API_KEY,
"Content-Type": "application/json",
},
)
response.raise_for_status()
print("Session created:", response.json())
```
## Get Session Recordings
Retrieve recordings for a specific session:
```javascript node.js
const axios = require('axios');
(async () => {
const sessionId = 'your-session-id'; // Replace with actual session ID
const recordings = await axios.get(
`https://api.anchorbrowser.io/v1/sessions/${sessionId}/recordings`,
{
headers: {
"anchor-api-key": process.env.ANCHOR_API_KEY,
},
}
);
console.log("Recordings:", recordings.data);
})().catch(console.error);
```
```python python
import os
import requests
ANCHOR_API_KEY = os.getenv("ANCHOR_API_KEY")
session_id = "your-session-id" # Replace with actual session ID
recordings = requests.get(
f"https://api.anchorbrowser.io/v1/sessions/{session_id}/recordings",
headers={
"anchor-api-key": ANCHOR_API_KEY,
},
)
recordings.raise_for_status()
print("Recordings:", recordings.json())
```
## Download Recording
Download a specific recording file:
```javascript node.js
const axios = require('axios');
const fs = require('fs');
(async () => {
const sessionId = 'your-session-id'; // Replace with actual session ID
const recording = await axios.get(
`https://api.anchorbrowser.io/v1/sessions/${sessionId}/recordings/primary/fetch`,
{
headers: {
"anchor-api-key": process.env.ANCHOR_API_KEY,
},
responseType: 'stream'
}
);
// Save to file
const writer = fs.createWriteStream(`recording-${sessionId}.mp4`);
recording.data.pipe(writer);
console.log(`Recording saved as recording-${sessionId}.mp4`);
})().catch(console.error);
```
```python python
import os
import requests
ANCHOR_API_KEY = os.getenv("ANCHOR_API_KEY")
session_id = "your-session-id" # Replace with actual session ID
recording = requests.get(
f"https://api.anchorbrowser.io/v1/sessions/{session_id}/recordings/primary/fetch",
headers={
"anchor-api-key": ANCHOR_API_KEY,
},
stream=True
)
recording.raise_for_status()
# Save to file
with open(f"recording-{session_id}.mp4", "wb") as f:
for chunk in recording.iter_content(chunk_size=8192):
f.write(chunk)
print(f"Recording saved as recording-{session_id}.mp4")
```
# Web UI Usage
## Create a Session
In order to create a session through the UI with recording enabled use the [playground](https://app.anchorbrowser.io/playground), it will be recorded by default.
## Session Recordings
The Session History dashboard shows all sessions. Each session has a link to its recording.
If a session is still running, the link in the session history page will take you to the session's live view instead of the recording. Once the session ends, the link will point to the recording.
## Recording Playback
When you click on a session recording, the playback interface will be opened.
You can use it to view the recording, navigate through it, and download it as MP4 file.
# Tools - Browser Control API
Source: https://docs.anchorbrowser.io/essentials/tool-building
Anchor Browser offers API endpoints (also known as "agentic tools") to simplify the usage of the browser, and enable browser utilization *without any coding*
### Featured tools
* **[Screenshot webpage](/api-reference/tools/screenshot-webpage)**: Get a fully javascript-rendered screenshot of a given webpage.
* **[Get webpage content](/api-reference/tools/get-webpage-content)**: Get an LLM ready, Markdown version of a given webpage.
### Featured AI based tools
* **[Perform task](/api-reference/ai-tools/perform-web-task)**: Use natural language to have the browser autonomously act and perform a task.
# Buyer Intent Discovery
Source: https://docs.anchorbrowser.io/examples/buyer-intent
The following example use-case shows how to find buyer-intent data based on Github stargazers of a Github project named 'Airflow'. A star from a person that works for a significant corporation can be a hint of buying intent in the data pipelines space.
```tsx node.js
import { chromium } from 'playwright';
const browser = await chromium.connectOverCDP(connectionString); // Fill in the browser CDP string
const context = browser.contexts()[0];
const ai = context.serviceWorkers()[0];
const page = context.pages()[0];
await page.goto("https://github.com/apache/airflow/stargazers?page=1");
const result = await ai.evaluate('On the current stargazers list, return the GitHub profile URLs of all users that are a part of a well-known company. Then, do this for the first 3 pages using the "page" query parameter. Return a JSON array result: ["url1", "url2", ...].')
console.log(result);
```
# Configuration Collection
Source: https://docs.anchorbrowser.io/examples/configuration-collection
The following example shows how to collect configuration data that is not exposed through an API from a SaaS service (Grafana) configuration page.
```tsx node.js
import { chromium } from 'playwright';
const browser = await chromium.connectOverCDP(connectionString);
const context = browser.contexts()[0];
const ai = context.serviceWorkers()[0];
const page = context.pages()[0];
await page.goto("https://play.grafana.org/a/grafana-k8s-app/navigation/nodes?from=now-1h&to=now&refresh=1m", { waitUntil: 'domcontentloaded' });
const result = await ai.evaluate('Collect the node names and their CPU average %, return in JSON array')
console.log(result);
```
# Form Filling Automation
Source: https://docs.anchorbrowser.io/examples/form-filling
The following example shows form filling, including the ability to self-complete missing data in the form filling process.
```tsx node.js
import { chromium } from 'playwright';
const browser = await chromium.connectOverCDP(connectionString);
const context = browser.contexts()[0];
const ai = context.serviceWorkers()[0];
const page = context.pages()[0];
page.goto('https://www.wix.com/demone2/nicol-rider');
const result = await ai.evaluate('Read the resume, understand the details, and complete the form at https://formspree.io/library/donation/charity-donation-form/preview.html as if you were her. Limit the donation to $10.');
console.info(result);
```
# Deep Research
Source: https://docs.anchorbrowser.io/examples/research-task
The following example demonstrates how to use Anchor Browser to perform web research tasks.
```tsx node.js
import { chromium } from 'playwright';
const browser = await chromium.connectOverCDP(connectionString);
const context = browser.contexts()[0];
const ai = context.serviceWorkers()[0];
const page = context.pages()[0];
await page.goto("http://docs.anchorbrowser.io/", { waitUntil: 'domcontentloaded' });
const result = await ai.evaluate('Find the most recent NBA game played by the Milwaukee Bucks and provide the result.')
console.log(result);
const author = await ai.evaluate('Find an article discussing the game and provide the author\'s name.')
console.log(author);
```
# Browser-use
Source: https://docs.anchorbrowser.io/integrations/browseruse-deployment
This guide is dedicated to running your own browser-use agent while connecting to an Anchor browser. To use the embedded browser use capability, refer to [AI task completion](/agentic-browser-control/ai-task-completion)
```python
import requests
import os
ANCHOR_API_KEY = "YOUR_ANCHOR_API_KEY"
browser_configuration = {
"adblock_config": {"active": True},
"captcha_config": {"active": False},
"proxy_config": {
"active": True,
"type": "anchor_mobile",
"country_code": "uk"
},
"headless": False
}
response = requests.post(
"https://api.anchorbrowser.io/api/sessions",
headers={
"anchor-api-key": ANCHOR_API_KEY,
"Content-Type": "application/json",
},
json=browser_configuration
)
session_data = response.json()
session_id = session_data["data"]["id"]
```
Returns:
```json
{
"data": {
"id": "",
"cdp_url": "",
"live_view_url": "https://live.anchorbrowser.io?sessionId="
// Use the live view URL to view the browser session in real-time
}
}
```
```python
from browser_use import Agent, Controller
from browser_use.browser import BrowserProfile, BrowserSession
from browser_use.llm import ChatOpenAI
# Configure your LLM (example with OpenAI)
llm = ChatOpenAI(
model='gpt-4o',
api_key=os.getenv('OPENAI_API_KEY'),
)
# Create CDP connection URL
cdp_url = f'wss://connect.anchorbrowser.io?sessionId={session_id}'
# Initialize browser session with Anchor
profile = BrowserProfile(keep_alive=True)
browser_session = BrowserSession(
headless=False,
cdp_url=cdp_url,
browser_profile=profile
)
# Create controller and agent
controller = Controller()
agent = Agent(
task="Your task description here",
llm=llm,
enable_memory=False,
use_vision=False,
controller=controller,
browser_session=browser_session,
)
# Run the agent
result = await agent.run(max_steps=40)
```
Use the `live_view_url` returned on the first step to view the browser session in real-time, or to embed it as a UI component
```html
```
# Make
Source: https://docs.anchorbrowser.io/integrations/make
Integrate Anchor Browser with Make (formerly Integromat) for no-code automation workflows
## About Make
[Make](https://www.make.com/) is a no-code automation platform that lets you connect apps and services together to build powerful workflows — without writing code.
## Quick Start
Use our modules to enhance your automation workflows with Anchor Browser powerful tools.
### Module Selection
Use our [AI Task Completion](/agentic-browser-control/ai-task-completion) module to perform various tasks in a single module.
### Basic Workflow
Here is a basic workflow that uses our modules to perform a task, capture a screenshot and save it to a file both in google drive and slack.
***
## Getting Help
If you experience any issues with Anchor Browser Make modules, please contact our support team at [support@anchorbrowser.io](mailto:support@anchorbrowser.io).
# OpenAI CUA
Source: https://docs.anchorbrowser.io/integrations/openai-cua
Integrate OpenAI Computer Use Agent with Anchor Browser
## Overview
Learn how to combine OpenAI's Computer Use Agent (CUA) with Anchor Browser to enable powerful cloud-based browser automation.
CUA is an advanced AI system that combines visual perception, contextual understanding, and browser control capabilities. When integrated with Anchor Browser's cloud infrastructure, it provides a robust platform for deploying automated web interactions at scale.
### Prerequisites
* OpenAI API key with Computer Use Agent access
* Anchor account and API key
* Python 3.8+
### Basic Integration
This basic setup will get you up and running with a CUA agent using Anchor Browser as the underlying browser automation platform.
```bash
git clone https://github.com/anchorforge/openai-cua-sample-app.git
```
```bash
pip install -r "requirements.txt"
```
```
ANCHOR_API_KEY=YOUR_API_KEY
OPENAI_API_KEY=YOUR_OPENAI_API_KEY
OPENAI_ORG=YOUR_OPENAI_ORG
```
```
python cli.py --computer anchorbrowser --input "Play tic tac toe"
```
### Customizing the CUA Agent
The CUA agent can be customized by updating the flags in the CLI:
* `--input`: The initial input to the agent (optional: the CLI will prompt you for input if not provided)
* `--debug`: Enable debug mode.
* `--show`: Show images (screenshots) during the execution.
* `--start-url`: Start the browsing session with a specific URL. By default, the CLI will start the browsing session with [https://bing.com](https://bing.com).
For the full capabilites set, refer to [openapi documentation](https://platform.openai.com/docs/guides/tools-computer-use/)
# Documentation
Source: https://docs.anchorbrowser.io/introduction
Welcome to Anchor Browser
Anchor is the platform for AI Agentic browser automation, which solves the challenge of automating workflows for web applications that lack APIs or have limited API coverage.
It simplifies the creation, deployment, and management of browser-based automations, transforming complex web interactions into simple API endpoints.
## Getting started
Get up and running with our quickstart guides, whether you code or don't
Build browser flows in a live interactive playground
## Next steps
Explore advanced features and capabilities
Seamlessly integrate with leading AI agent frameworks.
Securely manage access and identities for your agents.
Build web tools that empower your AI agent.
Jumpstart your project with practical, ready-to-use examples.
# Pricing
Source: https://docs.anchorbrowser.io/pricing
Below is a clear breakdown of our pricing structure to help you understand the costs associated with using our platform.
## Pricing Breakdown
### 1. **Browser Creation**
* **\$0.01 per browser creation**.\
Every new browser instance created incurs a minimal fee, ensuring cost-effective scaling of your automation workflows.
### 2. **Browser Usage**
* **\$0.05 per browser hour**.\
Charges are based on the total active time of the browser session, calculated to the nearest full minute.
### 3. **Anchor Proxy**
* **\$4 per GB** of Anchor Residential proxy data used.\
Our residential proxy offers high-speed, secure connections, ensuring seamless automation across the web.
* **\$8 per GB** of Anchor Mobile proxy.\
Anchor mobile proxy provides network access through a mobile device IP address, allowing to access almost any website.
### 4. **AI Steps**
* **\$0.01 per step**
Each AI task can consist of multiple steps, depending on its length & complexity.
## Example Calculation
For 10 browsers running for 5 hours, using 2GB of residential proxy data:
* **Browser Creation**: 10 browsers × $0.01 = $0.10
* **Browser Hours**: 10 browsers × 5 hours × $0.05 = $2.50
* **Proxy Data**: 2GB × $4 = $8.00
* **Total**: \$10.60
# API Quick Start
Source: https://docs.anchorbrowser.io/quickstart/use-via-api
Our APIs can be used directly (See our [API Reference](/api-reference)) or through integrations to automation platforms. We've created modules for our most commonly used API routes in each of the supported platforms.
Pick your preferred platform to view a quick-start for its usage:
Use the API directly as you like, See our [API Reference](/api-reference) for more details.
Enhance Browser-Use capabilities with Anchor tools and cloud-based browser sessions
Integrate with Make (formerly Integromat) for no-code automation
Integrate with CrewAI to gain robust qualities of Anchor Browser implementing no-code automation.
Integrate with Langchain to leverage Anchor Browser's browser tools in your LLM workflows.
Integrate with your own platform to leverage Anchor Browser's in your automations.
## Quick API Examples
### Single Step Browser Tool Call
The easiest way to utilize Anchor Browser is through browser tools. Browser tools are API endpoints that wrap end-to-end browser functionality in a single API call.
```bash curl
curl -X POST "https://api.anchorbrowser.io/v1/tools/perform-web-task" \
-H "anchor-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"task": "Go to anchorbrowser.io and click the Get Started button",
"headless": false
}'
```
```javascript node.js
const axios = require('axios');
const response = await axios.post('https://api.anchorbrowser.io/v1/tools/perform-web-task', {
task: 'Go to anchorbrowser.io and click the Get Started button',
headless: false
}, {
headers: {
'anchor-api-key': process.env.ANCHOR_API_KEY,
'Content-Type': 'application/json'
}
});
console.log(response.data);
```
```python python
import requests
response = requests.post('https://api.anchorbrowser.io/v1/tools/perform-web-task',
json={
'task': 'Go to anchorbrowser.io and click the Get Started button',
'headless': False
},
headers={
'anchor-api-key': os.getenv('ANCHOR_API_KEY'),
'Content-Type': 'application/json'
}
)
print(response.json())
```
### Multi-Step Browser Flow
For use cases where a custom browser configuration is required, or a multi-step browser flow is needed:
In [Anchor UI](https://app.anchorbrowser.io/api-key), copy your API key
[Create a session](/api-reference/browser-sessions/start-browser-session) with the desired configuration
Perform [tool calls](/tools-api-reference/ai-tools/ask-webpage) while referencing the created session ID
# Code Quick Start
Source: https://docs.anchorbrowser.io/quickstart/use-via-code
This page is a quick start using code. If you want a quick start using an Integration (CrewAI, Make, Langchain, etc.) [click here](/quickstart/use-via-api).
In [Anchor UI](https://app.anchorbrowser.io/api-access), copy your API key
```bash node.js
npm i playwright-core
```
```bash python
pip3 install playwright
```
If you don't have access to code running, consider using the [live playground](https://app.anchorbrowser.io/playground)
The following example demonstrates how to start the browser and navigate to a website
```javascript node.js
const { chromium } = require("playwright-core");
(async () => {
const ANCHOR_API_KEY = process.env.ANCHOR_API_KEY;
const browser = await chromium.connectOverCDP(`wss://connect.anchorbrowser.io?apiKey=${ANCHOR_API_KEY}`);
const page = await browser.newPage();
// Navigate to Anchor Browser's website
await page.goto("https://anchorbrowser.io");
console.log("Page title:", await page.title());
await browser.close();
})().catch(console.error);
```
```python python
import os
from playwright.sync_api import sync_playwright
ANCHOR_API_KEY = os.getenv("ANCHOR_API_KEY")
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(
f"wss://connect.anchorbrowser.io?apiKey={ANCHOR_API_KEY}"
)
page = browser.new_page()
# Navigate to Anchor Browser's website
page.goto("https://anchorbrowser.io")
print("Page title:", page.title())
browser.close()
```
Anchor Browser supports different configurations of the browser session (see [API reference](/api-reference/sessions/create-session) for all options).
Some of the most common configurations are:
* [Proxy Configuration](/advanced/proxy)
* [Profiles to store Authenticated Sessions](/essentials/authentication-and-identity)
* [Session Termination](/advanced/session-termination)
To use a browser with a specific configuration, first create a browser session with the desired configuration.
```javascript node.js
const axios = require("axios");
(async () => {
const ANCHOR_API_KEY = process.env.ANCHOR_API_KEY;
const browserConfiguration = {
session: {
// Proxy configuration
proxy: {
active: true,
type: "anchor_residential",
country_code: "it"
},
// Session lifetime management
max_duration: 1, // 1 minute
idle_timeout: 1 // 1 minute
}
};
const response = await axios.post("https://api.anchorbrowser.io/v1/sessions", browserConfiguration, {
headers: {
"anchor-api-key": ANCHOR_API_KEY,
"Content-Type": "application/json",
},
});
const session = response.data.data;
console.log("Session created:", session.id); // Keep this ID for later use
})().catch(console.error);
```
```python python
import os
import requests # `pip3 install requests` if needed.
from playwright.sync_api import sync_playwright
ANCHOR_API_KEY = os.getenv("ANCHOR_API_KEY")
browserConfiguration = {
"session": {
"recording": False, # Default is True
# Proxy configuration
"proxy": {
"active": True,
"type": "anchor_residential",
"country_code": "it"
},
# Session lifetime management
"max_duration": 1, # 1 minute
"idle_timeout": 1 # 1 minute
},
}
response = requests.post(
"https://api.anchorbrowser.io/v1/sessions",
headers={
"anchor-api-key": ANCHOR_API_KEY,
"Content-Type": "application/json",
}, json=browserConfiguration
)
response.raise_for_status()
session = response.json()["data"]
print("Session created:", session["id"]) # Keep this ID for later use
```
You can create sessions and reconnect to them later using the session ID. This is useful for maintaining state across multiple browser sessions.
```javascript node.js
const { chromium } = require("playwright-core");
const ANCHOR_API_KEY = process.env.ANCHOR_API_KEY;
(async () => {
const browser = await chromium.connectOverCDP(`wss://connect.anchorbrowser.io?apiKey=${ANCHOR_API_KEY}&sessionId=${sessionId}`);
const page = await browser.newPage();
// Check the IP address
await page.goto("https://www.whatismyip.com/");
await page.waitForTimeout(10000)
console.log(await page.textContent('#region-state'))
// Close browser but session remains active
await browser.close();
})().catch(console.error);
```
```python python
import os
from playwright.sync_api import sync_playwright
ANCHOR_API_KEY = os.getenv("ANCHOR_API_KEY")
# Connect to the session
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(
f"wss://connect.anchorbrowser.io?apiKey={ANCHOR_API_KEY}&sessionId={session['id']}"
)
page = browser.new_page()
# Check the IP address
page.goto("https://www.whatismyip.com/")
page.wait_for_timeout(10000)
print(page.text_content('#region-state'))
# Close browser but session remains active
browser.close()
```
# SDK Quick Start
Source: https://docs.anchorbrowser.io/quickstart/use-via-sdk
This page is a quick start using our official SDK. If you want a quick start using raw code with Playwright, [click here](/quickstart/use-via-code).
For complete documentation and advanced usage examples, visit our package repositories:
* **Node.js**: [anchorbrowser on npm](https://www.npmjs.com/package/anchorbrowser)
* **Python**: [anchorbrowser on PyPI](https://pypi.org/project/anchorbrowser/)
In [Anchor UI](https://app.anchorbrowser.io/api-access), copy your API key
```bash node.js
npm install anchorbrowser
```
```bash python
pip install anchorbrowser
```
Set up the Anchor Browser client with your API key:
```javascript node.js
import { AnchorClient } from "anchorbrowser";
const anchorClient = new AnchorClient({
apiKey: process.env.ANCHOR_API_KEY,
});
```
```python python
import os
from anchorbrowser import AnchorClient
anchor_client = AnchorClient(
api_key=os.getenv("ANCHOR_API_KEY")
)
```
Use AI agents to automate browser tasks with natural language commands:
```javascript node.js
// Simple navigation task
const result = await anchorClient.agent.task(
"go to news.ycombinator.com and get the title of the first story"
);
console.log("Task result:", result);
// Task with execution step monitoring
const executionStepLogs = [];
const navigationResult = await anchorClient.agent.task(
"go to news.ycombinator.com and get the title of the first story",
{
taskOptions: {
onAgentStep: (executionStep) => {
console.log("Agent step:", executionStep);
},
},
}
);
```
```python python
# Simple navigation task
result = anchor_client.agent.task(
"go to news.ycombinator.com and get the title of the first story"
)
print("Task result:", result)
# Task with execution step monitoring
execution_step_logs = []
def on_agent_step(execution_step):
print("Agent step:", execution_step)
navigation_result = anchor_client.agent.task(
"go to news.ycombinator.com and get the title of the first story",
task_options={
"on_agent_step": on_agent_step
}
)
```
Extract structured data from webpages using schemas:
```javascript node.js
import { z } from "zod";
// Define your data schema
const extractionSchema = z.object({
title: z.string(),
description: z.string(),
price: z.string().optional(),
});
// Extract structured data from product page
const structuredResult = await anchorClient.agent.task(
"Extract the product title, description, and price from this Amazon product page",
{
taskOptions: {
outputSchema: z.toJSONSchema(extractionSchema),
url: "https://www.amazon.com/dp/B0D7D9N7X3",
},
}
);
// Validate the result
const validatedData = extractionSchema.safeParse(structuredResult.result);
if (validatedData.success) {
console.log("Product title:", validatedData.data.title);
console.log("Description:", validatedData.data.description);
console.log("Price:", validatedData.data.price);
}
```
```python python
from pydantic import BaseModel
from typing import Optional
# Define your data schema
class ProductSchema(BaseModel):
title: str
description: str
price: Optional[str] = None
# Extract structured data from product page
structured_result = anchor_client.agent.task(
"Extract the product title, description, and price from this Amazon product page",
task_options={
"output_schema": ProductSchema.model_json_schema(),
"url": "https://www.amazon.com/dp/B0D7D9N7X3"
}
)
# Validate the result
validated_data = ProductSchema.model_validate(structured_result["result"])
print("Product title:", validated_data.title)
print("Description:", validated_data.description)
print("Price:", validated_data.price)
```
Create and manage browser sessions with full Playwright integration:
```javascript node.js
// Method 1: Browser task with session control
const browserTask = await anchorClient.agent.browserTask(
"go to github.com/trending and find the most popular JavaScript repository"
);
console.log("Session ID:", browserTask.sessionId);
// Access the Playwright browser instance
const playwrightBrowser = browserTask.playwrightBrowser;
const page = playwrightBrowser.contexts()[0].pages()[0];
// Direct Playwright manipulation
await page.goto("https://stackoverflow.com/");
console.log("Current URL:", page.url());
// Wait for task completion
const taskResult = await browserTask.taskResultPromise;
console.log("Final result:", taskResult);
// Method 2: Create session and connect
const sessionResponse = await anchorClient.sessions.create();
const sessionId = sessionResponse.data.id;
const browser = await anchorClient.browser.connect(sessionId);
const context = browser.contexts()[0];
const newPage = context.pages()[0];
await newPage.goto("https://reddit.com/r/programming");
// Method 3: Create standalone browser
const standaloneBrowser = await anchorClient.browser.create();
const standalonePage = standaloneBrowser.contexts()[0].pages()[0];
await standalonePage.goto("https://httpbin.org/ip");
```
```python python
# Method 1: Browser task with session control
browser_task = anchor_client.agent.browser_task(
"go to github.com/trending and find the most popular JavaScript repository"
)
print("Session ID:", browser_task.session_id)
# Access the Playwright browser instance
playwright_browser = browser_task.playwright_browser
page = playwright_browser.contexts[0].pages[0]
# Direct Playwright manipulation
page.goto("https://stackoverflow.com/")
print("Current URL:", page.url)
# Wait for task completion
task_result = browser_task.task_result_promise
print("Final result:", task_result)
# Method 2: Create session and connect
session_response = anchor_client.sessions.create()
session_id = session_response.data.id
with anchor_client.browser.connect(session_id) as browser:
context = browser.contexts[0]
new_page = context.pages[0]
new_page.goto("https://reddit.com/r/programming")
# Method 3: Create standalone browser
with anchor_client.browser.create() as standalone_browser:
standalone_page = standalone_browser.contexts[0].pages[0]
standalone_page.goto("https://httpbin.org/ip")
```
Capture screenshots and use additional tools:
```javascript node.js
// Capture screenshot from a specific session
const screenshot = await anchorClient.tools.screenshotWebpage({
sessionId: browserTask.sessionId,
});
// Convert to blob and save
const screenshotBlob = await screenshot.blob();
console.log("Screenshot type:", screenshotBlob.type); // image/png
// You can also save the screenshot
const buffer = await screenshotBlob.arrayBuffer();
// Save buffer to file system as needed
```
```python python
# Capture screenshot from a specific session
screenshot = anchor_client.tools.screenshot_webpage(
session_id=browser_task.session_id
)
# Get screenshot data
screenshot_data = screenshot.read()
print("Screenshot captured, size:", len(screenshot_data))
# Save screenshot to file
with open("screenshot.png", "wb") as f:
f.write(screenshot_data)
```
Configure browser sessions with proxies, timeouts, and other options:
```javascript node.js
// Create session with advanced configuration
const sessionConfig = {
session: {
recording: false, // Disable session recording
proxy: {
active: true,
type: "anchor_residential",
country_code: "us",
},
max_duration: 5, // 5 minutes
idle_timeout: 1, // 1 minute
},
};
const configuredSession = await anchorClient.sessions.create(sessionConfig);
const configuredBrowser = await anchorClient.browser.connect(
configuredSession.data.id
);
// Use the configured browser to check IP location
const page = configuredBrowser.contexts()[0].pages()[0];
await page.goto("https://httpbin.org/ip");
const ipInfo = await page.textContent("pre");
console.log("IP Info:", ipInfo);
```
```python python
# Create session with advanced configuration
session_config = {
"session": {
"recording": False, # Disable session recording
"proxy": {
"active": True,
"type": "anchor_residential",
"country_code": "us"
},
"max_duration": 5, # 5 minutes
"idle_timeout": 1 # 1 minute
}
}
configured_session = anchor_client.sessions.create(session_config)
with anchor_client.browser.connect(configured_session.data.id) as configured_browser:
# Use the configured browser to check IP location
page = configured_browser.contexts[0].pages[0]
page.goto("https://httpbin.org/ip")
ip_info = page.text_content("pre")
print("IP Info:", ip_info)
```
## Key SDK Benefits
The Anchor Browser SDK provides several advantages over direct API usage:
* **AI Agent Integration**: Use natural language to automate complex browser tasks
* **Structured Data Extraction**: Define schemas and extract data in a predictable format
* **Seamless Playwright Integration**: Full access to Playwright's powerful browser automation capabilities
* **Session Management**: Easy creation and management of persistent browser sessions
* **Built-in Tools**: Screenshot capture, proxy management, and more
* **Type Safety**: Full TypeScript support with proper type definitions
## Next Steps
* Explore the [API Reference](/api-reference) for detailed documentation
* Learn about [Authentication and Identity](/essentials/authentication-and-identity) management
* Check out [Advanced Proxy Configuration](/advanced/proxy) for location-specific browsing
# Perform Web Task
Source: https://docs.anchorbrowser.io/sdk-reference/ai-tools/perform-web-task
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/tools/perform-web-task
Start from a URL and perform the given task.
# End All Sessions
Source: https://docs.anchorbrowser.io/sdk-reference/browser-sessions/end-all-sessions
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml delete /v1/sessions/all
Terminates all active browser sessions associated with the provided API key.
# End Browser Session
Source: https://docs.anchorbrowser.io/sdk-reference/browser-sessions/end-browser-session
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml delete /v1/sessions/{session_id}
Deletes the browser session associated with the provided browser session ID. Requires a valid API key for authentication.
# List All Sessions Status
Source: https://docs.anchorbrowser.io/sdk-reference/browser-sessions/list-all-sessions-status
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml get /v1/sessions/all/status
Retrieves status information for all browser sessions associated with the API key.
# List Session Downloads
Source: https://docs.anchorbrowser.io/sdk-reference/browser-sessions/list-session-downloads
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml get /v1/sessions/{session_id}/downloads
Retrieves metadata of files downloaded during a browser session. Requires a valid API key for authentication.
# Start Browser Session
Source: https://docs.anchorbrowser.io/sdk-reference/browser-sessions/start-browser-session
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions
Allocates a new browser session for the user, with optional configurations for ad-blocking, captcha solving, proxy usage, and idle timeout.
# Delete Extension
Source: https://docs.anchorbrowser.io/sdk-reference/extensions/delete-extension
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml delete /v1/extensions/{id}
Delete an extension and remove it from storage
# Get Extension Details
Source: https://docs.anchorbrowser.io/sdk-reference/extensions/get-extension-details
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml get /v1/extensions/{id}
Get details of a specific extension by its ID
# List Extensions
Source: https://docs.anchorbrowser.io/sdk-reference/extensions/list-extensions
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml get /v1/extensions
Get all extensions for the authenticated user
# Upload Extension
Source: https://docs.anchorbrowser.io/sdk-reference/extensions/upload-extension
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/extensions
Upload a new browser extension as a ZIP file. The extension will be validated and stored for use in browser sessions.
# Copy Selected Text
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/copy-selected-text
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/copy
Copies the currently selected text to the clipboard
# Drag and Drop
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/drag-and-drop
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/drag-and-drop
Performs a drag and drop operation from start coordinates to end coordinates
# Get Clipboard Content
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/get-clipboard-content
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml get /v1/sessions/{sessionId}/clipboard
Retrieves the current content of the clipboard
# Keyboard Shortcut
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/keyboard-shortcut
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/keyboard/shortcut
Performs a keyboard shortcut using the specified keys
# Mouse Click
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/mouse-click
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/mouse/click
Performs a mouse click at the specified coordinates
# Mouse Double Click
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/mouse-double-click
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/mouse/doubleClick
Performs a double click at the specified coordinates
# Mouse Down
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/mouse-down
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/mouse/down
Performs a mouse button down action at the specified coordinates
# Mouse Move
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/mouse-move
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/mouse/move
Moves the mouse cursor to the specified coordinates
# Mouse Up
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/mouse-up
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/mouse/up
Performs a mouse button up action at the specified coordinates
# Navigate to URL
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/navigate-to-url
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/goto
Navigates the browser session to the specified URL
# Paste Text
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/paste-text
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/paste
Pastes text at the current cursor position
# Scroll
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/scroll
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/scroll
Performs a scroll action at the specified coordinates
# Set Clipboard Content
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/set-clipboard-content
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/clipboard
Sets the content of the clipboard
# Take Screenshot
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/take-screenshot
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml get /v1/sessions/{sessionId}/screenshot
Takes a screenshot of the current browser session and returns it as an image.
# Type Text
Source: https://docs.anchorbrowser.io/sdk-reference/os-level-control/type-text
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{sessionId}/keyboard/type
Types the specified text with optional delay between keystrokes
# Create Profile
Source: https://docs.anchorbrowser.io/sdk-reference/profiles/create-profile
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/profiles
Creates a new profile from a browser session. A Profile stores cookies, local storage, and cache.
# Delete Profile
Source: https://docs.anchorbrowser.io/sdk-reference/profiles/delete-profile
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml delete /v1/profiles/{name}
Deletes an existing profile by its name.
# Get Profile
Source: https://docs.anchorbrowser.io/sdk-reference/profiles/get-profile
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml get /v1/profiles/{name}
Retrieves details of a specific profile by its name.
# List Profiles
Source: https://docs.anchorbrowser.io/sdk-reference/profiles/list-profiles
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml get /v1/profiles
Fetches all stored profiles.
# Update Profile
Source: https://docs.anchorbrowser.io/sdk-reference/profiles/update-profile
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml put /v1/profiles/{name}
Updates the description or data of an existing profile using a browser session.
# Get Session Recording
Source: https://docs.anchorbrowser.io/sdk-reference/session-recordings/get-session-recording
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml get /v1/sessions/{session_id}/recordings/primary/fetch
Downloads the primary recording file for the specified browser session. Returns the recording as an MP4 file.
# List Session Recordings
Source: https://docs.anchorbrowser.io/sdk-reference/session-recordings/list-session-recordings
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml get /v1/sessions/{session_id}/recordings
Retrieves the URLs of the browser session's video recordings. Requires a valid API key for authentication.
# Pause Session Recording
Source: https://docs.anchorbrowser.io/sdk-reference/session-recordings/pause-session-recording
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{session_id}/recordings/pause
Pauses the video recording for the specified browser session.
# Resume Session Recording
Source: https://docs.anchorbrowser.io/sdk-reference/session-recordings/resume-session-recording
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/sessions/{session_id}/recordings/resume
Resumes the video recording for the specified browser session.
# Get Webpage Content
Source: https://docs.anchorbrowser.io/sdk-reference/tools/get-webpage-content
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/tools/fetch-webpage
Retrieve the rendered content of a webpage, optionally formatted as Markdown or HTML.
# Screenshot Webpage
Source: https://docs.anchorbrowser.io/sdk-reference/tools/screenshot-webpage
https://app.stainless.com/api/spec/documented/anchorbrowser/openapi.documented.yml post /v1/tools/screenshot
This endpoint captures a screenshot of the specified webpage using Chromium. Users can customize the viewport dimensions and capture options.
# Trust & Security
Source: https://docs.anchorbrowser.io/security
Anchor was engineered from the ground up to be the definitive secure browser solution, empowering developers to deploy to production with confidence. We provide the essential security backbone and advanced capabilities required to build the next generation of browser-based workloads.
This document outlines the security framework of Anchor Browser, covering:
* The reasons why leading enterprises build their solutions on Anchor Browser.
* An overview of our comprehensive Security Architecture.
For a detailed report on our compliance and security posture, please visit the [Anchor Trust Portal](https://trust.anchorbrowser.io/)
## Why Enterprise solutions are built on Anchor Browser
Anchor Browser is the result of deep security expertise from industry veterans, with our team hailing from leaders in cybersecurity such as SentinelOne, Noname Security (acquired by Akamai), and various specialized intelligence units. This collective experience has allowed us to embed robust security capabilities directly into the browser, giving our customers a distinct advantage in enterprise trust, security, and compliance.
### 1. Advanced Features for a More Secure End Solution
* **Complete Browser Isolation & Disposal**: Anchor creates a dedicated, isolated virtual machine (VM) for each browser instance. This VM is permanently terminated and erased upon session completion, ensuring that browsers are never reused and data remnants are eliminated.
* **Official Headful Browser Environments**: As the sole provider of secured and sandboxed environments using the official "Headful" browser operation mode, Anchor runs browsers as they were designed to be run. This ensures maximum stability and leverages the most rigorously tested and penetration-tested browser architecture.
* **Integrated Domain & Network Guardrails**: Anchor implements default network protections to shield customers from malicious websites. We also offer the ability to define granular whitelists of allowed domains, providing precise control over network access at the browser level.
* **Secure Authentication & Credential Management**: With Anchor, customers are never required to store credentials on our platform. Our browsers enable authenticated workflows using secure, encrypted, session-based authentication, eliminating the risks associated with stored credential-based logins.
* **Strict Tenant Isolation**: Anchor enforces rigorous logical isolation between all tenants. This architectural constraint guarantees the integrity and confidentiality of each customer's data.
* **Secure Peer-to-Peer File Transfers**: Secure Peer-to-Peer File Transfers: Uniquely, Anchor facilitates secure file downloads through a peer-to-peer mechanism. File downloads initiated in the browser are transferred directly to the customer's environment, meaning no file artifacts are ever created or stored on Anchor's infrastructure.
### 2. A Secure-by-Design Architecture
Anchor is built on a secure-by-design methodology. This principle ensures that the default configuration is always the most secure, significantly reducing the risk of misconfiguration errors and providing a foundation of trust from the moment you start.
### 3. Shared Responsibility Model
Our shared responsibility model clearly defines the security obligations of both Anchor and our customers. This well defined ownership perimeter approach ensures that all aspects of security are managed effectively, from the underlying infrastructure we secure to the applications you build on top of it.
### 4. Vetted and Audited Supply Chain
We maintain a rigorous security review and auditing process for our entire supply chain. Every component and third-party vendor is scrutinized to ensure they meet our high security standards, protecting our platform and our customers from upstream vulnerabilities.
## Product Architecture & Security Design
### Critical Security Controls
#### Storage of customer data
A core principle of Anchor Browser is minimizing data persistence. By design, we do not store customer data from within the browser sessions. Each browser instance runs in a dedicated, ephemeral virtual machine that is completely destroyed upon session termination. This means that any data accessed, generated, or downloaded during a session is either transferred directly to the customer's own environment via our secure peer-to-peer capability or is irretrievably deleted with the virtual machine. The only customer data we store is essential account and configuration information required for providing our service, such as user roles and network guardrail settings.
#### Confidentiality & Protection of Customer Data
We enforce strict measures to ensure the confidentiality and integrity of all customer data and platform interactions.
* Strict Tenant Isolation: Our architecture guarantees that each customer's browser instances are logically and physically isolated from one another. There is no possibility of cross-tenant data access.
* Ephemeral Environments: Browsers are never reused between sessions or customers. Every session starts with a pristine, isolated browser instance that is terminated and wiped clean after use, eliminating the risk of data leakage.
* Principle of Least Privilege: Access to all systems and data is governed by the principle of least privilege. Our employees are only granted the minimum level of access necessary to perform their job functions.
#### Data Encryption
Anchor employs robust encryption protocols to protect data at every stage.
* Encryption in Transit: All data transmitted between your local machine and the Anchor Browser instance, as well as any communication with our platform services, is encrypted using industry-standard TLS 1.2 or higher. We enforce the use of strong cipher suites to protect against eavesdropping and man-in-the-middle attacks.
* Encryption at Rest: While we minimize data storage, any essential configuration data or account information stored on our platform is encrypted at rest using AES-256, one of the strongest block ciphers available.
#### Reliability, Backup, and Business Continuity
Anchor is architected for high availability and resilience to ensure uninterrupted service.
* Redundant Architecture: Our infrastructure is deployed across multiple availability zones within our cloud provider's environment. This design protects against single-point-of-failure scenarios and ensures high uptime.
* Automated Backups: We perform regular, automated backups of critical platform configuration data. These backups are encrypted and stored securely, allowing for swift recovery in the unlikely event of a major disruption.
* Disaster Recovery: We maintain a comprehensive business continuity and disaster recovery plan that is regularly tested. This plan ensures that we can restore critical operations within a defined Recovery Time Objective (RTO).
#### Return of Customer Data
Given our ephemeral architecture, there is no session data to return. Any files downloaded during a session are transferred directly to your premises. As for your account and configuration data, you can request a copy of this information at any time during your service agreement. Upon termination of your contract, all associated account data will be permanently deleted from our systems in accordance with our data retention policy.
#### Certifications
Anchor is committed to meeting and exceeding industry standards for security and compliance. We are actively working towards achieving key certifications to formally validate our security controls. For the most up-to-date information on our certification status, please visit the Anchor Trust Portal.
#### Audits
Anchor engages independent, third-party auditors to conduct regular penetration tests and security assessments of our platform. These rigorous audits help us identify and remediate potential vulnerabilities, ensuring our defenses remain robust against emerging threats. A summary of our latest audit findings can be made available to customers upon request and under a Non-Disclosure Agreement (NDA).
#### Security Logs
We maintain detailed security logs to monitor for and investigate any suspicious activity.
* Audit Trails: We capture comprehensive audit logs of all administrative actions taken within the Anchor platform, such as changes to user permissions or security settings. Access to these logs is restricted to authorized personnel.
* Immutable Logging: Logs are stored in a secure, tamper-evident manner to ensure their integrity for forensic analysis and compliance purposes.
#### Personnel Practices
Our commitment to security extends to our internal team and practices.
* Security Training: We conduct mandatory security awareness training for all employees upon hiring and on an ongoing basis. This training covers data privacy, threat detection, and secure coding practices.
* Access Control: Access to our production environment is strictly controlled and limited to a small number of authorized engineers. We enforce multi-factor authentication (MFA) for all internal systems to add a critical layer of security.