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
broautonomously navigate and extract structured data on the fly. - Manual: 🕹️ Get full, deterministic control of the browser via agent-friendly commands.
- Autopilot: 🤖 Let
- 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:
- Sign up manually via UI: Visit https://getbro.ws/auth to sign up and get your API token.
- Sign Up with Agent: If you want your AI agent to sign up on your behalf, just give it this prompt: https://getbro.ws/signup_prompt.md
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:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55e7f28fb9c5a0e6944f12e5c6bf0b10d00f925e0dccc59d1fa3c1ffb37e6559
|
|
| MD5 |
2fe1e10d694ebfe120dd3261b68c5c84
|
|
| BLAKE2b-256 |
d8c38e24d368e449bc46bfa03c268a3f853e859169a07cfaf954aabadd327896
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c5b2b341986a57f85fd84030416347c9e87eebc568b9dfd1004fd2a1776ee6b
|
|
| MD5 |
7f935f5e0e44495724b50dcc5387bd39
|
|
| BLAKE2b-256 |
c0f27e7b4d17aadf593631d022b827ae7bce3e20f268f8707e135b5d441571b6
|