Skip to main content

The browser layer for AI agents, workflows, and data pipelines.

Project description

bro-sdk

🔮 We've abstracted away the chaos of the web so you can focus on building.

bro is a stealth agentic browser built to handle everything from everyday pages to the most complex and well-protected websites. It lets you and your agents reliably navigate the web and extract data at scale without getting blocked.

Instead of juggling low-level CDP commands, managing infrastructure and handling proxies, you control a fully headed, actual rendered Chrome browser through a simple, agents-friendly Python library. Every session runs on an isolated VM instance - you don't share compute resources or IPs.

Features

  • Zero-headache API: 🧘‍♂️ Whether you're navigating, extracting data or parsing DOM, every command has complex underlying logic built-in - it keeps the agent in a single tab, handles dynamic page loads, automatically retries failures, handles downloads, manages timeouts and CDP syncs.
  • Two powerful modes:
    • Autopilot: 🤖 Let bro autonomously navigate and extract structured data on the fly.
    • Manual: 🕹️ Get full, deterministic control of the browser via agent-friendly commands.
  • Stealth features: 🥷 Clean browser fingerprints, human-like interaction, customizable network routing, and proxy tracking.
  • Flexible & cost-effective: 📉 Cut costs by customizing proxy and AI configurations based on your specific task.

Installation

Install the package via pip (requires Python 3.8+):

pip install bro-sdk

Getting a Token (Sign Up)

To use the bro-sdk, you need an API key. You can get one by signing up:

Quick Start Examples

Below are a couple of examples showcasing how easy it is to use bro to handle the browser. Both use a straightforward session context manager that handles all lifecycle and cleanup automatically.

1. Parsing Text and URLs

Extracting clean text and URLs directly from the rendered page layout.

from bro import BroClient, commands

# Initialize the client
client = BroClient(api_key="your_api_key_here")

# Use a context manager to ensure the session is properly stopped
with client.create_session() as session:
    print(f"Session started: {session.session_id}")
    
    # Execute commands sequentially in a batch
    result = session.execute([
        commands.open_url(url="https://news.ycombinator.com/"),
        commands.parse_text(),
        commands.parse_urls()
    ])
    
    if result.get("status") == "done":
        # parse_text returns a raw string natively
        print("--- Text ---")
        print(result["response"]["commands"][1]["data"])
        
        # parse_urls returns a dictionary containing 'links' and 'images' arrays
        print("--- URLs ---")
        print(result["response"]["commands"][2]["data"])

print(f"\n--- Session Usage Stats ---")
if session.billing:
    print(f"Total billed: ${session.billing.get('total_billed', 0):.4f}")

2. Extracting data using Autopilot extract command

If you already have a target URL, you can extract structured data directly, including automatically clicking "Next" to traverse multiple pages. The AI will analyze the DOM and visual data on the page to extract JSON for you based on your schema.

import json
from bro import BroClient, commands

client = BroClient(api_key="your_api_key_here")

with client.create_session() as session:
    print(f"Session started: {session.session_id}")
    
    result = session.execute([
        commands.open_url(url="https://news.ycombinator.com/"),
        commands.extract(
            data_instruction="Extract a list of top publications on this page",
            json_schema=[{
                "title": "<post title>",
                "link": "<post URL>",
                "points": "<number of points>"
            }],
            model_size="medium",
            paginate=True,         # Let AI find the 'Next' button and merge data
            pages_to_paginate=2    # Max pages to navigate through
        )
    ])
    
    if result.get("status") == "done":
        for cmd in result.get("response", {}).get("commands", []):
            if cmd.get("command") == "extract":
                print(f"\nExtracted Data:\n{json.dumps(cmd.get('data'), indent=2)}")

print(f"\n--- Session Usage Stats ---")
if session.billing:
    print(f"Total billed: ${session.billing.get('total_billed', 0):.4f}")
if session.tokens:
    print(f"LLM Tokens: {session.tokens.get('total', 0)}")

3. AI Actions & Data Extraction

You can combine commands to navigate complex flows before extracting data. This example uses Autopilot to type into a search box, press enter, and extract the top results.

import json
from bro import BroClient, commands

client = BroClient(api_key="your_api_key_here")

with client.create_session(
    enable_proxy=True,
    proxy_tier="basic",
    proxy_policy="extended",
    country="US"
) as session:
    session_id = session.session_id
    print(f"Session started: {session.session_id}, stream: {session.stream_url}")
    
    print("\nExecuting commands")
    batch_result = session.execute([
        commands.open_url(url="https://news.ycombinator.com"),
        commands.act(
            instruction="type 'llm' in the search box",
            max_steps=2,
            model_size='medium'
        ),
        commands.press(keys='enter'),
        commands.extract(
            data_instruction="Extract the top 5 news titles and their links.",
            json_schema=[{
                "title": "<title of the publication>",
                "url": "<direct URL to the publication>",
                "summary": "<summary of the publication, less than 10 words>",
                "company_mentioned": "<company name mentioned in the publication, set a primary company if multiple have been mentioned>",
            }],
            model_size="small"
        )
    ])
    
    if batch_result["status"] == "done":
        commands_executed = batch_result.get("response", {}).get("commands", [])
        for i, cmd in enumerate(commands_executed):
            cmd_name = cmd.get("command", "unknown")
            data = cmd.get("data", {})
            
            if cmd_name == "extract":
                output = data.get("extracted_json")
            elif cmd_name == "act":
                output = data.get("action_steps")
            else:
                output = data
                
            print(f"\n--- [{i}] {cmd_name.upper()} ---")
            print(json.dumps(output, indent=2))

if session_id:
    print("\n--- Final Session Stats ---")
    final_stats = client.get_session(session_id).metadata
    print(json.dumps(final_stats, indent=2))

Full Documentation

For the comprehensive SDK documentation, including all available commands, API references, advanced configurations, and integrations, please visit:

👉 Full SDK Docs

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bro_api_sdk-0.1.0.tar.gz (23.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bro_api_sdk-0.1.0-py3-none-any.whl (22.4 kB view details)

Uploaded Python 3

File details

Details for the file bro_api_sdk-0.1.0.tar.gz.

File metadata

  • Download URL: bro_api_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 23.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for bro_api_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 55e7f28fb9c5a0e6944f12e5c6bf0b10d00f925e0dccc59d1fa3c1ffb37e6559
MD5 2fe1e10d694ebfe120dd3261b68c5c84
BLAKE2b-256 d8c38e24d368e449bc46bfa03c268a3f853e859169a07cfaf954aabadd327896

See more details on using hashes here.

File details

Details for the file bro_api_sdk-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: bro_api_sdk-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 22.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for bro_api_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8c5b2b341986a57f85fd84030416347c9e87eebc568b9dfd1004fd2a1776ee6b
MD5 7f935f5e0e44495724b50dcc5387bd39
BLAKE2b-256 c0f27e7b4d17aadf593631d022b827ae7bce3e20f268f8707e135b5d441571b6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page