Files
browser-use/skills/cloud/references/features.md

5.3 KiB

Cloud Features

Table of Contents


Proxies & Stealth

Stealth is on by default — anti-fingerprinting, CAPTCHA solving, ad/cookie blocking, Cloudflare bypass.

Residential Proxies (195+ Countries)

Default: US residential proxy always active.

# Common countries
session = await client.sessions.create(proxy_country_code="us")  # or gb, de, fr, jp, au, br, in, kr, ca, es, it, nl, se, sg...

Custom Proxy (HTTP or SOCKS5)

from browser_use_sdk import CustomProxy

session = await client.sessions.create(
    custom_proxy=CustomProxy(
        url="http://proxy-host:8080",
        username="user",
        password="pass",
    )
)
session = await client.sessions.create(proxy_country_code=None)

Webhooks

Real-time notifications when tasks complete.

Events

Event Description
agent.task.status_update Task status changed (started/finished/stopped)
test Test webhook delivery

Payload

{
  "type": "agent.task.status_update",
  "timestamp": "2025-01-15T10:30:00Z",
  "payload": {
    "task_id": "task_abc123",
    "session_id": "session_xyz",
    "status": "finished",
    "metadata": {}
  }
}

Signature Verification (HMAC-SHA256)

Headers: X-Browser-Use-Signature, X-Browser-Use-Timestamp

The signature is computed over {timestamp}.{body} where body is JSON with sorted keys and no extra whitespace. Reject requests older than 5 minutes to prevent replay attacks.

import hmac, hashlib, json, time

def verify_webhook(body: bytes, signature: str, timestamp: str, secret: str) -> bool:
    # Reject requests older than 5 minutes
    try:
        ts = int(timestamp)
    except (ValueError, TypeError):
        return False
    if abs(time.time() - ts) > 300:
        return False
    try:
        payload = json.loads(body)
    except (json.JSONDecodeError, ValueError):
        return False
    message = f"{timestamp}.{json.dumps(payload, separators=(',', ':'), sort_keys=True)}"
    expected = hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

Workspaces

Persistent file storage across sessions (v3 API). Max 10 files per upload.

from browser_use_sdk.v3 import AsyncBrowserUse
client = AsyncBrowserUse()

# Create workspace
workspace = await client.workspaces.create(name="my-data")

# Create a session
session = await client.sessions.create()

# Upload files before task
await client.sessions.upload_files(
    session.id,
    workspace_id=workspace.id,
    files=[open("input.pdf", "rb")]
)

# Download files after task
files = await client.sessions.files(session.id)
for f in files:
    url = f.download_url  # Presigned URL (60s expiry)

# Manage workspaces
workspaces = await client.workspaces.list()
await client.workspaces.delete(workspace.id)

Skills

Turn website interactions into reusable, deterministic API endpoints.

Anatomy

  • Goal: Full spec with parameters and return data
  • Demonstration: agent_prompt showing how to perform the task once

Create & Execute

# Create (~30s, $2 PAYG)
skill = await client.skills.create(
    goal="Extract product price from Amazon",
    demonstration="Navigate to product page, find price element..."
)

# Execute ($0.02 PAYG)
result = await client.skills.execute(skill.id, params={"url": "https://amazon.com/dp/..."})

# Refine (free)
await client.skills.refine(skill.id, feedback="Also extract the rating")

Marketplace

skills = await client.marketplace.list()
cloned = await client.marketplace.clone(skill_id)
result = await client.marketplace.execute(skill_id, params={})

Browse at cloud.browser-use.com/skills.

Load Skills in Local Agent

agent = Agent(
    task="...",
    skills=['skill-uuid-1', 'skill-uuid-2'],  # or ['*'] for all
    llm=ChatBrowserUse()
)

MCP Server

HTTP-based MCP at https://api.browser-use.com/mcp

Tool Cost Description
browser_task $0.01 + per-step Run automation task
execute_skill $0.02 Execute skill
list_skills Free List skills
get_cookies Free Get cookies
list_browser_profiles Free List profiles
monitor_task Free Check task progress

Setup: See references/open-source/integrations.md for Claude/Cursor/Windsurf config.


Live View

Human Takeover

Pause agent, let human take over via liveUrl:

session = await client.sessions.create(keep_alive=True)  # v3
await client.run("Navigate to checkout", session_id=session.id)
# Agent pauses at checkout

print(session.live_url)  # Human opens this, enters payment details

await client.run("Confirm the order", session_id=session.id)
await client.sessions.stop(session.id)

liveUrl gives full mouse/keyboard control.

Iframe Embed

Embed live view in your app — no X-Frame-Options or CSP restrictions:

<iframe
  src="{session.live_url}"
  width="1280"
  height="720"
  style="border: none;"
></iframe>

No polling needed — updates in real-time.