chore: import upstream snapshot with attribution
Test Browser Use CLI Install / uv pip install (ubuntu-latest) (push) Failing after 1s
Test Browser Use CLI Install / uvx browser-use from local wheel (push) Failing after 1s
Test Browser Use CLI Install / uvx browser-use[cli] from PyPI (push) Failing after 1s
package / pip-install-on-macos-latest-py-3.11 (push) Has been skipped
package / pip-install-on-macos-latest-py-3.13 (push) Has been skipped
package / pip-install-on-ubuntu-latest-py-3.11 (push) Has been skipped
package / pip-install-on-windows-latest-py-3.13 (push) Has been skipped
cloud_evals / trigger_cloud_eval_image_build (push) Failing after 1s
docker / build_publish_image (push) Failing after 1s
Test Browser Use CLI Install / browser-use skill sync (push) Failing after 1s
lint / code-style (push) Failing after 0s
lint / type-checker (push) Failing after 1s
package / pip-build (push) Failing after 1s
lint / syntax-errors (push) Failing after 3s
package / pip-install-on-ubuntu-latest-py-3.13 (push) Has been skipped
package / pip-install-on-windows-latest-py-3.11 (push) Has been skipped
test / ${{ matrix.test_filename }} (push) Has been skipped
test / evaluate-tasks (push) Has been skipped
test / setup-chromium (push) Failing after 2s
test / find_tests (push) Failing after 2s
Test Browser Use CLI Install / uv pip install (windows-latest) (push) Has been cancelled
Test Browser Use CLI Install / uv pip install (macos-latest) (push) Has been cancelled
Test Browser Use CLI Install / uv pip install (ubuntu-latest) (push) Failing after 1s
Test Browser Use CLI Install / uvx browser-use from local wheel (push) Failing after 1s
Test Browser Use CLI Install / uvx browser-use[cli] from PyPI (push) Failing after 1s
package / pip-install-on-macos-latest-py-3.11 (push) Has been skipped
package / pip-install-on-macos-latest-py-3.13 (push) Has been skipped
package / pip-install-on-ubuntu-latest-py-3.11 (push) Has been skipped
package / pip-install-on-windows-latest-py-3.13 (push) Has been skipped
cloud_evals / trigger_cloud_eval_image_build (push) Failing after 1s
docker / build_publish_image (push) Failing after 1s
Test Browser Use CLI Install / browser-use skill sync (push) Failing after 1s
lint / code-style (push) Failing after 0s
lint / type-checker (push) Failing after 1s
package / pip-build (push) Failing after 1s
lint / syntax-errors (push) Failing after 3s
package / pip-install-on-ubuntu-latest-py-3.13 (push) Has been skipped
package / pip-install-on-windows-latest-py-3.11 (push) Has been skipped
test / ${{ matrix.test_filename }} (push) Has been skipped
test / evaluate-tasks (push) Has been skipped
test / setup-chromium (push) Failing after 2s
test / find_tests (push) Failing after 2s
Test Browser Use CLI Install / uv pip install (windows-latest) (push) Has been cancelled
Test Browser Use CLI Install / uv pip install (macos-latest) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
"""
|
||||
Show how to use sample_images to add image context for your task
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import base64
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from browser_use import Agent
|
||||
from browser_use.llm import ChatOpenAI
|
||||
from browser_use.llm.messages import ContentPartImageParam, ContentPartTextParam, ImageURL
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
|
||||
def image_to_base64(image_path: str) -> str:
|
||||
"""
|
||||
Convert image file to base64 string.
|
||||
|
||||
Args:
|
||||
image_path: Path to the image file
|
||||
|
||||
Returns:
|
||||
Base64 encoded string of the image
|
||||
|
||||
Raises:
|
||||
FileNotFoundError: If image file doesn't exist
|
||||
IOError: If image file cannot be read
|
||||
"""
|
||||
image_file = Path(image_path)
|
||||
if not image_file.exists():
|
||||
raise FileNotFoundError(f'Image file not found: {image_path}')
|
||||
|
||||
try:
|
||||
with open(image_file, 'rb') as f:
|
||||
encoded_string = base64.b64encode(f.read())
|
||||
return encoded_string.decode('utf-8')
|
||||
except OSError as e:
|
||||
raise OSError(f'Failed to read image file: {e}')
|
||||
|
||||
|
||||
def create_sample_images() -> list[ContentPartTextParam | ContentPartImageParam]:
|
||||
"""
|
||||
Create image context for the agent.
|
||||
|
||||
Returns:
|
||||
list of content parts containing text and image data
|
||||
"""
|
||||
# Image path - replace with your actual image path
|
||||
image_path = 'sample_image.png'
|
||||
|
||||
# Image context configuration
|
||||
image_context: list[dict[str, Any]] = [
|
||||
{
|
||||
'type': 'text',
|
||||
'value': (
|
||||
'The following image explains the google layout. '
|
||||
'The image highlights several buttons with red boxes, '
|
||||
'and next to them are corresponding labels in red text.\n'
|
||||
'Each label corresponds to a button as follows:\n'
|
||||
'Label 1 is the "image" button.'
|
||||
),
|
||||
},
|
||||
{'type': 'image', 'value': image_to_base64(image_path)},
|
||||
]
|
||||
|
||||
# Convert to content parts
|
||||
content_parts = []
|
||||
for item in image_context:
|
||||
if item['type'] == 'text':
|
||||
content_parts.append(ContentPartTextParam(text=item['value']))
|
||||
elif item['type'] == 'image':
|
||||
content_parts.append(
|
||||
ContentPartImageParam(
|
||||
image_url=ImageURL(
|
||||
url=f'data:image/jpeg;base64,{item["value"]}',
|
||||
media_type='image/jpeg',
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
return content_parts
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""
|
||||
Main function to run the browser agent with image context.
|
||||
"""
|
||||
# Task configuration
|
||||
task_str = 'goto https://www.google.com/ and click image button'
|
||||
|
||||
# Initialize the language model
|
||||
model = ChatOpenAI(model='gpt-4.1')
|
||||
|
||||
# Create sample images for context
|
||||
try:
|
||||
sample_images = create_sample_images()
|
||||
except (FileNotFoundError, OSError) as e:
|
||||
print(f'Error loading sample images: {e}')
|
||||
print('Continuing without sample images...')
|
||||
sample_images = []
|
||||
|
||||
# Initialize and run the agent
|
||||
agent = Agent(task=task_str, llm=model, sample_images=sample_images)
|
||||
await agent.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,64 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
from browser_use.browser import BrowserProfile, BrowserSession
|
||||
|
||||
llm = ChatOpenAI(model='gpt-4o-mini')
|
||||
|
||||
# Example task: Try to navigate to various sites including blocked ones
|
||||
task = 'Navigate to example.com, then try to go to x.com, then facebook.com, and finally visit google.com. Tell me which sites you were able to access.'
|
||||
|
||||
prohibited_domains = [
|
||||
'x.com', # Block X (formerly Twitter) - "locked the f in"
|
||||
'twitter.com', # Block Twitter (redirects to x.com anyway)
|
||||
'facebook.com', # Lock the F in Facebook too
|
||||
'*.meta.com', # Block all Meta properties (wildcard pattern)
|
||||
'*.adult-site.com', # Block all subdomains of adult sites
|
||||
'https://explicit-content.org', # Block specific protocol/domain
|
||||
'gambling-site.net', # Block gambling sites
|
||||
]
|
||||
|
||||
# Note: For lists with 100+ domains, automatic optimization kicks in:
|
||||
# - Converts list to set for O(1) lookup (blazingly fast!)
|
||||
# - Pattern matching (*.domain) is disabled for large lists
|
||||
# - Both www.example.com and example.com variants are checked automatically
|
||||
# Perfect for ad blockers or large malware domain lists (e.g., 400k+ domains)
|
||||
|
||||
browser_session = BrowserSession(
|
||||
browser_profile=BrowserProfile(
|
||||
prohibited_domains=prohibited_domains,
|
||||
headless=False, # Set to True to run without visible browser
|
||||
user_data_dir='~/.config/browseruse/profiles/blocked-demo',
|
||||
),
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
task=task,
|
||||
llm=llm,
|
||||
browser_session=browser_session,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
print('Demo: Blocked Domains Feature - "Lock the F in" Edition')
|
||||
print("We're literally locking the F in Facebook and X!")
|
||||
print(f'Prohibited domains: {prohibited_domains}')
|
||||
print('The agent will try to visit various sites, but blocked domains will be prevented.')
|
||||
print()
|
||||
|
||||
await agent.run(max_steps=10)
|
||||
|
||||
input('Press Enter to close the browser...')
|
||||
await browser_session.kill()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
Generate CSV files with automatic normalization.
|
||||
|
||||
The agent's file system automatically normalizes CSV output using Python's csv module,
|
||||
so fields containing commas, quotes, or empty values are properly handled per RFC 4180.
|
||||
This means the agent doesn't need to worry about manual quoting — it's fixed at the
|
||||
infrastructure level.
|
||||
|
||||
Common LLM mistakes that are auto-corrected:
|
||||
- Unquoted fields containing commas (e.g. "San Francisco, CA" without quotes)
|
||||
- Unescaped double quotes inside fields
|
||||
- Inconsistent empty field handling
|
||||
- Stray blank lines
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatBrowserUse
|
||||
|
||||
|
||||
async def main():
|
||||
agent = Agent(
|
||||
task=(
|
||||
'Go to https://en.wikipedia.org/wiki/List_of_largest_cities and extract the top 10 cities. '
|
||||
'Create a CSV file called "top_cities.csv" with columns: rank, city name, country, population. '
|
||||
'Make sure to include all cities even if some data is missing — leave those cells empty.'
|
||||
),
|
||||
llm=ChatBrowserUse(model='bu-2-0'),
|
||||
)
|
||||
|
||||
history = await agent.run()
|
||||
|
||||
# Check the generated CSV file
|
||||
if agent.file_system:
|
||||
csv_file = agent.file_system.get_file('top_cities.csv')
|
||||
if csv_file:
|
||||
print('\nGenerated CSV content:')
|
||||
print(csv_file.content)
|
||||
print(f'\nFile saved to: {agent.file_system.get_dir() / csv_file.full_name}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,55 @@
|
||||
"""
|
||||
Show how to use custom outputs.
|
||||
|
||||
@dev You need to add OPENAI_API_KEY to your environment variables.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
|
||||
|
||||
class Post(BaseModel):
|
||||
post_title: str
|
||||
post_url: str
|
||||
num_comments: int
|
||||
hours_since_post: int
|
||||
|
||||
|
||||
class Posts(BaseModel):
|
||||
posts: list[Post]
|
||||
|
||||
|
||||
async def main():
|
||||
task = 'Go to hackernews show hn and give me the first 5 posts'
|
||||
model = ChatOpenAI(model='gpt-4.1-mini')
|
||||
agent = Agent(task=task, llm=model, output_model_schema=Posts)
|
||||
|
||||
history = await agent.run()
|
||||
|
||||
result = history.final_result()
|
||||
if result:
|
||||
parsed: Posts = Posts.model_validate_json(result)
|
||||
|
||||
for post in parsed.posts:
|
||||
print('\n--------------------------------')
|
||||
print(f'Title: {post.post_title}')
|
||||
print(f'URL: {post.post_url}')
|
||||
print(f'Comments: {post.num_comments}')
|
||||
print(f'Hours since post: {post.hours_since_post}')
|
||||
else:
|
||||
print('No result')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,38 @@
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
|
||||
extend_system_message = (
|
||||
'REMEMBER the most important RULE: ALWAYS open first a new tab and go first to url wikipedia.com no matter the task!!!'
|
||||
)
|
||||
|
||||
# or use override_system_message to completely override the system prompt
|
||||
|
||||
|
||||
async def main():
|
||||
task = 'do google search to find images of Elon Musk'
|
||||
model = ChatOpenAI(model='gpt-4.1-mini')
|
||||
agent = Agent(task=task, llm=model, extend_system_message=extend_system_message)
|
||||
|
||||
print(
|
||||
json.dumps(
|
||||
agent.message_manager.system_prompt.model_dump(exclude_unset=True),
|
||||
indent=4,
|
||||
)
|
||||
)
|
||||
|
||||
await agent.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,34 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
from browser_use import Agent, Browser, ChatGoogle
|
||||
|
||||
api_key = os.getenv('GOOGLE_API_KEY')
|
||||
if not api_key:
|
||||
raise ValueError('GOOGLE_API_KEY is not set')
|
||||
|
||||
llm = ChatGoogle(model='gemini-2.5-flash', api_key=api_key)
|
||||
|
||||
|
||||
browser = Browser(downloads_path='~/Downloads/tmp')
|
||||
|
||||
|
||||
async def run_download():
|
||||
agent = Agent(
|
||||
task='Go to "https://file-examples.com/" and download the smallest doc file. then go back and get the next file.',
|
||||
llm=llm,
|
||||
browser=browser,
|
||||
)
|
||||
await agent.run(max_steps=25)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(run_download())
|
||||
@@ -0,0 +1,55 @@
|
||||
"""
|
||||
Example: Using a fallback LLM model.
|
||||
|
||||
When the primary LLM fails with rate limits (429), authentication errors (401),
|
||||
payment/credit errors (402), or server errors (500, 502, 503, 504), the agent
|
||||
automatically switches to the fallback model and continues execution.
|
||||
|
||||
Note: The primary LLM will first exhaust its own retry logic (typically 5 attempts
|
||||
with exponential backoff) before the fallback is triggered. This means transient errors
|
||||
are handled by the provider's built-in retries, and the fallback only kicks in when
|
||||
the provider truly can't recover.
|
||||
|
||||
This is useful for:
|
||||
- High availability: Keep your agent running even when one provider has issues
|
||||
- Cost optimization: Use a cheaper model as fallback when the primary is rate limited
|
||||
- Multi-provider resilience: Switch between OpenAI, Anthropic, Google, etc.
|
||||
|
||||
@dev You need to add OPENAI_API_KEY and ANTHROPIC_API_KEY to your environment variables.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent
|
||||
from browser_use.llm import ChatAnthropic, ChatOpenAI
|
||||
|
||||
llm = ChatAnthropic(model='claude-sonnet-4-0')
|
||||
fallback_llm = ChatOpenAI(model='gpt-4o')
|
||||
|
||||
agent = Agent(
|
||||
task='Go to github.com and find the browser-use repository',
|
||||
llm=llm,
|
||||
fallback_llm=fallback_llm,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
result = await agent.run()
|
||||
print(result)
|
||||
|
||||
# You can check if fallback was used:
|
||||
if agent.is_using_fallback_llm:
|
||||
print('Note: Agent switched to fallback LLM during execution')
|
||||
print(f'Current model: {agent.current_llm_model}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,24 @@
|
||||
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()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,32 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
from browser_use.browser.profile import BrowserProfile
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent
|
||||
|
||||
profile = BrowserProfile(keep_alive=True)
|
||||
|
||||
|
||||
task = """Go to reddit.com"""
|
||||
|
||||
|
||||
async def main():
|
||||
agent = Agent(task=task, browser_profile=profile)
|
||||
await agent.run(max_steps=1)
|
||||
|
||||
while True:
|
||||
user_response = input('\n👤 New task or "q" to quit: ')
|
||||
agent.add_new_task(f'New task: {user_response}')
|
||||
await agent.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,31 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
|
||||
llm = ChatOpenAI(model='gpt-4.1-mini')
|
||||
|
||||
initial_actions = [
|
||||
{'navigate': {'url': 'https://www.google.com', 'new_tab': True}},
|
||||
{'navigate': {'url': 'https://en.wikipedia.org/wiki/Randomness', 'new_tab': True}},
|
||||
]
|
||||
agent = Agent(
|
||||
task='What theories are displayed on the page?',
|
||||
initial_actions=initial_actions,
|
||||
llm=llm,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
await agent.run(max_steps=10)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,47 @@
|
||||
"""
|
||||
Setup:
|
||||
1. Get your API key from https://cloud.browser-use.com/new-api-key
|
||||
2. Set environment variable: export BROWSER_USE_API_KEY="your-key"
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Add the parent directory to the path so we can import browser_use
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent
|
||||
from browser_use.llm.browser_use.chat import ChatBrowserUse
|
||||
|
||||
# task from GAIA
|
||||
task = """
|
||||
If Eliud Kipchoge could maintain his record-making marathon pace indefinitely, how many thousand hours would it take him to run the distance between the Earth and the Moon its closest approach?
|
||||
Please use the minimum perigee value on the Wikipedia page for the Moon when carrying out your calculation.
|
||||
Round your result to the nearest 1000 hours and do not use any comma separators if necessary.
|
||||
"""
|
||||
|
||||
|
||||
async def main():
|
||||
llm = ChatBrowserUse(model='bu-2-0')
|
||||
agent = Agent(
|
||||
task=task,
|
||||
llm=llm,
|
||||
use_judge=True,
|
||||
judge_llm=llm,
|
||||
ground_truth='16', # The TRUE answer is 17 but we put 16 to demonstrate judge can detect when the answer is wrong.
|
||||
)
|
||||
history = await agent.run()
|
||||
|
||||
# Get the judgement result
|
||||
if history.is_judged():
|
||||
judgement = history.judgement()
|
||||
print(f'Agent history judgement: {judgement}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,117 @@
|
||||
"""
|
||||
Example: Using large blocklists (400k+ domains) with automatic optimization
|
||||
|
||||
This example demonstrates:
|
||||
1. Loading a real-world blocklist (HaGeZi's Pro++ with 439k+ domains)
|
||||
2. Automatic conversion to set for O(1) lookup performance
|
||||
3. Testing that blocked domains are actually blocked
|
||||
|
||||
Performance: ~0.02ms per domain check (50,000+ checks/second!)
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
from browser_use.browser import BrowserProfile, BrowserSession
|
||||
|
||||
llm = ChatOpenAI(model='gpt-4.1-mini')
|
||||
|
||||
|
||||
def load_blocklist_from_url(url: str) -> list[str]:
|
||||
"""Load and parse a blocklist from a URL.
|
||||
|
||||
Args:
|
||||
url: URL to the blocklist file
|
||||
|
||||
Returns:
|
||||
List of domain strings (comments and empty lines removed)
|
||||
"""
|
||||
import urllib.request
|
||||
|
||||
print(f'📥 Downloading blocklist from {url}...')
|
||||
|
||||
domains = []
|
||||
with urllib.request.urlopen(url) as response:
|
||||
for line in response:
|
||||
line = line.decode('utf-8').strip()
|
||||
# Skip comments and empty lines
|
||||
if line and not line.startswith('#'):
|
||||
domains.append(line)
|
||||
|
||||
print(f'✅ Loaded {len(domains):,} domains')
|
||||
return domains
|
||||
|
||||
|
||||
async def main():
|
||||
# Load HaGeZi's Pro++ blocklist (blocks ads, tracking, malware, etc.)
|
||||
# Source: https://github.com/hagezi/dns-blocklists
|
||||
blocklist_url = 'https://gitlab.com/hagezi/mirror/-/raw/main/dns-blocklists/domains/pro.plus.txt'
|
||||
|
||||
print('=' * 70)
|
||||
print('🚀 Large Blocklist Demo - 439k+ Blocked Domains')
|
||||
print('=' * 70)
|
||||
print()
|
||||
|
||||
# Load the blocklist
|
||||
prohibited_domains = load_blocklist_from_url(blocklist_url)
|
||||
|
||||
# Sample some blocked domains to test
|
||||
test_blocked = [prohibited_domains[0], prohibited_domains[1000], prohibited_domains[-1]]
|
||||
print(f'\n📋 Sample blocked domains: {", ".join(test_blocked[:3])}')
|
||||
|
||||
print(f'\n🔧 Creating browser with {len(prohibited_domains):,} blocked domains...')
|
||||
print(' (Auto-optimizing to set for O(1) lookup performance)')
|
||||
|
||||
# Create browser with the blocklist
|
||||
# The list will be automatically optimized to a set for fast lookups
|
||||
browser_session = BrowserSession(
|
||||
browser_profile=BrowserProfile(
|
||||
prohibited_domains=prohibited_domains,
|
||||
headless=False,
|
||||
user_data_dir='~/.config/browseruse/profiles/blocklist-demo',
|
||||
),
|
||||
)
|
||||
|
||||
# Task: Try to visit a blocked domain and a safe domain
|
||||
blocked_site = test_blocked[0] # Will be blocked
|
||||
safe_site = 'github.com' # Will be allowed
|
||||
|
||||
task = f"""
|
||||
Try to navigate to these websites and report what happens:
|
||||
1. First, try to visit https://{blocked_site}
|
||||
2. Then, try to visit https://{safe_site}
|
||||
|
||||
Tell me which sites you were able to access and which were blocked.
|
||||
"""
|
||||
|
||||
agent = Agent(
|
||||
task=task,
|
||||
llm=llm,
|
||||
browser_session=browser_session,
|
||||
)
|
||||
|
||||
print(f'\n🤖 Agent task: Try to visit {blocked_site} (blocked) and {safe_site} (allowed)')
|
||||
print('\n' + '=' * 70)
|
||||
|
||||
await agent.run(max_steps=5)
|
||||
|
||||
print('\n' + '=' * 70)
|
||||
print('✅ Demo complete!')
|
||||
print(f'💡 The blocklist with {len(prohibited_domains):,} domains was optimized to a set')
|
||||
print(' for instant O(1) domain checking (vs slow O(n) pattern matching)')
|
||||
print('=' * 70)
|
||||
|
||||
input('\nPress Enter to close the browser...')
|
||||
await browser_session.kill()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,31 @@
|
||||
"""
|
||||
Simple try of the agent.
|
||||
|
||||
@dev You need to add OPENAI_API_KEY to your environment variables.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
|
||||
# video: https://preview.screen.studio/share/clenCmS6
|
||||
llm = ChatOpenAI(model='gpt-4.1-mini')
|
||||
agent = Agent(
|
||||
task='open 3 tabs with elon musk, sam altman, and steve jobs, then go back to the first and stop',
|
||||
llm=llm,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
await agent.run()
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,51 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import ChatOpenAI
|
||||
from browser_use.agent.service import Agent
|
||||
from browser_use.browser import BrowserProfile, BrowserSession
|
||||
|
||||
browser_session = BrowserSession(
|
||||
browser_profile=BrowserProfile(
|
||||
keep_alive=True,
|
||||
headless=False,
|
||||
record_video_dir=Path('./tmp/recordings'),
|
||||
user_data_dir='~/.config/browseruse/profiles/default',
|
||||
)
|
||||
)
|
||||
llm = ChatOpenAI(model='gpt-4.1-mini')
|
||||
|
||||
|
||||
# NOTE: This is experimental - you will have multiple agents running in the same browser session
|
||||
async def main():
|
||||
await browser_session.start()
|
||||
agents = [
|
||||
Agent(task=task, llm=llm, browser_session=browser_session)
|
||||
for task in [
|
||||
'Search Google for weather in Tokyo',
|
||||
'Check Reddit front page title',
|
||||
'Look up Bitcoin price on Coinbase',
|
||||
# 'Find NASA image of the day',
|
||||
# 'Check top story on CNN',
|
||||
# 'Search latest SpaceX launch date',
|
||||
# 'Look up population of Paris',
|
||||
# 'Find current time in Sydney',
|
||||
# 'Check who won last Super Bowl',
|
||||
# 'Search trending topics on Twitter',
|
||||
]
|
||||
]
|
||||
|
||||
print(await asyncio.gather(*[agent.run() for agent in agents]))
|
||||
await browser_session.kill()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,55 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
from pprint import pprint
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
from browser_use.agent.views import AgentHistoryList
|
||||
from browser_use.browser import BrowserProfile, BrowserSession
|
||||
from browser_use.browser.profile import ViewportSize
|
||||
|
||||
llm = ChatOpenAI(model='gpt-4.1-mini')
|
||||
|
||||
|
||||
async def main():
|
||||
browser_session = BrowserSession(
|
||||
browser_profile=BrowserProfile(
|
||||
headless=False,
|
||||
traces_dir='./tmp/result_processing',
|
||||
window_size=ViewportSize(width=1280, height=1000),
|
||||
user_data_dir='~/.config/browseruse/profiles/default',
|
||||
)
|
||||
)
|
||||
await browser_session.start()
|
||||
try:
|
||||
agent = Agent(
|
||||
task="go to google.com and type 'OpenAI' click search and give me the first url",
|
||||
llm=llm,
|
||||
browser_session=browser_session,
|
||||
)
|
||||
history: AgentHistoryList = await agent.run(max_steps=3)
|
||||
|
||||
print('Final Result:')
|
||||
pprint(history.final_result(), indent=4)
|
||||
|
||||
print('\nErrors:')
|
||||
pprint(history.errors(), indent=4)
|
||||
|
||||
# e.g. xPaths the model clicked on
|
||||
print('\nModel Outputs:')
|
||||
pprint(history.model_actions(), indent=4)
|
||||
|
||||
print('\nThoughts:')
|
||||
pprint(history.model_thoughts(), indent=4)
|
||||
finally:
|
||||
await browser_session.stop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,141 @@
|
||||
"""
|
||||
Example: Rerunning saved agent history with variable detection and substitution
|
||||
|
||||
This example shows how to:
|
||||
1. Run an agent and save its history (including initial URL navigation)
|
||||
2. Detect variables in the saved history (emails, names, dates, etc.)
|
||||
3. Rerun the history with substituted values (different data)
|
||||
4. Get AI-generated summary of rerun completion (with screenshot analysis)
|
||||
|
||||
Useful for:
|
||||
- Debugging agent behavior
|
||||
- Testing changes with consistent scenarios
|
||||
- Replaying successful workflows with different data
|
||||
- Understanding what values can be substituted in reruns
|
||||
- Getting automated verification of rerun success
|
||||
|
||||
Note: Initial actions (like opening URLs from tasks) are now automatically
|
||||
saved to history and will be replayed during rerun, so you don't need to
|
||||
worry about manually specifying URLs when rerunning.
|
||||
|
||||
AI Features During Rerun:
|
||||
|
||||
1. AI Step for Extract Actions:
|
||||
When an 'extract' action is replayed, the rerun automatically uses AI to
|
||||
re-analyze the current page content (since it may have changed with new data).
|
||||
This ensures the extracted content reflects the current state, not cached results.
|
||||
|
||||
2. AI Summary:
|
||||
At the end of the rerun, an AI summary analyzes the final screenshot and
|
||||
execution statistics to determine success/failure.
|
||||
|
||||
Custom LLM Usage:
|
||||
# Option 1: Use agent's LLM (default)
|
||||
results = await agent.load_and_rerun(history_file)
|
||||
|
||||
# Option 2: Use custom LLMs for AI steps and summary
|
||||
from browser_use.llm import ChatOpenAI
|
||||
custom_llm = ChatOpenAI(model='gpt-4.1-mini')
|
||||
results = await agent.load_and_rerun(
|
||||
history_file,
|
||||
ai_step_llm=custom_llm, # For extract action re-evaluation
|
||||
summary_llm=custom_llm, # For final summary
|
||||
)
|
||||
|
||||
The AI summary will be the last item in results and will have:
|
||||
- extracted_content: The summary text
|
||||
- success: Whether rerun was successful
|
||||
- is_done: Always True for summary
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
from browser_use import Agent
|
||||
from browser_use.llm import ChatBrowserUse
|
||||
|
||||
|
||||
async def main():
|
||||
# Example task to demonstrate history saving and rerunning
|
||||
history_file = Path('agent_history.json')
|
||||
task = 'Go to https://browser-use.github.io/stress-tests/challenges/reference-number-form.html and fill the form with example data and submit and extract the refernence number.'
|
||||
llm = ChatBrowserUse(model='bu-2-0')
|
||||
|
||||
# Optional: Use custom LLMs for AI features during rerun
|
||||
# Uncomment to use a custom LLM:
|
||||
# from browser_use.llm import ChatOpenAI
|
||||
# custom_llm = ChatOpenAI(model='gpt-4.1-mini')
|
||||
# ai_step_llm = custom_llm # For re-evaluating extract actions
|
||||
# summary_llm = custom_llm # For final summary
|
||||
ai_step_llm = None # Set to None to use agent's LLM (default)
|
||||
summary_llm = None # Set to None to use agent's LLM (default)
|
||||
|
||||
# Step 1: Run the agent and save history
|
||||
print('=== Running Agent ===')
|
||||
agent = Agent(task=task, llm=llm, max_actions_per_step=1)
|
||||
await agent.run(max_steps=10)
|
||||
agent.save_history(history_file)
|
||||
print(f'✓ History saved to {history_file}')
|
||||
|
||||
# Step 2: Detect variables in the saved history
|
||||
print('\n=== Detecting Variables ===')
|
||||
variables = agent.detect_variables()
|
||||
if variables:
|
||||
print(f'Found {len(variables)} variable(s):')
|
||||
for var_name, var_info in variables.items():
|
||||
format_info = f' (format: {var_info.format})' if var_info.format else ''
|
||||
print(f' • {var_name}: "{var_info.original_value}"{format_info}')
|
||||
else:
|
||||
print('No variables detected in history')
|
||||
|
||||
# Step 3: Rerun the history with substituted values
|
||||
if variables:
|
||||
print('\n=== Rerunning History (Substituted Values) ===')
|
||||
# Create new values for the detected variables
|
||||
new_values = {}
|
||||
for var_name, var_info in variables.items():
|
||||
# Map detected variables to new values
|
||||
if var_name == 'email':
|
||||
new_values[var_name] = 'jane.smith@example.com'
|
||||
elif var_name == 'full_name':
|
||||
new_values[var_name] = 'Jane Smith'
|
||||
elif var_name.startswith('full_name_'):
|
||||
new_values[var_name] = 'General Information'
|
||||
elif var_name == 'first_name':
|
||||
new_values[var_name] = 'Jane'
|
||||
elif var_name == 'date':
|
||||
new_values[var_name] = '1995-05-15'
|
||||
elif var_name == 'country':
|
||||
new_values[var_name] = 'Canada'
|
||||
# You can add more variable substitutions as needed
|
||||
|
||||
if new_values:
|
||||
print(f'Substituting {len(new_values)} variable(s):')
|
||||
for var_name, new_value in new_values.items():
|
||||
old_value = variables[var_name].original_value
|
||||
print(f' • {var_name}: "{old_value}" → "{new_value}"')
|
||||
|
||||
# Rerun with substituted values and optional custom LLMs
|
||||
substitute_agent = Agent(task='', llm=llm)
|
||||
results = await substitute_agent.load_and_rerun(
|
||||
history_file,
|
||||
variables=new_values,
|
||||
ai_step_llm=ai_step_llm, # For extract action re-evaluation
|
||||
summary_llm=summary_llm, # For final summary
|
||||
max_step_interval=20,
|
||||
delay_between_actions=1,
|
||||
)
|
||||
|
||||
# Display AI-generated summary (last result)
|
||||
if results and results[-1].is_done:
|
||||
summary = results[-1]
|
||||
print('\n📊 AI Summary:')
|
||||
print(f' Summary: {summary.extracted_content}')
|
||||
print(f' Success: {summary.success}')
|
||||
print('✓ History rerun with substituted values complete')
|
||||
else:
|
||||
print('\n⚠️ No variables detected, skipping substitution rerun')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,43 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
from browser_use.browser import BrowserProfile, BrowserSession
|
||||
|
||||
llm = ChatOpenAI(model='gpt-4.1-mini')
|
||||
task = (
|
||||
"go to google.com and search for openai.com and click on the first link then extract content and scroll down - what's there?"
|
||||
)
|
||||
|
||||
allowed_domains = ['google.com']
|
||||
|
||||
browser_session = BrowserSession(
|
||||
browser_profile=BrowserProfile(
|
||||
executable_path='/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
||||
allowed_domains=allowed_domains,
|
||||
user_data_dir='~/.config/browseruse/profiles/default',
|
||||
),
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
task=task,
|
||||
llm=llm,
|
||||
browser_session=browser_session,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
await agent.run(max_steps=25)
|
||||
|
||||
input('Press Enter to close the browser...')
|
||||
await browser_session.kill()
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
Save any webpage as a PDF using the save_as_pdf action.
|
||||
|
||||
The agent can save the current page as a PDF at any point during a task.
|
||||
Supports custom filenames, paper sizes (Letter, A4, Legal, A3, Tabloid),
|
||||
landscape orientation, and background printing.
|
||||
|
||||
By default the PDF includes page metadata in the margins (just like Chrome's
|
||||
Print dialog): the date in the header and the page URL plus page numbers in the
|
||||
footer. Pass display_header_footer=False for a clean PDF, or supply custom
|
||||
header_template / footer_template HTML to control exactly what's printed.
|
||||
|
||||
Setup:
|
||||
1. Get your API key from https://cloud.browser-use.com/new-api-key
|
||||
2. Set environment variable: export BROWSER_USE_API_KEY="your-key"
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatBrowserUse
|
||||
|
||||
|
||||
async def main():
|
||||
agent = Agent(
|
||||
task=(
|
||||
'Go to https://news.ycombinator.com and save the front page as a PDF named "hackernews". '
|
||||
'Then go to https://en.wikipedia.org/wiki/Web_browser and save just that article as a PDF in A4 format.'
|
||||
),
|
||||
llm=ChatBrowserUse(model='bu-2-0'),
|
||||
)
|
||||
|
||||
history = await agent.run()
|
||||
|
||||
# Print paths of any PDF files the agent saved
|
||||
print('\nSaved files:')
|
||||
for result in history.action_results():
|
||||
if result.attachments:
|
||||
for path in result.attachments:
|
||||
print(f' {path}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,96 @@
|
||||
# Goal: Automates webpage scrolling with various scrolling actions, including element-specific scrolling.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
from browser_use.browser import BrowserProfile, BrowserSession
|
||||
|
||||
if not os.getenv('OPENAI_API_KEY'):
|
||||
raise ValueError('OPENAI_API_KEY is not set')
|
||||
|
||||
"""
|
||||
Example: Enhanced 'Scroll' action with page amounts and element-specific scrolling.
|
||||
|
||||
This script demonstrates the new enhanced scrolling capabilities:
|
||||
|
||||
1. PAGE-LEVEL SCROLLING:
|
||||
- Scrolling by specific page amounts using 'num_pages' parameter (0.5, 1.0, 2.0, etc.)
|
||||
- Scrolling up or down using the 'down' parameter
|
||||
- Uses JavaScript window.scrollBy() or smart container detection
|
||||
|
||||
2. ELEMENT-SPECIFIC SCROLLING:
|
||||
- NEW: Optional 'index' parameter to scroll within specific elements
|
||||
- Perfect for dropdowns, sidebars, and custom UI components
|
||||
- Uses direct scrollTop manipulation (no mouse events that might close dropdowns)
|
||||
- Automatically finds scroll containers in the element hierarchy
|
||||
- Falls back to page scrolling if no container found
|
||||
|
||||
3. IMPLEMENTATION DETAILS:
|
||||
- Does NOT use mouse movement or wheel events
|
||||
- Direct DOM manipulation for precision and reliability
|
||||
- Container-aware scrolling prevents unwanted side effects
|
||||
"""
|
||||
|
||||
llm = ChatOpenAI(model='gpt-4.1-mini')
|
||||
|
||||
browser_profile = BrowserProfile(headless=False)
|
||||
browser_session = BrowserSession(browser_profile=browser_profile)
|
||||
|
||||
# Example 1: Basic page scrolling with custom amounts
|
||||
agent1 = Agent(
|
||||
task="Navigate to 'https://en.wikipedia.org/wiki/Internet' and scroll down by one page - then scroll up by 0.5 pages - then scroll down by 0.25 pages - then scroll down by 2 pages.",
|
||||
llm=llm,
|
||||
browser_session=browser_session,
|
||||
)
|
||||
|
||||
# Example 2: Element-specific scrolling (dropdowns and containers)
|
||||
agent2 = Agent(
|
||||
task="""Go to https://semantic-ui.com/modules/dropdown.html#/definition and:
|
||||
1. Scroll down in the left sidebar by 2 pages
|
||||
2. Then scroll down 1 page in the main content area
|
||||
3. Click on the State dropdown and scroll down 1 page INSIDE the dropdown to see more states
|
||||
4. The dropdown should stay open while scrolling inside it""",
|
||||
llm=llm,
|
||||
browser_session=browser_session,
|
||||
)
|
||||
|
||||
# Example 3: Text-based scrolling alternative
|
||||
agent3 = Agent(
|
||||
task="Navigate to 'https://en.wikipedia.org/wiki/Internet' and scroll to the text 'The vast majority of computer'",
|
||||
llm=llm,
|
||||
browser_session=browser_session,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
print('Choose which scrolling example to run:')
|
||||
print('1. Basic page scrolling with custom amounts (Wikipedia)')
|
||||
print('2. Element-specific scrolling (Semantic UI dropdowns)')
|
||||
print('3. Text-based scrolling (Wikipedia)')
|
||||
|
||||
choice = input('Enter choice (1-3): ').strip()
|
||||
|
||||
if choice == '1':
|
||||
print('🚀 Running Example 1: Basic page scrolling...')
|
||||
await agent1.run()
|
||||
elif choice == '2':
|
||||
print('🚀 Running Example 2: Element-specific scrolling...')
|
||||
await agent2.run()
|
||||
elif choice == '3':
|
||||
print('🚀 Running Example 3: Text-based scrolling...')
|
||||
await agent3.run()
|
||||
else:
|
||||
print('❌ Invalid choice. Running Example 1 by default...')
|
||||
await agent1.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
Azure OpenAI example with data privacy and high-scale configuration.
|
||||
|
||||
Environment Variables Required:
|
||||
- AZURE_OPENAI_KEY (or AZURE_OPENAI_API_KEY)
|
||||
- AZURE_OPENAI_ENDPOINT
|
||||
- AZURE_OPENAI_DEPLOYMENT (optional)
|
||||
|
||||
DATA PRIVACY WITH AZURE OPENAI:
|
||||
✅ Good News: No Training on Your Data by Default
|
||||
|
||||
Azure OpenAI Service already protects your data:
|
||||
✅ NOT used to train OpenAI models
|
||||
✅ NOT shared with other customers
|
||||
✅ NOT accessible to OpenAI directly
|
||||
✅ NOT used to improve Microsoft/third-party products
|
||||
✅ Hosted entirely within Azure (not OpenAI's servers)
|
||||
|
||||
⚠️ Default Data Retention (30 Days)
|
||||
- Prompts and completions stored for up to 30 days
|
||||
- Purpose: Abuse monitoring and compliance
|
||||
- Access: Microsoft authorized personnel (only if abuse detected)
|
||||
|
||||
🔒 How to Disable Data Logging Completely
|
||||
Apply for Microsoft's "Limited Access Program":
|
||||
1. Contact Microsoft Azure support
|
||||
2. Submit Limited Access Program request
|
||||
3. Demonstrate legitimate business need
|
||||
4. After approval: Zero data logging, immediate deletion, no human review
|
||||
|
||||
For high-scale deployments (500+ agents), consider:
|
||||
- Multiple deployments across regions
|
||||
|
||||
|
||||
How to Verify This Yourself, that there is no data logging:
|
||||
- Network monitoring: Run with network monitoring tools
|
||||
- Firewall rules: Block all domains except Azure OpenAI and your target sites
|
||||
|
||||
Contact us if you need help with this: support@browser-use.com
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
os.environ['ANONYMIZED_TELEMETRY'] = 'false'
|
||||
|
||||
|
||||
from browser_use import Agent, BrowserProfile, ChatAzureOpenAI
|
||||
|
||||
# Configuration LLM
|
||||
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)
|
||||
|
||||
# Configuration Task
|
||||
task = 'Find the founders of the sensitive company_name'
|
||||
|
||||
# Configuration Browser (optional)
|
||||
browser_profile = BrowserProfile(allowed_domains=['*google.com', 'browser-use.com'], enable_default_extensions=False)
|
||||
|
||||
# Sensitive data (optional) - {key: sensitive_information} - we filter out the sensitive_information from any input to the LLM, it will only work with placeholder.
|
||||
# By default we pass screenshots to the LLM which can contain your information. Set use_vision=False to disable this.
|
||||
# If you trust your LLM endpoint, you don't need to worry about this.
|
||||
sensitive_data = {'company_name': 'browser-use'}
|
||||
|
||||
|
||||
# Create Agent
|
||||
agent = Agent(task=task, llm=llm, browser_profile=browser_profile, sensitive_data=sensitive_data) # type: ignore
|
||||
|
||||
|
||||
async def main():
|
||||
await agent.run(max_steps=10)
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,47 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
|
||||
# Initialize the model
|
||||
llm = ChatOpenAI(
|
||||
model='gpt-4.1',
|
||||
temperature=0.0,
|
||||
)
|
||||
# Simple case: the model will see x_name and x_password, but never the actual values.
|
||||
# sensitive_data = {'x_name': 'my_x_name', 'x_password': 'my_x_password'}
|
||||
|
||||
# Advanced case: domain-specific credentials with reusable data
|
||||
# Define a single credential set that can be reused
|
||||
company_credentials: dict[str, str] = {'telephone': '9123456789', 'email': 'user@example.com', 'name': 'John Doe'}
|
||||
|
||||
# Map the same credentials to multiple domains for secure access control
|
||||
# Type annotation to satisfy pyright
|
||||
sensitive_data: dict[str, str | dict[str, str]] = {
|
||||
# 'https://example.com': company_credentials,
|
||||
# 'https://admin.example.com': company_credentials,
|
||||
# 'https://*.example-staging.com': company_credentials,
|
||||
# 'http*://test.example.com': company_credentials,
|
||||
'httpbin.org': company_credentials,
|
||||
# # You can also add domain-specific credentials
|
||||
# 'https://google.com': {'g_email': 'user@gmail.com', 'g_pass': 'google_password'}
|
||||
}
|
||||
# Update task to use one of the credentials above
|
||||
task = 'Go to https://httpbin.org/forms/post and put the secure information in the relevant fields.'
|
||||
|
||||
agent = Agent(task=task, llm=llm, sensitive_data=sensitive_data)
|
||||
|
||||
|
||||
async def main():
|
||||
await agent.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,27 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
|
||||
# This uses a bigger model for the planning
|
||||
# And a smaller model for the page content extraction
|
||||
# THink of it like a subagent which only task is to extract content from the current page
|
||||
llm = ChatOpenAI(model='gpt-4.1')
|
||||
small_llm = ChatOpenAI(model='gpt-4.1-mini')
|
||||
task = 'Find the founders of browser-use in ycombinator, extract all links and open the links one by one'
|
||||
agent = Agent(task=task, llm=llm, page_extraction_llm=small_llm)
|
||||
|
||||
|
||||
async def main():
|
||||
await agent.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,43 @@
|
||||
import asyncio
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
|
||||
from browser_use.llm.google.chat import ChatGoogle
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent
|
||||
|
||||
llm = ChatGoogle(model='gemini-3-flash-preview', temperature=1.0)
|
||||
|
||||
|
||||
def check_is_task_stopped():
|
||||
async def _internal_check_is_task_stopped() -> bool:
|
||||
if random.random() < 0.1:
|
||||
print('[TASK STOPPER] Task is stopped')
|
||||
return True
|
||||
else:
|
||||
print('[TASK STOPPER] Task is not stopped')
|
||||
return False
|
||||
|
||||
return _internal_check_is_task_stopped
|
||||
|
||||
|
||||
task = """
|
||||
Go to https://browser-use.github.io/stress-tests/challenges/wufoo-style-form.html and complete the Wufoo-style form by filling in all required fields and submitting.
|
||||
"""
|
||||
|
||||
agent = Agent(task=task, llm=llm, flash_mode=True, register_should_stop_callback=check_is_task_stopped(), max_actions_per_step=1)
|
||||
|
||||
|
||||
async def main():
|
||||
await agent.run(max_steps=30)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,25 @@
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
from browser_use import Agent, Browser, ChatOpenAI
|
||||
|
||||
# NOTE: To use this example, install imageio[ffmpeg], e.g. with uv pip install "browser-use[video]"
|
||||
|
||||
|
||||
async def main():
|
||||
browser_session = Browser(record_video_dir=Path('./tmp/recordings'))
|
||||
|
||||
agent = Agent(
|
||||
task='Go to github.com/trending then navigate to the first trending repository and report how many commits it has.',
|
||||
llm=ChatOpenAI(model='gpt-4.1-mini'),
|
||||
browser_session=browser_session,
|
||||
)
|
||||
|
||||
await agent.run(max_steps=5)
|
||||
|
||||
# The video will be saved automatically when the agent finishes and the session closes.
|
||||
print('Agent run finished. Check the ./tmp/recordings directory for the video.')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user