ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
---
|
||||
title: "Authentication"
|
||||
description: "Learn how to authenticate with the Browser Use Cloud API"
|
||||
icon: "lock"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
The Browser Use Cloud API uses API keys to authenticate requests. You can obtain an API key from your [Browser Use Cloud dashboard](https://cloud.browser-use.com/settings/api-keys).
|
||||
|
||||
## API Keys
|
||||
|
||||
All API requests must include your API key in the `Authorization` header:
|
||||
|
||||
```bash
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
```
|
||||
|
||||
Keep your API keys secure and do not share them in publicly accessible areas such as GitHub, client-side code, or in your browser's developer tools. API keys should be stored securely in environment variables or a secure key management system.
|
||||
|
||||
## Example Request
|
||||
|
||||
Here's an example of how to include your API key in a request using Python:
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
API_KEY = 'your_api_key_here'
|
||||
BASE_URL = 'https://api.browser-use.com/api/v1'
|
||||
HEADERS = {'Authorization': f'Bearer {API_KEY}'}
|
||||
|
||||
response = requests.get(f'{BASE_URL}/me', headers=HEADERS)
|
||||
print(response.json())
|
||||
```
|
||||
|
||||
## Verifying Authentication
|
||||
|
||||
You can verify that your API key is valid by making a request to the `/api/v1/me` endpoint. See the [Me endpoint documentation](/api-reference/api-v1/me) for more details.
|
||||
|
||||
## API Key Security
|
||||
|
||||
To ensure the security of your API keys:
|
||||
|
||||
1. **Never share your API key** in publicly accessible areas
|
||||
2. **Rotate your API keys** periodically
|
||||
3. **Use environment variables** to store API keys in your applications
|
||||
4. **Implement proper access controls** for your API keys
|
||||
5. **Monitor API key usage** for suspicious activity
|
||||
|
||||
If you believe your API key has been compromised, you should immediately revoke it and generate a new one from your Browser Use Cloud dashboard.
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
title: "Cloud SDK"
|
||||
description: "Learn how to set up your own Browser Use Cloud SDK"
|
||||
icon: "code"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
This guide walks you through setting up your own Browser Use Cloud SDK.
|
||||
|
||||
## Building your own client (OpenAPI)
|
||||
|
||||
<Note>
|
||||
This approach is recommended **only** if you need to run simple tasks and
|
||||
**don’t require fine-grained control**.
|
||||
</Note>
|
||||
|
||||
The best way to build your own client is to use our [OpenAPI specification](http://api.browser-use.com/openapi.json) to generate a type-safe client library.
|
||||
|
||||
### Python
|
||||
|
||||
Use [openapi-python-client](https://github.com/openapi-generators/openapi-python-client) to generate a modern Python client:
|
||||
|
||||
```bash
|
||||
# Install the generator
|
||||
pipx install openapi-python-client --include-deps
|
||||
|
||||
# Generate the client
|
||||
openapi-python-client generate --url http://api.browser-use.com/openapi.json
|
||||
```
|
||||
|
||||
This will create a Python package with full type hints, modern dataclasses, and async support.
|
||||
|
||||
### TypeScript/JavaScript
|
||||
|
||||
Use [OpenAPI TS](https://openapi-ts.dev/) library to generate a type safe TypeScript client for the Browser Use API.
|
||||
|
||||
The following guide shows how to create a simple type-safe `fetch` client, but you can also use other generators.
|
||||
|
||||
- React Query - https://openapi-ts.dev/openapi-react-query/
|
||||
- SWR - https://openapi-ts.dev/swr-openapi/
|
||||
|
||||
|
||||
<CodeGroup>
|
||||
```bash npm
|
||||
npm install openapi-fetch
|
||||
npm install -D openapi-typescript typescript
|
||||
```
|
||||
|
||||
```bash yarn
|
||||
yarn add openapi-fetch
|
||||
yarn add -D openapi-typescript typescript
|
||||
```
|
||||
```bash pnpm
|
||||
pnpm add openapi-fetch
|
||||
pnpm add -D openapi-typescript typescript
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
```json title="package.json"
|
||||
{
|
||||
"scripts": {
|
||||
"openapi:gen": "openapi-typescript https://api.browser-use.com/openapi.json -o ./src/lib/api/v1.d.ts"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
pnpm openapi:gen
|
||||
```
|
||||
|
||||
```ts
|
||||
// client.ts
|
||||
|
||||
'use client'
|
||||
|
||||
import createClient from 'openapi-fetch'
|
||||
import { paths } from '@/lib/api/v1'
|
||||
|
||||
export type Client = ReturnType<typeof createClient<paths>>
|
||||
|
||||
export const client = createClient<paths>({
|
||||
baseUrl: 'https://api.browser-use.com/',
|
||||
|
||||
// NOTE: You can get your API key from https://cloud.browser-use.com/billing!
|
||||
headers: { Authorization: `Bearer ${apiKey}` },
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
<Note>
|
||||
Need help? Contact our support team at support@browser-use.com or join our
|
||||
[Discord community](https://link.browser-use.com/discord)
|
||||
</Note>
|
||||
@@ -0,0 +1,199 @@
|
||||
---
|
||||
title: "V1 Implementation"
|
||||
description: "Learn how to implement the Browser Use API in Python"
|
||||
icon: "code"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
This guide shows how to implement common API patterns using Python. We'll create a complete example that creates and monitors a browser automation task.
|
||||
|
||||
## Basic Implementation
|
||||
|
||||
For all settings see [Run Task](/api-reference/api-v1/run-task).
|
||||
|
||||
Here's a simple implementation using Python's `requests` library to stream the task steps:
|
||||
|
||||
```python
|
||||
import json
|
||||
import time
|
||||
|
||||
import requests
|
||||
|
||||
API_KEY = 'your_api_key_here'
|
||||
BASE_URL = 'https://api.browser-use.com/api/v1'
|
||||
HEADERS = {'Authorization': f'Bearer {API_KEY}'}
|
||||
|
||||
|
||||
def create_task(instructions: str):
|
||||
"""Create a new browser automation task"""
|
||||
response = requests.post(f'{BASE_URL}/run-task', headers=HEADERS, json={'task': instructions})
|
||||
return response.json()['id']
|
||||
|
||||
|
||||
def get_task_status(task_id: str):
|
||||
"""Get current task status"""
|
||||
response = requests.get(f'{BASE_URL}/task/{task_id}/status', headers=HEADERS)
|
||||
return response.json()
|
||||
|
||||
|
||||
def get_task_details(task_id: str):
|
||||
"""Get full task details including output"""
|
||||
response = requests.get(f'{BASE_URL}/task/{task_id}', headers=HEADERS)
|
||||
return response.json()
|
||||
|
||||
|
||||
def wait_for_completion(task_id: str, poll_interval: int = 2):
|
||||
"""Poll task status until completion"""
|
||||
count = 0
|
||||
unique_steps = []
|
||||
while True:
|
||||
details = get_task_details(task_id)
|
||||
new_steps = details['steps']
|
||||
# use only the new steps that are not in unique_steps.
|
||||
if new_steps != unique_steps:
|
||||
for step in new_steps:
|
||||
if step not in unique_steps:
|
||||
print(json.dumps(step, indent=4))
|
||||
unique_steps = new_steps
|
||||
count += 1
|
||||
status = details['status']
|
||||
|
||||
if status in ['finished', 'failed', 'stopped']:
|
||||
return details
|
||||
time.sleep(poll_interval)
|
||||
|
||||
|
||||
def main():
|
||||
task_id = create_task('Open https://www.google.com and search for openai')
|
||||
print(f'Task created with ID: {task_id}')
|
||||
task_details = wait_for_completion(task_id)
|
||||
print(f"Final output: {task_details['output']}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
```
|
||||
|
||||
## Task Control Example
|
||||
|
||||
Here's how to implement task control with pause/resume functionality:
|
||||
|
||||
```python
|
||||
def control_task():
|
||||
# Create a new task
|
||||
task_id = create_task("Go to google.com and search for Browser Use")
|
||||
|
||||
# Wait for 5 seconds
|
||||
time.sleep(5)
|
||||
|
||||
# Pause the task
|
||||
requests.put(f"{BASE_URL}/pause-task?task_id={task_id}", headers=HEADERS)
|
||||
print("Task paused! Check the live preview.")
|
||||
|
||||
# Wait for user input
|
||||
input("Press Enter to resume...")
|
||||
|
||||
# Resume the task
|
||||
requests.put(f"{BASE_URL}/resume-task?task_id={task_id}", headers=HEADERS)
|
||||
|
||||
# Wait for completion
|
||||
result = wait_for_completion(task_id)
|
||||
print(f"Task completed with output: {result['output']}")
|
||||
```
|
||||
|
||||
## Structured Output Example
|
||||
|
||||
Here's how to implement a task with structured JSON output:
|
||||
|
||||
```python
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
import requests
|
||||
from pydantic import BaseModel
|
||||
from typing import List
|
||||
|
||||
|
||||
API_KEY = os.getenv("API_KEY")
|
||||
BASE_URL = 'https://api.browser-use.com/api/v1'
|
||||
HEADERS = {
|
||||
"Authorization": f"Bearer {API_KEY}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
|
||||
# Define output schema using Pydantic
|
||||
class SocialMediaCompany(BaseModel):
|
||||
name: str
|
||||
market_cap: float
|
||||
headquarters: str
|
||||
founded_year: int
|
||||
|
||||
|
||||
class SocialMediaCompanies(BaseModel):
|
||||
companies: List[SocialMediaCompany]
|
||||
|
||||
|
||||
def create_structured_task(instructions: str, schema: dict):
|
||||
"""Create a task that expects structured output"""
|
||||
payload = {
|
||||
"task": instructions,
|
||||
"structured_output_json": json.dumps(schema)
|
||||
}
|
||||
response = requests.post(f"{BASE_URL}/run-task", headers=HEADERS, json=payload)
|
||||
response.raise_for_status()
|
||||
return response.json()["id"]
|
||||
|
||||
|
||||
def wait_for_task_completion(task_id: str, poll_interval: int = 5):
|
||||
"""Poll task status until it completes"""
|
||||
while True:
|
||||
response = requests.get(f"{BASE_URL}/task/{task_id}/status", headers=HEADERS)
|
||||
response.raise_for_status()
|
||||
status = response.json()
|
||||
if status == "finished":
|
||||
break
|
||||
elif status in ["failed", "stopped"]:
|
||||
raise RuntimeError(f"Task {task_id} ended with status: {status}")
|
||||
print("Waiting for task to finish...")
|
||||
time.sleep(poll_interval)
|
||||
|
||||
|
||||
def fetch_task_output(task_id: str):
|
||||
"""Retrieve the final task result"""
|
||||
response = requests.get(f"{BASE_URL}/task/{task_id}", headers=HEADERS)
|
||||
response.raise_for_status()
|
||||
return response.json()["output"]
|
||||
|
||||
|
||||
def main():
|
||||
schema = SocialMediaCompanies.model_json_schema()
|
||||
task_id = create_structured_task(
|
||||
"Get me the top social media companies by market cap",
|
||||
schema
|
||||
)
|
||||
print(f"Task created with ID: {task_id}")
|
||||
|
||||
wait_for_task_completion(task_id)
|
||||
print("Task completed!")
|
||||
|
||||
output = fetch_task_output(task_id)
|
||||
print("Raw output:", output)
|
||||
|
||||
try:
|
||||
parsed = SocialMediaCompanies.model_validate_json(output)
|
||||
print("Parsed output:")
|
||||
print(parsed)
|
||||
except Exception as e:
|
||||
print(f"Failed to parse structured output: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
<Note>
|
||||
Remember to handle your API key securely and implement proper error handling
|
||||
in production code.
|
||||
</Note>
|
||||
@@ -0,0 +1,393 @@
|
||||
---
|
||||
title: "N8N + Browser Use Cloud"
|
||||
description: "Learn how to integrate Browser Use Cloud API with n8n using a practical workflow example (competitor research)."
|
||||
icon: "plug"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
> **TL;DR** – In **3 minutes** you can have an n8n workflow that:
|
||||
>
|
||||
> 1. Shows a form asking for a competitor’s name
|
||||
> 2. Starts a Browser Use task that crawls the web and extracts **pricing, jobs, new features & announcements**
|
||||
> 3. Waits for the task to finish via a **webhook**
|
||||
> 4. Formats the output and drops a rich message into Slack
|
||||
|
||||
You can grab the workflow JSON below – copy it and import it into n8n, plug in your API keys and hit _Execute_ 🚀.
|
||||
|
||||
---
|
||||
|
||||
## Why use Browser Use in n8n?
|
||||
|
||||
• **Autonomous browsing** – Browser Use opens pages like a real user, follows links, clicks buttons and reads DOM content.
|
||||
|
||||
• **Structured output** – You tell the agent _exactly_ which fields you need. No brittle regex or XPaths.
|
||||
|
||||
• **Scales effortlessly** – Kick off hundreds of tasks and monitor them through the Cloud API.
|
||||
|
||||
n8n glues everything together so your team gets the data instantly—no Python scripts or CRON jobs needed.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. **Browser Use Cloud API key** – grab one from your [Billing page](https://cloud.browser-use.com/billing).
|
||||
2. **n8n instance** – self-hosted or n8n.cloud. (The screenshots below use n8n 1.45+.)
|
||||
3. **Slack Incoming Webhook URL** – create one in your Slack workspace.
|
||||
|
||||
Add both secrets to n8n’s credential manager:
|
||||
|
||||
```env title=".env example"
|
||||
BROWSER_USE_API_KEY="sk-…"
|
||||
SLACK_WEBHOOK_URL="https://hooks.slack.com/services/…"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Import the template
|
||||
|
||||
1. Copy the [workflow JSON](#workflow-json) below to your clipboard.
|
||||
2. In n8n create a new workflow and paste the JSON.
|
||||
3. Replace the _Browser-Use API Key_ credential and _Slack Incoming Webhook URL_ with yours.
|
||||
|
||||
---
|
||||
|
||||
## How the workflow works
|
||||
|
||||
### 1. `Form Trigger` – collect the competitor’s name
|
||||
|
||||
A public n8n form with a single required field. When a user submits, the workflow fires instantly.
|
||||
|
||||
### 2. `HTTP Request – Browser Use Run Task`
|
||||
|
||||
We POST to `/api/v1/run-task` with the following body:
|
||||
|
||||
```json title="run-task payload"
|
||||
{
|
||||
"task": "Do exhaustive research on {{ $json[\"Competitor Name\"] }} and extract all pricing information, job postings, new features and announcements",
|
||||
"save_browser_data": true,
|
||||
"structured_output_json": {
|
||||
"pricing": {
|
||||
"plans": ["string"],
|
||||
"prices": ["string"],
|
||||
"features": ["string"]
|
||||
},
|
||||
"jobs": {
|
||||
"titles": ["string"],
|
||||
"departments": ["string"],
|
||||
"locations": ["string"]
|
||||
},
|
||||
"new_features": { "titles": ["string"], "description": ["string"] },
|
||||
"announcements": { "titles": ["string"], "description": ["string"] }
|
||||
},
|
||||
"metadata": { "source": "n8n-competitor-demo" }
|
||||
}
|
||||
```
|
||||
|
||||
Important bits:
|
||||
|
||||
• `structured_output_json` tells the agent which keys to return – no post-processing required.
|
||||
• We tag the task with `metadata.source` so the webhook can filter only _our_ jobs.
|
||||
|
||||
### 3. `Webhook` + `IF` – wait for task completion
|
||||
|
||||
Browser Use sends a webhook when anything happens to a task (see our [Webhooks guide](/cloud/v1/webhooks) for setup details). We expose an n8n Webhook node at `/get-research-data` and let the agent call it.
|
||||
|
||||
We only proceed when **both** conditions are true:
|
||||
|
||||
- `payload.status == "finished"`
|
||||
- `payload.metadata.source == "n8n-competitor-demo"`
|
||||
|
||||
### 4. `Get Task Details`
|
||||
|
||||
The webhook body includes the `session_id`. We fetch the full task record so we get the `output` field containing the structured JSON from step 2.
|
||||
|
||||
### 5. `Code – Generate Slack message`
|
||||
|
||||
A short JS snippet turns the JSON into a nicely-formatted Slack block with emojis and bullet points. Feel free to tweak the formatting.
|
||||
|
||||
### 6. `HTTP Request – Send to Slack`
|
||||
|
||||
Finally we POST the message to your incoming webhook and celebrate 🎉.
|
||||
|
||||
---
|
||||
|
||||
## Customize as you want
|
||||
|
||||
This workflow is just the starting point – Browser Use + n8n gives you endless possibilities. Here are some ideas:
|
||||
|
||||
| Want to... | How to do it |
|
||||
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Extract different data** | Edit `structured_output_json` to specify exactly what fields you need (pricing, reviews, contact info, etc.) and adjust the JS formatter. |
|
||||
| **Send to Teams/Email/Notion** | Swap the last Slack node for Teams, Gmail, or any of n8n's 400+ connectors. |
|
||||
| **Run automatically** | Replace the Form trigger with a Cron trigger for daily/weekly competitor monitoring. |
|
||||
| **Monitor multiple competitors** | Use a Google Sheets trigger with a list of companies and loop through them. |
|
||||
| **Add AI analysis** | Pipe the extracted data through OpenAI/Claude to generate insights and summaries. |
|
||||
| **Create alerts** | Set up conditional logic to only notify when competitors announce new features or price changes. |
|
||||
| **Build a dashboard** | Send data to Airtable, Notion, or Google Sheets to build a real-time competitor intelligence dashboard. |
|
||||
|
||||
The beauty of Browser Use is that it handles the complex web browsing while you focus on building the perfect workflow for your needs.
|
||||
|
||||
---
|
||||
|
||||
## Workflow JSON
|
||||
|
||||
<Accordion title="n8n Workflow JSON (click to expand)">
|
||||
```json id="workflow-json"
|
||||
{
|
||||
"name": "Competitor Intelligence Workflow with webhooks",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"httpMethod": "POST",
|
||||
"path": "get-research-data",
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
-480,
|
||||
176
|
||||
],
|
||||
"id": "81166dab-eb91-4627-b773-1aa7f7bd86ee",
|
||||
"name": "Webhook",
|
||||
"webhookId": "025bc4bf-00c0-47d4-bd5f-79046674d017"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"conditions": {
|
||||
"options": {
|
||||
"caseSensitive": true,
|
||||
"leftValue": "",
|
||||
"typeValidation": "strict",
|
||||
"version": 2
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"id": "8d9701b6-1dc2-4e55-9fe4-ef1735ff1ebc",
|
||||
"leftValue": "={{ $json.body.payload.status }}",
|
||||
"rightValue": "finished",
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"operation": "equals",
|
||||
"name": "filter.operator.equals"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "7cf18a23-f3d8-4a70-a77c-c286a231fc7f",
|
||||
"leftValue": "={{ $json.body.payload.metadata.source }}",
|
||||
"rightValue": "n8n-competitor-demo",
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"operation": "equals",
|
||||
"name": "filter.operator.equals"
|
||||
}
|
||||
}
|
||||
],
|
||||
"combinator": "and"
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.if",
|
||||
"typeVersion": 2.2,
|
||||
"position": [
|
||||
-256,
|
||||
176
|
||||
],
|
||||
"id": "b38737cc-0b8a-4a76-930f-362eb5de9ef9",
|
||||
"name": "If"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"formTitle": "Run Competitor Analysis",
|
||||
"formFields": {
|
||||
"values": [
|
||||
{
|
||||
"fieldLabel": "Competitor Name",
|
||||
"placeholder": "(e.g. OpenAI)",
|
||||
"requiredField": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.formTrigger",
|
||||
"typeVersion": 2.2,
|
||||
"position": [
|
||||
-336,
|
||||
-64
|
||||
],
|
||||
"id": "fcfc33dd-7d8a-460b-838d-955c65416aea",
|
||||
"name": "On form submission",
|
||||
"webhookId": "b2712d5b-14ae-424b-8733-fe6e77cebd43"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"method": "POST",
|
||||
"url": "https://api.browser-use.com/api/v1/run-task",
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpBearerAuth",
|
||||
"sendHeaders": true,
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{}
|
||||
]
|
||||
},
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"jsonBody": "={\n \"task\": \"Do exhaustive research on {{ $json['Competitor Name'] }} and extract all pricing information, job postings, new features and announcements\",\n \"save_browser_data\": true,\n \"structured_output_json\": \"{\\n \\\"pricing\\\": {\\n \\\"plans\\\": [\\\"string\\\"],\\n \\\"prices\\\": [\\\"string\\\"],\\n \\\"features\\\": [\\\"string\\\"]\\n },\\n \\\"jobs\\\": {\\n \\\"titles\\\": [\\\"string\\\"],\\n \\\"departments\\\": [\\\"string\\\"],\\n \\\"locations\\\": [\\\"string\\\"]\\n },\\n \\\"new_features\\\": {\\n \\\"titles\\\": [\\\"string\\\"],\\n \\\"description\\\": [\\\"string\\\"]\\n },\\n \\\"announcements\\\": {\\n \\\"titles\\\": [\\\"string\\\"],\\n \\\"description\\\": [\\\"string\\\"]\\n }\\n}\",\n\"metadata\": {\"source\": \"n8n-competitor-demo\"}\n} ",
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.2,
|
||||
"position": [
|
||||
-112,
|
||||
-64
|
||||
],
|
||||
"id": "d10bef40-e2a3-41ff-a507-4f365c13dc52",
|
||||
"name": "BrowserUse Run Task",
|
||||
"credentials": {
|
||||
"httpBearerAuth": {
|
||||
"id": "peg6MzgmJNRMCMnT",
|
||||
"name": "Browser-Use API Key"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "=https://api.browser-use.com/api/v1/task/{{ $('Webhook').item.json.body.payload.session_id }}",
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpBearerAuth",
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.2,
|
||||
"position": [
|
||||
0,
|
||||
144
|
||||
],
|
||||
"id": "e49c28ff-11a2-4195-94ab-ca5796572c34",
|
||||
"name": "Get Task details",
|
||||
"credentials": {
|
||||
"httpBearerAuth": {
|
||||
"id": "peg6MzgmJNRMCMnT",
|
||||
"name": "Browser-Use API Key"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const output_data = $input.first().json.output;\nconst data = JSON.parse(output_data);\n\nconst pricing = data?.pricing;\nconst jobs = data?.jobs;\nconst newFeatures = data?.new_features;\nconst announcements = data?.announcements;\n\n// Helper function to format arrays as bullet points\nconst formatAsBullets = (arr, prefix = \"• \" => {\n if (!arr || arr.length === 0) return \"• N/A\";\n return arr.map(item => `${prefix}${item}`).join(\"\\n\");\n};\n\nreturn {\n text: `🏷️ *Pricing*\\nPlans:\\n${formatAsBullets(pricing?.plans)}\\n\\nPrices:\\n${formatAsBullets(pricing?.prices)}\\n\\nFeatures:\\n${formatAsBullets(pricing?.features)}\\n\\n💼 *Jobs*\\nTitles:\\n${formatAsBullets(jobs?.titles)}\\n\\nDepartments:\\n${formatAsBullets(jobs?.departments)}\\n\\nLocations:\\n${formatAsBullets(jobs?.locations)}\\n\\n✨ *New Features*\\nTitles:\\n${formatAsBullets(newFeatures?.titles)}\\n\\nDescription:\\n${formatAsBullets(newFeatures?.description)}\\n\\n📢 *Announcements*\\n${formatAsBullets(announcements?.description)}`\n};"
|
||||
},
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
208,
|
||||
144
|
||||
],
|
||||
"id": "54bc087d-237d-438a-b688-bcbec25d9c45",
|
||||
"name": "Generate Slack message"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"method": "POST",
|
||||
"url": "",
|
||||
"sendBody": true,
|
||||
"bodyParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "text",
|
||||
"value": "={{ $json.text }}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.2,
|
||||
"position": [
|
||||
432,
|
||||
144
|
||||
],
|
||||
"id": "969a16f0-677b-4e46-a8bb-57a80b5daf07",
|
||||
"name": "Send to Slack"
|
||||
}
|
||||
],
|
||||
"pinData": {},
|
||||
"connections": {
|
||||
"Webhook": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "If",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"If": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get Task details",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"On form submission": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "BrowserUse Run Task",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Task details": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Generate Slack message",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Generate Slack message": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Send to Slack",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": true,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "f3b38678-4821-41ad-952c-df9bbba40fc8",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "7a1d1fd830bae2a00010153cf810fd67e0c87b8ae64ceb62273c87183efda365"
|
||||
},
|
||||
"id": "qmhqkZH8DhISWMmc",
|
||||
"tags": []
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
Copy everything between the braces, import into n8n and you're good to go.
|
||||
|
||||
<Note>
|
||||
Having trouble? Ping us in the #integrations channel on
|
||||
[Discord](https://link.browser-use.com/discord) – we’re happy to help.
|
||||
</Note>
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
title: "Pricing"
|
||||
description: "Browser Use Cloud API pricing structure and cost breakdown"
|
||||
icon: "dollar-sign"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
The Browser Use Cloud API pricing consists of two components:
|
||||
|
||||
1. **Task Initialization Cost**: $0.01 per started task
|
||||
2. **Task Step Cost**: Additional cost based on the specific model used for each step
|
||||
|
||||
## LLM Model Step Pricing
|
||||
|
||||
> **Limited Time Offer**: O3 model pricing reduced from $0.03 to $0.01 per step!
|
||||
|
||||
The following table shows the total cost per step for each available LLM model:
|
||||
|
||||
| Model | Cost per Step |
|
||||
| -------------------------------- | ------------- |
|
||||
| GPT-4.1 | $0.025 |
|
||||
| GPT-4.1 mini | $0.0075 |
|
||||
| O4 mini | $0.02 |
|
||||
| O3 | $0.01 |
|
||||
| Gemini 2.5 Flash | $0.0075 |
|
||||
| Gemini 2.5 Pro | $0.025 |
|
||||
| Claude 3.7 Sonnet (2025-02-19) | $0.03 |
|
||||
| Claude Sonnet 4 (2025-05-14) | $0.03 |
|
||||
| Llama 4 Maverick 17B Instruct | $0.01 |
|
||||
|
||||
## Example Cost Calculations
|
||||
|
||||
**Using GPT-4.1 for a 10 step task:**
|
||||
- Task initialization: $0.01
|
||||
- 10 steps × $0.025 per step = $0.25
|
||||
- **Total cost: $0.26**
|
||||
|
||||
**Using O3 for a 10 step task (Limited Time Offer):**
|
||||
- Task initialization: $0.01
|
||||
- 10 steps × $0.01 per step = $0.10
|
||||
- **Total cost: $0.11**
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "Quickstart"
|
||||
description: "Learn how to get started with the Browser Use Cloud API"
|
||||
icon: "cloud"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<img
|
||||
className="block dark:hidden rounded-2xl"
|
||||
src="/images/cloud-banner.png"
|
||||
alt="Browser Use Cloud Banner"
|
||||
/>
|
||||
<img
|
||||
className="hidden dark:block rounded-2xl"
|
||||
src="/images/cloud-banner-dark.png"
|
||||
alt="Browser Use Cloud Banner"
|
||||
/>
|
||||
|
||||
<Note>
|
||||
You need an active subscription and an API key from
|
||||
[cloud.browser-use.com/billing](https://cloud.browser-use.com/billing). For
|
||||
detailed pricing information, see our [pricing page](/cloud/v1/pricing).
|
||||
</Note>
|
||||
|
||||
## Creating Your First Agent
|
||||
|
||||
To understand how the API works visit the [Run Task](/api-reference/api-v1/run-task?playground=open) page.
|
||||
|
||||
```bash
|
||||
curl -X POST https://api.browser-use.com/api/v1/run-task \
|
||||
-H "Authorization: Bearer your_api_key_here" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"task": "Go to google.com and search for Browser Use"
|
||||
}'
|
||||
```
|
||||
|
||||
`run-task` API returns a task ID, which you can query to get the task status, live preview URL, and the result output.
|
||||
|
||||
<Note>
|
||||
To play around with the API, you can use the [Browser Use Cloud
|
||||
Playground](https://cloud.browser-use.com/playground).
|
||||
</Note>
|
||||
|
||||
For the full implementation guide see the [Implementation](/cloud/v1/implementation) page.
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
title: "Search API"
|
||||
description: "Get started with Browser Use's search endpoints to extract content from websites"
|
||||
icon: "magnifying-glass"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Warning>
|
||||
**🧪 BETA - This API is in beta - it may change and might not be available at
|
||||
all times.**
|
||||
</Warning>
|
||||
|
||||
## Why Browser Use Over Traditional Search?
|
||||
|
||||
**Browser Use actually browses websites like a human** while other tools return cached data from landing pages. Browser Use navigates deep into sites in real-time:
|
||||
|
||||
- 🔍 **Deep navigation**: Clicks through menus, forms, and multiple pages to find buried content
|
||||
- 🚀 **Always current**: Live prices, breaking news, real-time analytics - not cached results
|
||||
- 🎯 **No stale data**: See exactly what's on the page right now
|
||||
- 🌐 **Dynamic content**: Handles JavaScript, forms, and interactive elements
|
||||
- 🏠 **No surface limitations**: Gets data from pages that require navigation or interaction
|
||||
|
||||
**Other tools see yesterday's front door. Browser Use explores today's whole house.**
|
||||
|
||||
## Quick Start
|
||||
|
||||
The Search API allows you to quickly extract relevant content from websites using AI. There are two main endpoints:
|
||||
|
||||
💡 **Complete working examples** are available in the [examples/search](https://github.com/browser-use/browser-use/tree/main/examples/search) folder.
|
||||
|
||||
### Simple Search
|
||||
|
||||
Search Google and extract content from multiple top results:
|
||||
|
||||
```python
|
||||
import aiohttp
|
||||
import asyncio
|
||||
|
||||
async def simple_search():
|
||||
payload = {
|
||||
"query": "latest AI news",
|
||||
"max_websites": 5,
|
||||
"depth": 2
|
||||
}
|
||||
|
||||
headers = {
|
||||
"Authorization": "Bearer YOUR_API_KEY",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(
|
||||
"https://api.browser-use.com/api/v1/simple-search",
|
||||
json=payload,
|
||||
headers=headers
|
||||
) as response:
|
||||
result = await response.json()
|
||||
return result
|
||||
|
||||
asyncio.run(simple_search())
|
||||
```
|
||||
|
||||
### Search URL
|
||||
|
||||
Extract content from a specific URL:
|
||||
|
||||
```python
|
||||
async def search_url():
|
||||
payload = {
|
||||
"url": "https://browser-use.com/#pricing",
|
||||
"query": "Find pricing information for Browser Use",
|
||||
"depth": 2
|
||||
}
|
||||
|
||||
headers = {
|
||||
"Authorization": "Bearer YOUR_API_KEY",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(
|
||||
"https://api.browser-use.com/api/v1/search-url",
|
||||
json=payload,
|
||||
headers=headers
|
||||
) as response:
|
||||
result = await response.json()
|
||||
return result
|
||||
|
||||
asyncio.run(search_url())
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
- **query**: Search query or content to extract
|
||||
- **depth**: How deep to navigate within each website (2-5, default: 2)
|
||||
- `depth=2`: Checks main page + 1 click deeper
|
||||
- `depth=3`: Checks main page + 2 clicks deeper
|
||||
- `depth=5`: Thoroughly explores multiple navigation levels
|
||||
- **max_websites**: Number of websites to process (simple-search only, default: 5)
|
||||
- **url**: Target URL to extract from (search-url only)
|
||||
|
||||
## Pricing
|
||||
|
||||
### Simple Search
|
||||
|
||||
**Cost per request**: `1 cent × depth × max_websites`
|
||||
|
||||
Example: depth=2, max_websites=3 = 6 cents per request
|
||||
|
||||
### Search URL
|
||||
|
||||
**Cost per request**: `1 cent × depth`
|
||||
|
||||
Example: depth=2 = 2 cents per request
|
||||
@@ -0,0 +1,145 @@
|
||||
---
|
||||
title: "Webhooks"
|
||||
description: "Learn how to integrate webhooks with Browser Use Cloud API"
|
||||
icon: "code"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
Webhooks allow you to receive real-time notifications about events in your Browser Use tasks. This guide will show you how to set up and verify webhook endpoints.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<Note>
|
||||
You need an active subscription to create webhooks. See your billing page
|
||||
[cloud.browser-use.com/billing](https://cloud.browser-use.com/billing)
|
||||
</Note>
|
||||
|
||||
## Setting Up Webhooks
|
||||
|
||||
To receive webhook notifications, you need to:
|
||||
|
||||
1. Create an endpoint that can receive HTTPS POST requests
|
||||
2. Configure your webhook URL in the Browser Use dashboard
|
||||
3. Implement signature verification to ensure webhook authenticity
|
||||
|
||||
<Note>
|
||||
When adding a webhook URL in the dashboard, it must be a valid HTTPS URL that can receive POST requests.
|
||||
On creation, we will send a test payload `{"type": "test", "timestamp": "2024-03-21T12:00:00Z", "payload": {"test": "ok"}}` to verify the endpoint is working correctly before creating the actual webhook!
|
||||
</Note>
|
||||
|
||||
## Webhook Events
|
||||
|
||||
Browser Use sends various types of events. Each event has a specific type and payload structure.
|
||||
|
||||
### Event Types
|
||||
|
||||
Currently supported events:
|
||||
|
||||
| Event Type | Description |
|
||||
| -------------------------- | -------------------------------- |
|
||||
| `agent.task.status_update` | Status updates for running tasks |
|
||||
|
||||
### Task Status Updates
|
||||
|
||||
The `agent.task.status_update` event includes the following statuses:
|
||||
|
||||
| Status | Description |
|
||||
| -------------- | -------------------------------------- |
|
||||
| `initializing` | A task is initializing |
|
||||
| `started` | A Task has started (browser available) |
|
||||
| `paused` | A task has been paused mid execution |
|
||||
| `stopped` | A task has been stopped mid execution |
|
||||
| `finished` | A task has finished |
|
||||
|
||||
## Webhook Payload Structure
|
||||
|
||||
Each webhook call includes:
|
||||
|
||||
- A JSON payload with event details
|
||||
- `X-Browser-Use-Timestamp` header with the current timestamp
|
||||
- `X-Browser-Use-Signature` header for verification
|
||||
|
||||
The payload follows this structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "agent.task.status_update",
|
||||
"timestamp": "2025-05-25T09:22:22.269116+00:00",
|
||||
"payload": {
|
||||
"session_id": "cd9cc7bf-e3af-4181-80a2-73f083bc94b4",
|
||||
"task_id": "5b73fb3f-a3cb-4912-be40-17ce9e9e1a45",
|
||||
"status": "finished",
|
||||
"metadata": {
|
||||
"campaign": "q4-automation",
|
||||
"team": "marketing"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The webhook payload now includes a `metadata` field containing any custom key-value pairs that were provided when the task was created. This allows you to correlate webhook events with your internal tracking systems.
|
||||
|
||||
## Implementing Webhook Verification
|
||||
|
||||
To ensure webhook authenticity, you must verify the signature. Here's an example implementation in Python using FastAPI:
|
||||
|
||||
```python
|
||||
import uvicorn
|
||||
import hmac
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
|
||||
from fastapi import FastAPI, Request, HTTPException
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
SECRET_KEY = os.environ['SECRET_KEY']
|
||||
|
||||
def verify_signature(payload: dict, timestamp: str, received_signature: str) -> bool:
|
||||
message = f'{timestamp}.{json.dumps(payload, separators=(",", ":"), sort_keys=True)}'
|
||||
expected_signature = hmac.new(SECRET_KEY.encode(), message.encode(), hashlib.sha256).hexdigest()
|
||||
return hmac.compare_digest(expected_signature, received_signature)
|
||||
|
||||
@app.post('/webhook')
|
||||
async def webhook(request: Request):
|
||||
body = await request.json()
|
||||
|
||||
timestamp = request.headers.get('X-Browser-Use-Timestamp')
|
||||
signature = request.headers.get('X-Browser-Use-Signature')
|
||||
if not timestamp or not signature:
|
||||
raise HTTPException(status_code=400, detail='Missing timestamp or signature')
|
||||
|
||||
if not verify_signature(body, timestamp, signature):
|
||||
raise HTTPException(status_code=403, detail='Invalid signature')
|
||||
|
||||
# Handle different event types
|
||||
event_type = body.get('type')
|
||||
if event_type == 'agent.task.status_update':
|
||||
# Handle task status update
|
||||
print('Task status update received:', body['payload'])
|
||||
elif event_type == 'test':
|
||||
# Handle test webhook
|
||||
print('Test webhook received:', body['payload'])
|
||||
else:
|
||||
print('Unknown event type:', event_type)
|
||||
|
||||
return {'status': 'success', 'message': 'Webhook received'}
|
||||
|
||||
if __name__ == '__main__':
|
||||
uvicorn.run(app, host='0.0.0.0', port=4242)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always verify signatures**: Never process webhook payloads without verifying the signature
|
||||
2. **Handle retries**: Browser Use will retry failed webhook deliveries up to 5 times
|
||||
3. **Respond quickly**: Return a 200 response as soon as you've verified the signature
|
||||
4. **Process asynchronously**: Handle the webhook payload processing in a background task
|
||||
5. **Monitor failures**: Set up monitoring for webhook delivery failures
|
||||
6. **Handle unknown events**: Implement graceful handling of new event types that may be added in the future
|
||||
|
||||
<Note>
|
||||
Need help? Contact our support team at support@browser-use.com or join our
|
||||
[Discord community](https://link.browser-use.com/discord)
|
||||
</Note>
|
||||
Reference in New Issue
Block a user