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,95 @@
|
||||
---
|
||||
title: "Ad-Use (Ad Generator)"
|
||||
description: "Generate Instagram image ads and TikTok video ads from landing pages using browser agents, Google's Nano Banana 🍌, and Veo3."
|
||||
icon: "image"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
This demo requires browser-use v0.7.6+.
|
||||
</Note>
|
||||
|
||||
<video
|
||||
controls
|
||||
className="w-full aspect-video rounded-xl"
|
||||
src="https://github.com/user-attachments/assets/7fab54a9-b36b-4fba-ab98-a438f2b86b7e">
|
||||
</video>
|
||||
|
||||
## Features
|
||||
|
||||
1. Agent visits your target website
|
||||
2. Captures brand name, tagline, and key selling points
|
||||
3. Takes a clean screenshot for design reference
|
||||
4. Creates scroll-stopping Instagram image ads with 🍌
|
||||
5. Generates viral TikTok video ads with Veo3
|
||||
6. Supports parallel generation of multiple ads
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure the newest version of browser-use is installed (with screenshot functionality):
|
||||
```bash
|
||||
pip install -U browser-use
|
||||
```
|
||||
|
||||
Export your Gemini API key, get it from: [Google AI Studio](https://makersuite.google.com/app/apikey)
|
||||
```
|
||||
export GOOGLE_API_KEY='your-google-api-key-here'
|
||||
```
|
||||
|
||||
Clone the repo and cd into the app folder
|
||||
```bash
|
||||
git clone https://github.com/browser-use/browser-use.git
|
||||
cd browser-use/examples/apps/ad-use
|
||||
```
|
||||
|
||||
## Normal Usage
|
||||
|
||||
```bash
|
||||
# Basic - Generate Instagram image ad (default)
|
||||
python ad_generator.py --url https://www.apple.com/iphone-16-pro/
|
||||
|
||||
# Generate TikTok video ad with Veo3
|
||||
python ad_generator.py --tiktok --url https://www.apple.com/iphone-16-pro/
|
||||
|
||||
# Generate multiple ads in parallel
|
||||
python ad_generator.py --instagram --count 3 --url https://www.apple.com/iphone-16-pro/
|
||||
python ad_generator.py --tiktok --count 2 --url https://www.apple.com/iphone-16-pro/
|
||||
|
||||
# Debug Mode - See the browser in action
|
||||
python ad_generator.py --url https://www.apple.com/iphone-16-pro/ --debug
|
||||
```
|
||||
|
||||
## Command Line Options
|
||||
|
||||
- `--url`: Landing page URL to analyze
|
||||
- `--instagram`: Generate Instagram image ad (default if no flag specified)
|
||||
- `--tiktok`: Generate TikTok video ad using Veo3
|
||||
- `--count N`: Generate N ads in parallel (default: 1)
|
||||
- `--debug`: Show browser window and enable verbose logging
|
||||
|
||||
## Programmatic Usage
|
||||
```python
|
||||
import asyncio
|
||||
from ad_generator import create_ad_from_landing_page
|
||||
|
||||
async def main():
|
||||
results = await create_ad_from_landing_page(
|
||||
url="https://your-landing-page.com",
|
||||
debug=False
|
||||
)
|
||||
print(f"Generated ads: {results}")
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
Generated ads are saved in the `output/` directory with:
|
||||
- **PNG image files** (ad_timestamp.png) - Instagram ads generated with Gemini 2.5 Flash Image
|
||||
- **MP4 video files** (ad_timestamp.mp4) - TikTok ads generated with Veo3
|
||||
- **Analysis files** (analysis_timestamp.txt) - Browser agent analysis and prompts used
|
||||
- **Landing page screenshots** (landing_page_timestamp.png) - Reference screenshots
|
||||
|
||||
## Source Code
|
||||
|
||||
Full implementation: [https://github.com/browser-use/browser-use/tree/main/examples/apps/ad-use](https://github.com/browser-use/browser-use/tree/main/examples/apps/ad-use)
|
||||
@@ -0,0 +1,124 @@
|
||||
---
|
||||
title: "Msg-Use (WhatsApp Sender)"
|
||||
description: "AI-powered WhatsApp message scheduler using browser agents and Gemini. Schedule personalized messages in natural language."
|
||||
icon: "message"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
This demo requires browser-use v0.7.7+.
|
||||
</Note>
|
||||
|
||||
<video
|
||||
controls
|
||||
className="w-full aspect-video rounded-xl"
|
||||
src="https://browser-use.github.io/media/demos/msg_use.mp4">
|
||||
</video>
|
||||
|
||||
## Features
|
||||
|
||||
1. Agent logs into WhatsApp Web automatically
|
||||
2. Parses natural language scheduling instructions
|
||||
3. Composes personalized messages using AI
|
||||
4. Schedules messages for future delivery or sends immediately
|
||||
5. Persistent session (no repeated QR scanning)
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure the newest version of browser-use is installed:
|
||||
```bash
|
||||
pip install -U browser-use
|
||||
```
|
||||
|
||||
Export your Gemini API key, get it from: [Google AI Studio](https://makersuite.google.com/app/apikey)
|
||||
```bash
|
||||
export GOOGLE_API_KEY='your-gemini-api-key-here'
|
||||
```
|
||||
|
||||
Clone the repo and cd into the app folder
|
||||
```bash
|
||||
git clone https://github.com/browser-use/browser-use.git
|
||||
cd browser-use/examples/apps/msg-use
|
||||
```
|
||||
|
||||
## Initial Login
|
||||
|
||||
First-time setup requires QR code scanning:
|
||||
```bash
|
||||
python login.py
|
||||
```
|
||||
- Scan QR code when browser opens
|
||||
- Session will be saved for future use
|
||||
|
||||
## Normal Usage
|
||||
|
||||
1. **Edit your schedule** in `messages.txt`:
|
||||
```
|
||||
- Send "Hi" to Magnus on the 13.06 at 18:15
|
||||
- Tell hinge date (Camila) at 20:00 that I miss her
|
||||
- Send happy birthday message to sister on the 15.06
|
||||
- Remind mom to pick up the car next tuesday
|
||||
```
|
||||
|
||||
2. **Test mode** - See what will be sent:
|
||||
```bash
|
||||
python scheduler.py --test
|
||||
```
|
||||
|
||||
3. **Run scheduler**:
|
||||
```bash
|
||||
python scheduler.py
|
||||
|
||||
# Debug Mode - See the browser in action
|
||||
python scheduler.py --debug
|
||||
|
||||
# Auto Mode - Respond to unread messages every ~30 minutes
|
||||
python scheduler.py --auto
|
||||
```
|
||||
|
||||
## Programmatic Usage
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from scheduler import schedule_messages
|
||||
|
||||
async def main():
|
||||
messages = [
|
||||
"Send hello to John at 15:30",
|
||||
"Remind Sarah about meeting tomorrow at 9am"
|
||||
]
|
||||
await schedule_messages(messages, debug=False)
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## Example Output
|
||||
|
||||
The scheduler processes natural language and outputs structured results:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"contact": "Magnus",
|
||||
"original_message": "Hi",
|
||||
"composed_message": "Hi",
|
||||
"scheduled_time": "2025-06-13 18:15"
|
||||
},
|
||||
{
|
||||
"contact": "Camila",
|
||||
"original_message": "I miss her",
|
||||
"composed_message": "I miss you ❤️",
|
||||
"scheduled_time": "2025-06-14 20:00"
|
||||
},
|
||||
{
|
||||
"contact": "sister",
|
||||
"original_message": "happy birthday message",
|
||||
"composed_message": "Happy birthday! 🎉 Wishing you an amazing day, sis! Hope you have the best birthday ever! ❤️🎂🎈",
|
||||
"scheduled_time": "2025-06-15 09:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Source Code
|
||||
|
||||
Full implementation: [https://github.com/browser-use/browser-use/tree/main/examples/apps/msg-use](https://github.com/browser-use/browser-use/tree/main/examples/apps/msg-use)
|
||||
@@ -0,0 +1,133 @@
|
||||
---
|
||||
title: "News-Use (News Monitor)"
|
||||
description: "Monitor news websites and extract articles with sentiment analysis using browser agents and Google Gemini."
|
||||
icon: "newspaper"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
This demo requires browser-use v0.7.7+.
|
||||
</Note>
|
||||
|
||||
<video
|
||||
controls
|
||||
className="w-full aspect-video rounded-xl"
|
||||
src="https://browser-use.github.io/media/demos/news_use.mp4">
|
||||
</video>
|
||||
|
||||
## Features
|
||||
|
||||
1. Agent visits any news website automatically
|
||||
2. Finds and clicks the most recent headline article
|
||||
3. Extracts title, URL, posting time, and full content
|
||||
4. Generates short/long summaries with sentiment analysis
|
||||
5. Persistent deduplication across monitoring sessions
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure the newest version of browser-use is installed:
|
||||
```bash
|
||||
pip install -U browser-use
|
||||
```
|
||||
|
||||
Export your Gemini API key, get it from: [Google AI Studio](https://makersuite.google.com/app/apikey)
|
||||
```bash
|
||||
export GOOGLE_API_KEY='your-google-api-key-here'
|
||||
```
|
||||
|
||||
Clone the repo, cd to the app
|
||||
```bash
|
||||
git clone https://github.com/browser-use/browser-use.git
|
||||
cd browser-use/examples/apps/news-use
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
```bash
|
||||
# One-time extraction - Get the latest article and exit
|
||||
python news_monitor.py --once
|
||||
|
||||
# Monitor Bloomberg continuously (default)
|
||||
python news_monitor.py
|
||||
|
||||
# Monitor TechCrunch every 60 seconds
|
||||
python news_monitor.py --url https://techcrunch.com --interval 60
|
||||
|
||||
# Debug mode - See browser in action
|
||||
python news_monitor.py --once --debug
|
||||
```
|
||||
|
||||
## Output Format
|
||||
|
||||
Articles are displayed with timestamp, sentiment emoji, and summary:
|
||||
|
||||
```
|
||||
[2025-09-11 02:49:21] - 🟢 - Klarna's IPO raises $1.4B, benefiting existing investors
|
||||
[2025-09-11 02:54:15] - 🔴 - Tech layoffs continue as major firms cut workforce
|
||||
[2025-09-11 02:59:33] - 🟡 - Federal Reserve maintains interest rates unchanged
|
||||
```
|
||||
|
||||
**Sentiment Indicators:**
|
||||
- 🟢 **Positive** - Good news, growth, success stories
|
||||
- 🟡 **Neutral** - Factual reporting, announcements, updates
|
||||
- 🔴 **Negative** - Challenges, losses, negative events
|
||||
|
||||
## Data Persistence
|
||||
|
||||
All extracted articles are saved to `news_data.json` with complete metadata:
|
||||
|
||||
```json
|
||||
{
|
||||
"hash": "a1b2c3d4...",
|
||||
"pulled_at": "2025-09-11T02:49:21Z",
|
||||
"data": {
|
||||
"title": "Klarna's IPO pops, raising $1.4B",
|
||||
"url": "https://techcrunch.com/2025/09/11/klarna-ipo/",
|
||||
"posting_time": "12:11 PM PDT · September 10, 2025",
|
||||
"short_summary": "Klarna's IPO raises $1.4B, benefiting existing investors like Sequoia.",
|
||||
"long_summary": "Fintech Klarna successfully IPO'd on the NYSE...",
|
||||
"sentiment": "positive"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Programmatic Usage
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from news_monitor import extract_latest_article
|
||||
|
||||
async def main():
|
||||
# Extract latest article from any news site
|
||||
result = await extract_latest_article(
|
||||
site_url="https://techcrunch.com",
|
||||
debug=False
|
||||
)
|
||||
|
||||
if result["status"] == "success":
|
||||
article = result["data"]
|
||||
print(f"📰 {article['title']}")
|
||||
print(f"😊 Sentiment: {article['sentiment']}")
|
||||
print(f"📝 Summary: {article['short_summary']}")
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
```python
|
||||
# Custom monitoring with filters
|
||||
async def monitor_with_filters():
|
||||
while True:
|
||||
result = await extract_latest_article("https://bloomberg.com")
|
||||
if result["status"] == "success":
|
||||
article = result["data"]
|
||||
# Only alert on negative market news
|
||||
if article["sentiment"] == "negative" and "market" in article["title"].lower():
|
||||
send_alert(article)
|
||||
await asyncio.sleep(300) # Check every 5 minutes
|
||||
```
|
||||
|
||||
## Source Code
|
||||
|
||||
Full implementation: [https://github.com/browser-use/browser-use/tree/main/examples/apps/news-use](https://github.com/browser-use/browser-use/tree/main/examples/apps/news-use)
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
title: "Vibetest-Use (Automated QA)"
|
||||
description: "Run multi-agent Browser-Use tests to catch UI bugs, broken links, and accessibility issues before they ship."
|
||||
icon: "bug"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Requires **browser-use < v0.5.0** and Playwright Chromium. Currently getting an update to v0.7.6+.
|
||||
</Note>
|
||||
|
||||
<video
|
||||
controls
|
||||
className="w-full aspect-video rounded-xl"
|
||||
src="https://github.com/user-attachments/assets/6450b5b7-10e5-4019-82a4-6d726dbfbe1f">
|
||||
</video>
|
||||
|
||||
## Features
|
||||
|
||||
1. Launches multiple headless (or visible) Browser-Use agents in parallel
|
||||
2. Crawls your site and records screenshots, broken links & a11y issues
|
||||
3. Works on production URLs *and* `localhost` dev servers
|
||||
4. Simple natural-language prompts via MCP in Cursor / Claude Code
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
|
||||
# 1. Clone repo
|
||||
git clone https://github.com/browser-use/vibetest-use.git
|
||||
cd vibetest-use
|
||||
|
||||
# 2. Create & activate env
|
||||
uv venv --python 3.11
|
||||
source .venv/bin/activate
|
||||
|
||||
# 3. Install project
|
||||
uv pip install -e .
|
||||
|
||||
# 4. Install browser runtime once
|
||||
playwright install chromium --with-deps --no-shell
|
||||
```
|
||||
|
||||
### 1) Claude Code
|
||||
|
||||
```bash
|
||||
# Register the MCP server
|
||||
claude mcp add vibetest /full/path/to/vibetest-use/.venv/bin/vibetest-mcp \
|
||||
-e GOOGLE_API_KEY="your_api_key"
|
||||
|
||||
# Inside a Claude chat
|
||||
> /mcp
|
||||
# ⎿ MCP Server Status
|
||||
# • vibetest: connected
|
||||
```
|
||||
|
||||
### 2) Cursor (manual MCP entry)
|
||||
|
||||
1. Open **Settings → MCP**
|
||||
2. Click **Add Server** and paste:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"vibetest": {
|
||||
"command": "/full/path/to/vibetest-use/.venv/bin/vibetest-mcp",
|
||||
"env": {
|
||||
"GOOGLE_API_KEY": "your_api_key"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Basic Prompts
|
||||
```
|
||||
> Vibetest my website with 5 agents: browser-use.com
|
||||
> Run vibetest on localhost:3000
|
||||
> Run a headless vibetest on localhost:4242 with 10 agents
|
||||
```
|
||||
|
||||
### Parameters
|
||||
* **URL** – any `https` or `http` host or `localhost:port`
|
||||
* **Agents** – `3` by default; more agents = deeper coverage
|
||||
* **Headless** – say *headless* to hide the browser, omit to watch it live
|
||||
|
||||
## Requirements
|
||||
|
||||
* Python 3.11+
|
||||
* Google API key (Gemini flash used for analysis)
|
||||
* Cursor / Claude with MCP support
|
||||
|
||||
## Source Code
|
||||
|
||||
Full implementation: [https://github.com/browser-use/vibetest-use](https://github.com/browser-use/vibetest-use)
|
||||
@@ -0,0 +1,97 @@
|
||||
---
|
||||
title: "Fast Agent"
|
||||
description: "Optimize agent performance for maximum speed and efficiency."
|
||||
icon: "bolt"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, BrowserProfile
|
||||
|
||||
# Speed optimization instructions for the model
|
||||
SPEED_OPTIMIZATION_PROMPT = """
|
||||
Speed optimization instructions:
|
||||
- Be extremely concise and direct in your responses
|
||||
- Get to the goal as quickly as possible
|
||||
- Use multi-action sequences whenever possible to reduce steps
|
||||
"""
|
||||
|
||||
|
||||
async def main():
|
||||
# 1. Use fast LLM - Llama 4 on Groq for ultra-fast inference
|
||||
from browser_use import ChatGroq
|
||||
|
||||
llm = ChatGroq(
|
||||
model='meta-llama/llama-4-maverick-17b-128e-instruct',
|
||||
temperature=0.0,
|
||||
)
|
||||
# from browser_use import ChatGoogle
|
||||
|
||||
# llm = ChatGoogle(model='gemini-2.5-flash')
|
||||
|
||||
# 2. Create speed-optimized browser profile
|
||||
browser_profile = BrowserProfile(
|
||||
minimum_wait_page_load_time=0.1,
|
||||
wait_between_actions=0.1,
|
||||
headless=False,
|
||||
)
|
||||
|
||||
# 3. Define a speed-focused task
|
||||
task = """
|
||||
1. Go to reddit https://www.reddit.com/search/?q=browser+agent&type=communities
|
||||
2. Click directly on the first 5 communities to open each in new tabs
|
||||
3. Find out what the latest post is about, and switch directly to the next tab
|
||||
4. Return the latest post summary for each page
|
||||
"""
|
||||
|
||||
# 4. Create agent with all speed optimizations
|
||||
agent = Agent(
|
||||
task=task,
|
||||
llm=llm,
|
||||
flash_mode=True, # Disables thinking in the LLM output for maximum speed
|
||||
browser_profile=browser_profile,
|
||||
extend_system_message=SPEED_OPTIMIZATION_PROMPT,
|
||||
)
|
||||
|
||||
await agent.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## Speed Optimization Techniques
|
||||
|
||||
### 1. Fast LLM Models
|
||||
```python
|
||||
# Groq - Ultra-fast inference
|
||||
from browser_use import ChatGroq
|
||||
llm = ChatGroq(model='meta-llama/llama-4-maverick-17b-128e-instruct')
|
||||
|
||||
# Google Gemini Flash - Optimized for speed
|
||||
from browser_use import ChatGoogle
|
||||
llm = ChatGoogle(model='gemini-2.5-flash')
|
||||
```
|
||||
|
||||
### 2. Browser Optimizations
|
||||
```python
|
||||
browser_profile = BrowserProfile(
|
||||
minimum_wait_page_load_time=0.1, # Reduce wait time
|
||||
wait_between_actions=0.1, # Faster action execution
|
||||
headless=True, # No GUI overhead
|
||||
)
|
||||
```
|
||||
|
||||
### 3. Agent Optimizations
|
||||
```python
|
||||
agent = Agent(
|
||||
task=task,
|
||||
llm=llm,
|
||||
flash_mode=True, # Skip LLM thinking process
|
||||
extend_system_message=SPEED_PROMPT, # Optimize LLM behavior
|
||||
)
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "Follow up tasks"
|
||||
description: "Follow up tasks with the same browser session."
|
||||
icon: "link"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Chain Agent Tasks
|
||||
|
||||
Keep your browser session alive and chain multiple tasks together. Perfect for conversational workflows or multi-step processes.
|
||||
|
||||
```python
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from browser_use import Agent, Browser
|
||||
|
||||
|
||||
load_dotenv()
|
||||
|
||||
import asyncio
|
||||
|
||||
|
||||
async def main():
|
||||
browser = Browser(keep_alive=True)
|
||||
|
||||
await browser.start()
|
||||
|
||||
agent = Agent(task='search for browser-use.', browser_session=browser)
|
||||
await agent.run(max_steps=2)
|
||||
agent.add_new_task('return the title of first result')
|
||||
await agent.run()
|
||||
|
||||
await browser.kill()
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Persistent Browser**: `BrowserProfile(keep_alive=True)` prevents browser from closing between tasks
|
||||
2. **Task Chaining**: Use `agent.add_new_task()` to add follow-up tasks
|
||||
3. **Context Preservation**: Agent maintains memory and browser state across tasks
|
||||
4. **Interactive Flow**: Perfect for conversational interfaces
|
||||
5. **Break down long flows**: If you have very long flows, you can keep the browser alive and send new agents to it.
|
||||
|
||||
<Note>
|
||||
The browser session remains active throughout the entire chain, preserving all cookies, local storage, and page state.
|
||||
</Note>
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
title: "More Examples"
|
||||
description: "Explore additional examples and use cases on GitHub."
|
||||
icon: "arrow-up-right-from-square"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
### 🔗 Browse All Examples
|
||||
|
||||
**[View Complete Examples Directory →](https://github.com/browser-use/browser-use/tree/main/examples)**
|
||||
|
||||
### 🤝 Contributing Examples
|
||||
|
||||
Have a great use case? **[Submit a pull request](https://github.com/browser-use/browser-use/pulls)** with your example!
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: "Parallel Agents"
|
||||
description: "Run multiple agents in parallel with separate browser instances"
|
||||
icon: "copy"
|
||||
---
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from browser_use import Agent, Browser, ChatOpenAI
|
||||
|
||||
async def main():
|
||||
# Create 3 separate browser instances
|
||||
browsers = [
|
||||
Browser(
|
||||
user_data_dir=f'./temp-profile-{i}',
|
||||
headless=False,
|
||||
)
|
||||
for i in range(3)
|
||||
]
|
||||
|
||||
# Create 3 agents with different tasks
|
||||
agents = [
|
||||
Agent(
|
||||
task='Search for "browser automation" on Google',
|
||||
browser=browsers[0],
|
||||
llm=ChatOpenAI(model='gpt-4.1-mini'),
|
||||
),
|
||||
Agent(
|
||||
task='Search for "AI agents" on DuckDuckGo',
|
||||
browser=browsers[1],
|
||||
llm=ChatOpenAI(model='gpt-4.1-mini'),
|
||||
),
|
||||
Agent(
|
||||
task='Visit Wikipedia and search for "web scraping"',
|
||||
browser=browsers[2],
|
||||
llm=ChatOpenAI(model='gpt-4.1-mini'),
|
||||
),
|
||||
]
|
||||
|
||||
# Run all agents in parallel
|
||||
tasks = [agent.run() for agent in agents]
|
||||
results = await asyncio.gather(*tasks, return_exceptions=True)
|
||||
|
||||
print('🎉 All agents completed!')
|
||||
```
|
||||
|
||||
> **Note:** This is experimental, and agents might conflict each other.
|
||||
+393
@@ -0,0 +1,393 @@
|
||||
---
|
||||
title: "Playwright Integration"
|
||||
description: "Advanced example showing Playwright and Browser-Use working together"
|
||||
icon: "wand-magic-sparkles"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Key Features
|
||||
|
||||
1. Browser-Use and Playwright sharing the same Chrome instance via CDP
|
||||
2. Take actions with Playwright and continue with Browser-Use actions
|
||||
3. Let the agent call Playwright functions like screenshot or click on selectors for deterministic steps
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
uv pip install playwright aiohttp
|
||||
```
|
||||
|
||||
## Full Example
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
# Check for required dependencies first - before other imports
|
||||
try:
|
||||
import aiohttp # type: ignore
|
||||
from playwright.async_api import Browser, Page, async_playwright # type: ignore
|
||||
except ImportError as e:
|
||||
print(f'❌ Missing dependencies for this example: {e}')
|
||||
print('This example requires: playwright aiohttp')
|
||||
print('Install with: uv add playwright aiohttp')
|
||||
print('Also run: playwright install chromium')
|
||||
sys.exit(1)
|
||||
|
||||
from browser_use import Agent, BrowserSession, ChatOpenAI, Tools
|
||||
from browser_use.agent.views import ActionResult
|
||||
|
||||
# Global Playwright browser instance - shared between custom actions
|
||||
playwright_browser: Browser | None = None
|
||||
playwright_page: Page | None = None
|
||||
|
||||
|
||||
# Custom action parameter models
|
||||
class PlaywrightFillFormAction(BaseModel):
|
||||
"""Parameters for Playwright form filling action."""
|
||||
|
||||
customer_name: str = Field(..., description='Customer name to fill')
|
||||
phone_number: str = Field(..., description='Phone number to fill')
|
||||
email: str = Field(..., description='Email address to fill')
|
||||
size_option: str = Field(..., description='Size option (small/medium/large)')
|
||||
|
||||
|
||||
class PlaywrightScreenshotAction(BaseModel):
|
||||
"""Parameters for Playwright screenshot action."""
|
||||
|
||||
filename: str = Field(default='playwright_screenshot.png', description='Filename for screenshot')
|
||||
quality: int | None = Field(default=None, description='JPEG quality (1-100), only for .jpg/.jpeg files')
|
||||
|
||||
|
||||
class PlaywrightGetTextAction(BaseModel):
|
||||
"""Parameters for getting text using Playwright selectors."""
|
||||
|
||||
selector: str = Field(..., description='CSS selector to get text from. Use "title" for page title.')
|
||||
|
||||
|
||||
async def start_chrome_with_debug_port(port: int = 9222):
|
||||
"""
|
||||
Start Chrome with remote debugging enabled.
|
||||
Returns the Chrome process.
|
||||
"""
|
||||
# Create temporary directory for Chrome user data
|
||||
user_data_dir = tempfile.mkdtemp(prefix='chrome_cdp_')
|
||||
|
||||
# Chrome launch command
|
||||
chrome_paths = [
|
||||
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', # macOS
|
||||
'/usr/bin/google-chrome', # Linux
|
||||
'/usr/bin/chromium-browser', # Linux Chromium
|
||||
'chrome', # Windows/PATH
|
||||
'chromium', # Generic
|
||||
]
|
||||
|
||||
chrome_exe = None
|
||||
for path in chrome_paths:
|
||||
if os.path.exists(path) or path in ['chrome', 'chromium']:
|
||||
try:
|
||||
# Test if executable works
|
||||
test_proc = await asyncio.create_subprocess_exec(
|
||||
path, '--version', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
||||
)
|
||||
await test_proc.wait()
|
||||
chrome_exe = path
|
||||
break
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if not chrome_exe:
|
||||
raise RuntimeError('❌ Chrome not found. Please install Chrome or Chromium.')
|
||||
|
||||
# Chrome command arguments
|
||||
cmd = [
|
||||
chrome_exe,
|
||||
f'--remote-debugging-port={port}',
|
||||
f'--user-data-dir={user_data_dir}',
|
||||
'--no-first-run',
|
||||
'--no-default-browser-check',
|
||||
'--disable-extensions',
|
||||
'about:blank', # Start with blank page
|
||||
]
|
||||
|
||||
# Start Chrome process
|
||||
process = await asyncio.create_subprocess_exec(*cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
|
||||
# Wait for Chrome to start and CDP to be ready
|
||||
cdp_ready = False
|
||||
for _ in range(20): # 20 second timeout
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(
|
||||
f'http://localhost:{port}/json/version', timeout=aiohttp.ClientTimeout(total=1)
|
||||
) as response:
|
||||
if response.status == 200:
|
||||
cdp_ready = True
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
await asyncio.sleep(1)
|
||||
|
||||
if not cdp_ready:
|
||||
process.terminate()
|
||||
raise RuntimeError('❌ Chrome failed to start with CDP')
|
||||
|
||||
return process
|
||||
|
||||
|
||||
async def connect_playwright_to_cdp(cdp_url: str):
|
||||
"""
|
||||
Connect Playwright to the same Chrome instance Browser-Use is using.
|
||||
This enables custom actions to use Playwright functions.
|
||||
"""
|
||||
global playwright_browser, playwright_page
|
||||
|
||||
playwright = await async_playwright().start()
|
||||
playwright_browser = await playwright.chromium.connect_over_cdp(cdp_url)
|
||||
|
||||
# Get or create a page
|
||||
if playwright_browser and playwright_browser.contexts and playwright_browser.contexts[0].pages:
|
||||
playwright_page = playwright_browser.contexts[0].pages[0]
|
||||
elif playwright_browser:
|
||||
context = await playwright_browser.new_context()
|
||||
playwright_page = await context.new_page()
|
||||
|
||||
|
||||
# Create custom tools that use Playwright functions
|
||||
tools = Tools()
|
||||
|
||||
|
||||
@tools.registry.action(
|
||||
"Fill out a form using Playwright's precise form filling capabilities. This uses Playwright selectors for reliable form interaction.",
|
||||
param_model=PlaywrightFillFormAction,
|
||||
)
|
||||
async def playwright_fill_form(params: PlaywrightFillFormAction, browser_session: BrowserSession):
|
||||
"""
|
||||
Custom action that uses Playwright to fill forms with high precision.
|
||||
This demonstrates how to create Browser-Use actions that leverage Playwright's capabilities.
|
||||
"""
|
||||
try:
|
||||
if not playwright_page:
|
||||
return ActionResult(error='Playwright not connected. Run setup first.')
|
||||
|
||||
# Filling form with Playwright's precise selectors
|
||||
|
||||
# Wait for form to be ready and fill basic fields
|
||||
await playwright_page.wait_for_selector('input[name="custname"]', timeout=10000)
|
||||
await playwright_page.fill('input[name="custname"]', params.customer_name)
|
||||
await playwright_page.fill('input[name="custtel"]', params.phone_number)
|
||||
await playwright_page.fill('input[name="custemail"]', params.email)
|
||||
|
||||
# Handle size selection - check if it's a select dropdown or radio buttons
|
||||
size_select = playwright_page.locator('select[name="size"]')
|
||||
size_radio = playwright_page.locator(f'input[name="size"][value="{params.size_option}"]')
|
||||
|
||||
if await size_select.count() > 0:
|
||||
# It's a select dropdown
|
||||
await playwright_page.select_option('select[name="size"]', params.size_option)
|
||||
elif await size_radio.count() > 0:
|
||||
# It's radio buttons
|
||||
await playwright_page.check(f'input[name="size"][value="{params.size_option}"]')
|
||||
else:
|
||||
raise ValueError(f'Could not find size input field for value: {params.size_option}')
|
||||
|
||||
# Get form data to verify it was filled
|
||||
form_data = {}
|
||||
form_data['name'] = await playwright_page.input_value('input[name="custname"]')
|
||||
form_data['phone'] = await playwright_page.input_value('input[name="custtel"]')
|
||||
form_data['email'] = await playwright_page.input_value('input[name="custemail"]')
|
||||
|
||||
# Get size value based on input type
|
||||
if await size_select.count() > 0:
|
||||
form_data['size'] = await playwright_page.input_value('select[name="size"]')
|
||||
else:
|
||||
# For radio buttons, find the checked one
|
||||
checked_radio = playwright_page.locator('input[name="size"]:checked')
|
||||
if await checked_radio.count() > 0:
|
||||
form_data['size'] = await checked_radio.get_attribute('value')
|
||||
else:
|
||||
form_data['size'] = 'none selected'
|
||||
|
||||
success_msg = f'✅ Form filled successfully with Playwright: {form_data}'
|
||||
|
||||
return ActionResult(
|
||||
extracted_content=success_msg, include_in_memory=True, long_term_memory=f'Filled form with: {form_data}'
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f'❌ Playwright form filling failed: {str(e)}'
|
||||
return ActionResult(error=error_msg)
|
||||
|
||||
|
||||
@tools.registry.action(
|
||||
"Take a screenshot using Playwright's screenshot capabilities with high quality and precision.",
|
||||
param_model=PlaywrightScreenshotAction,
|
||||
)
|
||||
async def playwright_screenshot(params: PlaywrightScreenshotAction, browser_session: BrowserSession):
|
||||
"""
|
||||
Custom action that uses Playwright's advanced screenshot features.
|
||||
"""
|
||||
try:
|
||||
if not playwright_page:
|
||||
return ActionResult(error='Playwright not connected. Run setup first.')
|
||||
|
||||
# Taking screenshot with Playwright
|
||||
|
||||
# Use Playwright's screenshot with full page capture
|
||||
screenshot_kwargs = {'path': params.filename, 'full_page': True}
|
||||
|
||||
# Add quality parameter only for JPEG files
|
||||
if params.quality is not None and params.filename.lower().endswith(('.jpg', '.jpeg')):
|
||||
screenshot_kwargs['quality'] = params.quality
|
||||
|
||||
await playwright_page.screenshot(**screenshot_kwargs)
|
||||
|
||||
success_msg = f'✅ Screenshot saved as {params.filename} using Playwright'
|
||||
|
||||
return ActionResult(
|
||||
extracted_content=success_msg, include_in_memory=True, long_term_memory=f'Screenshot saved: {params.filename}'
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f'❌ Playwright screenshot failed: {str(e)}'
|
||||
return ActionResult(error=error_msg)
|
||||
|
||||
|
||||
@tools.registry.action(
|
||||
"Extract text from elements using Playwright's powerful CSS selectors and XPath support.", param_model=PlaywrightGetTextAction
|
||||
)
|
||||
async def playwright_get_text(params: PlaywrightGetTextAction, browser_session: BrowserSession):
|
||||
"""
|
||||
Custom action that uses Playwright's advanced text extraction with CSS selectors and XPath.
|
||||
"""
|
||||
try:
|
||||
if not playwright_page:
|
||||
return ActionResult(error='Playwright not connected. Run setup first.')
|
||||
|
||||
# Extracting text with Playwright selectors
|
||||
|
||||
# Handle special selectors
|
||||
if params.selector.lower() == 'title':
|
||||
# Use page.title() for title element
|
||||
text_content = await playwright_page.title()
|
||||
result_data = {
|
||||
'selector': 'title',
|
||||
'text_content': text_content,
|
||||
'inner_text': text_content,
|
||||
'tag_name': 'TITLE',
|
||||
'is_visible': True,
|
||||
}
|
||||
else:
|
||||
# Use Playwright's robust element selection and text extraction
|
||||
element = playwright_page.locator(params.selector).first
|
||||
|
||||
if await element.count() == 0:
|
||||
error_msg = f'❌ No element found with selector: {params.selector}'
|
||||
return ActionResult(error=error_msg)
|
||||
|
||||
text_content = await element.text_content()
|
||||
inner_text = await element.inner_text()
|
||||
|
||||
# Get additional element info
|
||||
tag_name = await element.evaluate('el => el.tagName')
|
||||
is_visible = await element.is_visible()
|
||||
|
||||
result_data = {
|
||||
'selector': params.selector,
|
||||
'text_content': text_content,
|
||||
'inner_text': inner_text,
|
||||
'tag_name': tag_name,
|
||||
'is_visible': is_visible,
|
||||
}
|
||||
|
||||
success_msg = f'✅ Extracted text using Playwright: {result_data}'
|
||||
|
||||
return ActionResult(
|
||||
extracted_content=str(result_data),
|
||||
include_in_memory=True,
|
||||
long_term_memory=f'Extracted from {params.selector}: {result_data["text_content"]}',
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f'❌ Playwright text extraction failed: {str(e)}'
|
||||
return ActionResult(error=error_msg)
|
||||
|
||||
|
||||
async def main():
|
||||
"""
|
||||
Main function demonstrating Browser-Use + Playwright integration with custom actions.
|
||||
"""
|
||||
print('🚀 Advanced Playwright + Browser-Use Integration with Custom Actions')
|
||||
|
||||
chrome_process = None
|
||||
try:
|
||||
# Step 1: Start Chrome with CDP debugging
|
||||
chrome_process = await start_chrome_with_debug_port()
|
||||
cdp_url = 'http://localhost:9222'
|
||||
|
||||
# Step 2: Connect Playwright to the same Chrome instance
|
||||
await connect_playwright_to_cdp(cdp_url)
|
||||
|
||||
# Step 3: Create Browser-Use session connected to same Chrome
|
||||
browser_session = BrowserSession(cdp_url=cdp_url)
|
||||
|
||||
# Step 4: Create AI agent with our custom Playwright-powered tools
|
||||
agent = Agent(
|
||||
task="""
|
||||
Please help me demonstrate the integration between Browser-Use and Playwright:
|
||||
|
||||
1. First, navigate to https://httpbin.org/forms/post
|
||||
2. Use the 'playwright_fill_form' action to fill the form with these details:
|
||||
- Customer name: "Alice Johnson"
|
||||
- Phone: "555-9876"
|
||||
- Email: "alice@demo.com"
|
||||
- Size: "large"
|
||||
3. Take a screenshot using the 'playwright_screenshot' action and save it as "form_demo.png"
|
||||
4. Extract the title of the page using 'playwright_get_text' action with selector "title"
|
||||
5. Finally, submit the form and tell me what happened
|
||||
|
||||
This demonstrates how Browser-Use AI can orchestrate tasks while using Playwright's precise capabilities for specific operations.
|
||||
""",
|
||||
llm=ChatOpenAI(model='gpt-4.1-mini'),
|
||||
tools=tools, # Our custom tools with Playwright actions
|
||||
browser_session=browser_session,
|
||||
)
|
||||
|
||||
print('🎯 Starting AI agent with custom Playwright actions...')
|
||||
|
||||
# Step 5: Run the agent - it will use both Browser-Use actions and our custom Playwright actions
|
||||
result = await agent.run()
|
||||
|
||||
# Keep browser open briefly to see results
|
||||
print(f'✅ Integration demo completed! Result: {result}')
|
||||
await asyncio.sleep(2) # Brief pause to see results
|
||||
|
||||
except Exception as e:
|
||||
print(f'❌ Error: {e}')
|
||||
raise
|
||||
|
||||
finally:
|
||||
# Clean up resources
|
||||
if playwright_browser:
|
||||
await playwright_browser.close()
|
||||
|
||||
if chrome_process:
|
||||
chrome_process.terminate()
|
||||
try:
|
||||
await asyncio.wait_for(chrome_process.wait(), 5)
|
||||
except TimeoutError:
|
||||
chrome_process.kill()
|
||||
|
||||
print('✅ Cleanup complete')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Run the advanced integration demo
|
||||
asyncio.run(main())
|
||||
```
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
title: "Secure Setup"
|
||||
description: "Azure OpenAI with data privacy and security configuration."
|
||||
icon: "shield-check"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Secure Setup with Azure OpenAI
|
||||
|
||||
Enterprise-grade security with Azure OpenAI, data privacy protection, and restricted browser access.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
os.environ['ANONYMIZED_TELEMETRY'] = 'false'
|
||||
from browser_use import Agent, BrowserProfile, ChatAzureOpenAI
|
||||
|
||||
# Azure OpenAI configuration
|
||||
api_key = os.getenv('AZURE_OPENAI_KEY')
|
||||
azure_endpoint = os.getenv('AZURE_OPENAI_ENDPOINT')
|
||||
llm = ChatAzureOpenAI(model='gpt-4.1-mini', api_key=api_key, azure_endpoint=azure_endpoint)
|
||||
|
||||
# Secure browser configuration
|
||||
browser_profile = BrowserProfile(
|
||||
allowed_domains=['*google.com', 'browser-use.com'],
|
||||
enable_default_extensions=False
|
||||
)
|
||||
|
||||
# Sensitive data filtering
|
||||
sensitive_data = {'company_name': 'browser-use'}
|
||||
|
||||
# Create secure agent
|
||||
agent = Agent(
|
||||
task='Find the founders of the sensitive company_name',
|
||||
llm=llm,
|
||||
browser_profile=browser_profile,
|
||||
sensitive_data=sensitive_data
|
||||
)
|
||||
|
||||
async def main():
|
||||
await agent.run(max_steps=10)
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## Security Features
|
||||
|
||||
**Azure OpenAI:**
|
||||
- NOT used to train OpenAI models
|
||||
- NOT shared with other customers
|
||||
- Hosted entirely within Azure
|
||||
- 30-day retention (or zero with Limited Access Program)
|
||||
|
||||
**Browser Security:**
|
||||
- `allowed_domains`: Restrict navigation to trusted sites
|
||||
- `enable_default_extensions=False`: Disable potentially dangerous extensions
|
||||
- `sensitive_data`: Filter sensitive information from LLM input
|
||||
|
||||
|
||||
|
||||
<Note>
|
||||
For enterprise deployments contact support@browser-use.com.
|
||||
</Note>
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: "Sensitive Data"
|
||||
description: "Handle secret information securely and avoid sending PII & passwords to the LLM."
|
||||
icon: "shield"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
|
||||
```python
|
||||
import os
|
||||
from browser_use import Agent, Browser, ChatOpenAI
|
||||
os.environ['ANONYMIZED_TELEMETRY'] = "false"
|
||||
|
||||
|
||||
company_credentials = {'x_user': 'your-real-username@email.com', 'x_pass': 'your-real-password123'}
|
||||
|
||||
# Option 1: Secrets available for all websites
|
||||
sensitive_data = company_credentials
|
||||
|
||||
# Option 2: Secrets per domain with regex
|
||||
# sensitive_data = {
|
||||
# 'https://*.example-staging.com': company_credentials,
|
||||
# 'http*://test.example.com': company_credentials,
|
||||
# 'https://example.com': company_credentials,
|
||||
# 'https://google.com': {'g_email': 'user@gmail.com', 'g_pass': 'google_password'},
|
||||
# }
|
||||
|
||||
|
||||
agent = Agent(
|
||||
task='Log into example.com with username x_user and password x_pass',
|
||||
sensitive_data=sensitive_data,
|
||||
use_vision=False, # Disable vision to prevent LLM seeing sensitive data in screenshots
|
||||
llm=ChatOpenAI(model='gpt-4.1-mini'),
|
||||
)
|
||||
async def main():
|
||||
await agent.run()
|
||||
```
|
||||
|
||||
## How it Works
|
||||
1. **Text Filtering**: The LLM only sees placeholders (`x_user`, `x_pass`), we filter your sensitive data from the input text.
|
||||
2. **DOM Actions**: Real values are injected directly into form fields after the LLM call
|
||||
|
||||
## Best Practices
|
||||
- Use `Browser(allowed_domains=[...])` to restrict navigation
|
||||
- Set `use_vision=False` to prevent screenshot leaks
|
||||
- Use `storage_state='./auth.json'` for login cookies instead of passwords when possible
|
||||
Reference in New Issue
Block a user