Event logs are runtime data, not source code. Also adds mem compact command and browser-use + memory-service knowledge.
187 lines
5.4 KiB
Markdown
187 lines
5.4 KiB
Markdown
# browser-use — AI Browser Automation
|
|
|
|
## What It Is
|
|
- AI agent that controls a real browser via CDP (Chrome DevTools Protocol).
|
|
- Describe task in natural language → agent clicks, types, navigates, extracts data.
|
|
- Python library for code-level automation OR CLI for agent integration (Claude Code, Cursor, etc).
|
|
- Open source, self-hosted. Optional cloud for stealth/scaling.
|
|
|
|
## Installation
|
|
```bash
|
|
# Python library
|
|
uv add browser-use
|
|
# or: pip install browser-use
|
|
|
|
# CLI (via uvx, no install needed)
|
|
uvx browser-use
|
|
|
|
# Install Chromium + dependencies
|
|
browser-use install
|
|
|
|
# Register skill for coding agents
|
|
browser-use skill install
|
|
```
|
|
|
|
## CLI Usage
|
|
```bash
|
|
# Run inline Python with pre-imported helpers
|
|
browser-use <<'PY'
|
|
new_tab("https://example.com")
|
|
print(page_info())
|
|
PY
|
|
|
|
# Check local Chrome connection
|
|
browser-use --doctor
|
|
|
|
# macOS: approve remote debugging permission
|
|
browser-use mac-approve
|
|
|
|
# Auth for cloud browsers
|
|
browser-use auth login
|
|
```
|
|
|
|
## Python Library — Basic Agent
|
|
```python
|
|
import asyncio
|
|
from browser_use import Agent, ChatBrowserUse
|
|
|
|
async def main():
|
|
agent = Agent(
|
|
task="Find the price of iPhone 16 on Amazon",
|
|
llm=ChatBrowserUse(model='openai/gpt-5.5'),
|
|
)
|
|
result = await agent.run()
|
|
print(result)
|
|
|
|
asyncio.run(main())
|
|
```
|
|
|
|
## Structured Output
|
|
```python
|
|
from pydantic import BaseModel, Field
|
|
from browser_use import Agent, ChatBrowserUse
|
|
|
|
class ProductInfo(BaseModel):
|
|
title: str = Field(..., description='Product name')
|
|
price: float = Field(..., description='Price as number')
|
|
url: str = Field(..., description='Product URL')
|
|
|
|
agent = Agent(
|
|
task="Find the top 3 results for 'mechanical keyboard' on Amazon",
|
|
llm=ChatBrowserUse(model='bu-2-0-mini-preview'),
|
|
output_model_schema=ProductInfo,
|
|
)
|
|
result = asyncio.run(agent.run())
|
|
if result and result.structured_output:
|
|
print(result.structured_output)
|
|
```
|
|
|
|
## Connect to Existing Browser
|
|
```python
|
|
from browser_use import Agent, Browser, ChatBrowserUse
|
|
|
|
# Connect to local Chrome with CDP
|
|
browser = Browser(cdp_url='http://localhost:9222')
|
|
agent = Agent(browser=browser, llm=ChatBrowserUse(), task="...")
|
|
```
|
|
|
|
## CLI Helper Functions
|
|
Pre-imported in `browser-use` CLI context:
|
|
- `new_tab(url)` — open URL in new tab (first navigation per task)
|
|
- `goto_url(url)` — navigate current tab
|
|
- `page_info()` — get current page info
|
|
- `current_tab()` — get current tab info
|
|
- `list_tabs()` — list all open tabs
|
|
- `switch_tab(target)` — switch to existing tab
|
|
- `activate_tab(target)` — bring tab to foreground
|
|
- `click_at_xy(x, y)` — click at viewport coordinates
|
|
- `js(code)` — execute JavaScript in page
|
|
- `wait_for_load()` — wait for page load after navigation
|
|
- `ensure_real_tab()` — skip internal/stale tabs
|
|
- `cdp("Domain.method", ...)` — raw CDP command
|
|
- `start_recording(name)` / `stop_recording()` — record session
|
|
|
|
## Remote/Cloud Browsers
|
|
```bash
|
|
# Start remote browser (for parallel tasks or stealth)
|
|
browser-use <<'PY'
|
|
start_remote_daemon("my-task")
|
|
PY
|
|
|
|
# Use remote browser
|
|
BU_NAME=my-task browser-use <<'PY'
|
|
new_tab("https://example.com")
|
|
print(page_info())
|
|
PY
|
|
|
|
# Stop when done (billed until stopped)
|
|
browser-use <<'PY'
|
|
stop_remote_daemon("my-task")
|
|
PY
|
|
```
|
|
|
|
## Page Interaction Workflow
|
|
1. Find elements via accessibility tree: `cdp("Accessibility.getFullAXTree")["nodes"]`
|
|
2. Get coordinates: `cdp("DOM.getBoxModel", backendNodeId=n)` → compute center
|
|
3. Click: `click_at_xy(x, y)`
|
|
4. Verify: `js(...)` or `page_info()` to confirm action
|
|
5. Fallback to raw HTML via `js(...)` only when AX tree lacks element
|
|
|
|
## When to Use browser-use vs curl
|
|
- **Use curl**: public pages, APIs, static content, docs
|
|
- **Use browser-use**: login-required pages, JS-rendered content, form filling, clicking, bot-protected sites, interactive workflows
|
|
|
|
## Environment Variables
|
|
- `BROWSER_USE_API_KEY` — API key for ChatBrowserUse or cloud
|
|
- `BU_NAME` — name for remote daemon
|
|
- `BU_CDP_URL` — custom CDP endpoint
|
|
- `BH_DOMAIN_SKILLS=1` — enable domain-specific skills
|
|
- `BH_AGENT_WORKSPACE` — path to agent workspace with helpers
|
|
|
|
## Recordings
|
|
```bash
|
|
# Enable/disable background recording
|
|
browser-use recordings enable
|
|
browser-use recordings disable
|
|
|
|
# View latest recording
|
|
browser-use recordings --latest
|
|
```
|
|
|
|
## Common Use Cases
|
|
- Fill job applications with resume data
|
|
- Extract structured data from websites (followers, products, prices)
|
|
- Compare prices across multiple sites
|
|
- Automate checkout flows
|
|
- Screenshot pages for verification
|
|
- QA testing of web applications
|
|
- Monitor website changes
|
|
|
|
## Integration with Verification Workflow
|
|
```bash
|
|
# After deploying an API, verify it works via browser
|
|
browser-use <<'PY'
|
|
new_tab("https://api.riotpiao.com/health")
|
|
info = page_info()
|
|
print(info) # Should show {"status": "ok"}
|
|
PY
|
|
|
|
# Verify UI renders correctly after deployment
|
|
browser-use <<'PY'
|
|
new_tab("https://myapp.riotpiao.com")
|
|
wait_for_load()
|
|
# Check page title
|
|
title = js("document.title")
|
|
print(f"Page title: {title}")
|
|
PY
|
|
```
|
|
|
|
## Gotchas
|
|
- First navigation per task must use `new_tab(url)`, not `goto_url(url)`
|
|
- Don't open duplicate tabs — check `list_tabs()` first
|
|
- Login walls: stop and ask user. Exception: SSO if already signed in
|
|
- `chrome://inspect/#remote-debugging` must be enabled for local Chrome
|
|
- CDP target order ≠ Chrome's visible tab-strip order
|
|
- Always call `wait_for_load()` after navigation
|
|
- Cloud browsers bill until stopped — always `stop_remote_daemon()` when done
|