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

This commit is contained in:
wehub-resource-sync
2026-07-13 12:02:32 +08:00
commit 4cd2d4af2b
475 changed files with 121829 additions and 0 deletions
+188
View File
@@ -0,0 +1,188 @@
"""
Cloud Example 1: Your First Browser Use Cloud Task
==================================================
This example demonstrates the most basic Browser Use Cloud functionality:
- Create a simple automation task
- Get the task ID
- Monitor completion
- Retrieve results
Perfect for first-time cloud users to understand the API basics.
Cost: ~$0.04 (1 task + 3 steps with GPT-4.1 mini)
"""
import os
import time
from typing import Any
import requests
from requests.exceptions import RequestException
# Configuration
API_KEY = os.getenv('BROWSER_USE_API_KEY')
if not API_KEY:
raise ValueError(
'Please set BROWSER_USE_API_KEY environment variable. You can also create an API key at https://cloud.browser-use.com/new-api-key'
)
BASE_URL = os.getenv('BROWSER_USE_BASE_URL', 'https://api.browser-use.com/api/v1')
TIMEOUT = int(os.getenv('BROWSER_USE_TIMEOUT', '30'))
HEADERS = {'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'}
def _request_with_retry(method: str, url: str, **kwargs) -> requests.Response:
"""Make HTTP request with timeout and retry logic."""
kwargs.setdefault('timeout', TIMEOUT)
for attempt in range(3):
try:
response = requests.request(method, url, **kwargs)
response.raise_for_status()
return response
except RequestException as e:
if attempt == 2: # Last attempt
raise
sleep_time = 2**attempt
print(f'⚠️ Request failed (attempt {attempt + 1}/3), retrying in {sleep_time}s: {e}')
time.sleep(sleep_time)
# This line should never be reached, but satisfies type checker
raise RuntimeError('Unexpected error in retry logic')
def create_task(instructions: str) -> str:
"""
Create a new browser automation task.
Args:
instructions: Natural language description of what the agent should do
Returns:
task_id: Unique identifier for the created task
"""
print(f'📝 Creating task: {instructions}')
payload = {
'task': instructions,
'llm_model': 'gpt-4.1-mini', # Cost-effective model
'max_agent_steps': 10, # Prevent runaway costs
'enable_public_share': True, # Enable shareable execution URLs
}
response = _request_with_retry('post', f'{BASE_URL}/run-task', headers=HEADERS, json=payload)
task_id = response.json()['id']
print(f'✅ Task created with ID: {task_id}')
return task_id
def get_task_status(task_id: str) -> dict[str, Any]:
"""Get the current status of a task."""
response = _request_with_retry('get', f'{BASE_URL}/task/{task_id}/status', headers=HEADERS)
return response.json()
def get_task_details(task_id: str) -> dict[str, Any]:
"""Get full task details including steps and output."""
response = _request_with_retry('get', f'{BASE_URL}/task/{task_id}', headers=HEADERS)
return response.json()
def wait_for_completion(task_id: str, poll_interval: int = 3) -> dict[str, Any]:
"""
Wait for task completion and show progress.
Args:
task_id: The task to monitor
poll_interval: How often to check status (seconds)
Returns:
Complete task details with output
"""
print(f'⏳ Monitoring task {task_id}...')
step_count = 0
start_time = time.time()
while True:
details = get_task_details(task_id)
status = details['status']
current_steps = len(details.get('steps', []))
elapsed = time.time() - start_time
# Clear line and show current progress
if current_steps > step_count:
step_count = current_steps
# Build status message
if status == 'running':
if current_steps > 0:
status_msg = f'🔄 Step {current_steps} | ⏱️ {elapsed:.0f}s | 🤖 Agent working...'
else:
status_msg = f'🤖 Agent starting... | ⏱️ {elapsed:.0f}s'
else:
status_msg = f'🔄 Step {current_steps} | ⏱️ {elapsed:.0f}s | Status: {status}'
# Clear line and print status
print(f'\r{status_msg:<80}', end='', flush=True)
# Check if finished
if status == 'finished':
print(f'\r✅ Task completed successfully! ({current_steps} steps in {elapsed:.1f}s)' + ' ' * 20)
return details
elif status in ['failed', 'stopped']:
print(f'\r❌ Task {status} after {current_steps} steps' + ' ' * 30)
return details
time.sleep(poll_interval)
def main():
"""Run a basic cloud automation task."""
print('🚀 Browser Use Cloud - Basic Task Example')
print('=' * 50)
# Define a simple search task (using DuckDuckGo to avoid captchas)
task_description = (
"Go to DuckDuckGo and search for 'browser automation tools'. Tell me the top 3 results with their titles and URLs."
)
try:
# Step 1: Create the task
task_id = create_task(task_description)
# Step 2: Wait for completion
result = wait_for_completion(task_id)
# Step 3: Display results
print('\n📊 Results:')
print('-' * 30)
print(f'Status: {result["status"]}')
print(f'Steps taken: {len(result.get("steps", []))}')
if result.get('output'):
print(f'Output: {result["output"]}')
else:
print('No output available')
# Show share URLs for viewing execution
if result.get('live_url'):
print(f'\n🔗 Live Preview: {result["live_url"]}')
if result.get('public_share_url'):
print(f'🌐 Share URL: {result["public_share_url"]}')
elif result.get('share_url'):
print(f'🌐 Share URL: {result["share_url"]}')
if not result.get('live_url') and not result.get('public_share_url') and not result.get('share_url'):
print("\n💡 Tip: Add 'enable_public_share': True to task payload to get shareable URLs")
except requests.exceptions.RequestException as e:
print(f'❌ API Error: {e}')
except Exception as e:
print(f'❌ Error: {e}')
if __name__ == '__main__':
main()
+265
View File
@@ -0,0 +1,265 @@
"""
Cloud Example 2: Ultra-Fast Mode with Gemini Flash ⚡
====================================================
This example demonstrates the fastest and most cost-effective configuration:
- Gemini 2.5 Flash model ($0.01 per step)
- No proxy (faster execution, but no captcha solving)
- No element highlighting (better performance)
- Optimized viewport size
- Maximum speed configuration
Perfect for: Quick content generation, humor tasks, fast web scraping
Cost: ~$0.03 (1 task + 2-3 steps with Gemini Flash)
Speed: 2-3x faster than default configuration
Fun Factor: 💯 (Creates hilarious tech commentary)
"""
import argparse
import os
import time
from typing import Any
import requests
from requests.exceptions import RequestException
# Configuration
API_KEY = os.getenv('BROWSER_USE_API_KEY')
if not API_KEY:
raise ValueError(
'Please set BROWSER_USE_API_KEY environment variable. You can also create an API key at https://cloud.browser-use.com/new-api-key'
)
BASE_URL = os.getenv('BROWSER_USE_BASE_URL', 'https://api.browser-use.com/api/v1')
TIMEOUT = int(os.getenv('BROWSER_USE_TIMEOUT', '30'))
HEADERS = {'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'}
def _request_with_retry(method: str, url: str, **kwargs) -> requests.Response:
"""Make HTTP request with timeout and retry logic."""
kwargs.setdefault('timeout', TIMEOUT)
for attempt in range(3):
try:
response = requests.request(method, url, **kwargs)
response.raise_for_status()
return response
except RequestException as e:
if attempt == 2: # Last attempt
raise
sleep_time = 2**attempt
print(f'⚠️ Request failed (attempt {attempt + 1}/3), retrying in {sleep_time}s: {e}')
time.sleep(sleep_time)
raise RuntimeError('Unexpected error in retry logic')
def create_fast_task(instructions: str) -> str:
"""
Create a browser automation task optimized for speed and cost.
Args:
instructions: Natural language description of what the agent should do
Returns:
task_id: Unique identifier for the created task
"""
print(f'⚡ Creating FAST task: {instructions}')
# Ultra-fast configuration
payload = {
'task': instructions,
# Model: Fastest and cheapest
'llm_model': 'gemini-2.5-flash',
# Performance optimizations
'use_proxy': False, # No proxy = faster execution
'highlight_elements': False, # No highlighting = better performance
'use_adblock': True, # Block ads for faster loading
# Viewport optimization (smaller = faster)
'browser_viewport_width': 1024,
'browser_viewport_height': 768,
# Cost control
'max_agent_steps': 25, # Reasonable limit for fast tasks
# Enable sharing for viewing execution
'enable_public_share': True, # Get shareable URLs
# Optional: Speed up with domain restrictions
# "allowed_domains": ["google.com", "*.google.com"]
}
response = _request_with_retry('post', f'{BASE_URL}/run-task', headers=HEADERS, json=payload)
task_id = response.json()['id']
print(f'✅ Fast task created with ID: {task_id}')
print('⚡ Configuration: Gemini Flash + No Proxy + No Highlighting')
return task_id
def monitor_fast_task(task_id: str) -> dict[str, Any]:
"""
Monitor task with optimized polling for fast execution.
Args:
task_id: The task to monitor
Returns:
Complete task details with output
"""
print(f'🚀 Fast monitoring task {task_id}...')
start_time = time.time()
step_count = 0
last_step_time = start_time
# Faster polling for quick tasks
poll_interval = 1 # Check every second for fast tasks
while True:
response = _request_with_retry('get', f'{BASE_URL}/task/{task_id}', headers=HEADERS)
details = response.json()
status = details['status']
# Show progress with timing
current_steps = len(details.get('steps', []))
elapsed = time.time() - start_time
# Build status message
if current_steps > step_count:
step_time = time.time() - last_step_time
last_step_time = time.time()
step_count = current_steps
step_msg = f'🔥 Step {current_steps} | ⚡ {step_time:.1f}s | Total: {elapsed:.1f}s'
else:
if status == 'running':
step_msg = f'🚀 Step {current_steps} | ⏱️ {elapsed:.1f}s | Fast processing...'
else:
step_msg = f'🚀 Step {current_steps} | ⏱️ {elapsed:.1f}s | Status: {status}'
# Clear line and show progress
print(f'\r{step_msg:<80}', end='', flush=True)
# Check completion
if status == 'finished':
total_time = time.time() - start_time
if current_steps > 0:
avg_msg = f'⚡ Average: {total_time / current_steps:.1f}s per step'
else:
avg_msg = '⚡ No steps recorded'
print(f'\r🏁 Task completed in {total_time:.1f}s! {avg_msg}' + ' ' * 20)
return details
elif status in ['failed', 'stopped']:
print(f'\r❌ Task {status} after {elapsed:.1f}s' + ' ' * 30)
return details
time.sleep(poll_interval)
def run_speed_comparison():
"""Run multiple tasks to compare speed vs accuracy."""
print('\n🏃‍♂️ Speed Comparison Demo')
print('=' * 40)
tasks = [
'Go to ProductHunt and roast the top product like a sarcastic tech reviewer',
'Visit Reddit r/ProgrammerHumor and summarize the top post as a dramatic news story',
"Check GitHub trending and write a conspiracy theory about why everyone's switching to Rust",
]
results = []
for i, task in enumerate(tasks, 1):
print(f'\n📝 Fast Task {i}/{len(tasks)}')
print(f'Task: {task}')
start = time.time()
task_id = create_fast_task(task)
result = monitor_fast_task(task_id)
end = time.time()
results.append(
{
'task': task,
'duration': end - start,
'steps': len(result.get('steps', [])),
'status': result['status'],
'output': result.get('output', '')[:100] + '...' if result.get('output') else 'No output',
}
)
# Summary
print('\n📊 Speed Summary')
print('=' * 50)
total_time = sum(r['duration'] for r in results)
total_steps = sum(r['steps'] for r in results)
for i, result in enumerate(results, 1):
print(f'Task {i}: {result["duration"]:.1f}s ({result["steps"]} steps) - {result["status"]}')
print(f'\n⚡ Total time: {total_time:.1f}s')
print(f'🔥 Average per task: {total_time / len(results):.1f}s')
if total_steps > 0:
print(f'💨 Average per step: {total_time / total_steps:.1f}s')
else:
print('💨 Average per step: N/A (no steps recorded)')
def main():
"""Demonstrate ultra-fast cloud automation."""
print('⚡ Browser Use Cloud - Ultra-Fast Mode with Gemini Flash')
print('=' * 60)
print('🎯 Configuration Benefits:')
print('• Gemini Flash: $0.01 per step (cheapest)')
print('• No proxy: 30% faster execution')
print('• No highlighting: Better performance')
print('• Optimized viewport: Faster rendering')
try:
# Single fast task
print('\n🚀 Single Fast Task Demo')
print('-' * 30)
task = """
Go to Hacker News (news.ycombinator.com) and get the top 3 articles from the front page.
Then, write a funny tech news segment in the style of Fireship YouTube channel:
- Be sarcastic and witty about tech trends
- Use developer humor and memes
- Make fun of common programming struggles
- Include phrases like "And yes, it runs on JavaScript" or "Plot twist: it's written in Rust"
- Keep it under 250 words but make it entertaining
- Structure it like a news anchor delivering breaking tech news
Make each story sound dramatic but also hilarious, like you're reporting on the most important events in human history.
"""
task_id = create_fast_task(task)
result = monitor_fast_task(task_id)
print(f'\n📊 Result: {result.get("output", "No output")}')
# Show execution URLs
if result.get('live_url'):
print(f'\n🔗 Live Preview: {result["live_url"]}')
if result.get('public_share_url'):
print(f'🌐 Share URL: {result["public_share_url"]}')
elif result.get('share_url'):
print(f'🌐 Share URL: {result["share_url"]}')
# Optional: Run speed comparison with --compare flag
parser = argparse.ArgumentParser(description='Fast mode demo with Gemini Flash')
parser.add_argument('--compare', action='store_true', help='Run speed comparison with 3 tasks')
args = parser.parse_args()
if args.compare:
print('\n🏃‍♂️ Running speed comparison...')
run_speed_comparison()
except requests.exceptions.RequestException as e:
print(f'❌ API Error: {e}')
except Exception as e:
print(f'❌ Error: {e}')
if __name__ == '__main__':
main()
+362
View File
@@ -0,0 +1,362 @@
"""
Cloud Example 3: Structured JSON Output 📋
==========================================
This example demonstrates how to get structured, validated JSON output:
- Define Pydantic schemas for type safety
- Extract structured data from websites
- Validate and parse JSON responses
- Handle different data types and nested structures
Perfect for: Data extraction, API integration, structured analysis
Cost: ~$0.06 (1 task + 5-6 steps with GPT-4.1 mini)
"""
import argparse
import json
import os
import time
from typing import Any
import requests
from pydantic import BaseModel, Field, ValidationError
from requests.exceptions import RequestException
# Configuration
API_KEY = os.getenv('BROWSER_USE_API_KEY')
if not API_KEY:
raise ValueError(
'Please set BROWSER_USE_API_KEY environment variable. You can also create an API key at https://cloud.browser-use.com/new-api-key'
)
BASE_URL = os.getenv('BROWSER_USE_BASE_URL', 'https://api.browser-use.com/api/v1')
TIMEOUT = int(os.getenv('BROWSER_USE_TIMEOUT', '30'))
HEADERS = {'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'}
def _request_with_retry(method: str, url: str, **kwargs) -> requests.Response:
"""Make HTTP request with timeout and retry logic."""
kwargs.setdefault('timeout', TIMEOUT)
for attempt in range(3):
try:
response = requests.request(method, url, **kwargs)
response.raise_for_status()
return response
except RequestException as e:
if attempt == 2: # Last attempt
raise
sleep_time = 2**attempt
print(f'⚠️ Request failed (attempt {attempt + 1}/3), retrying in {sleep_time}s: {e}')
time.sleep(sleep_time)
raise RuntimeError('Unexpected error in retry logic')
# Define structured output schemas using Pydantic
class NewsArticle(BaseModel):
"""Schema for a news article."""
title: str = Field(description='The headline of the article')
summary: str = Field(description='Brief summary of the article')
url: str = Field(description='Direct link to the article')
published_date: str | None = Field(description='Publication date if available')
category: str | None = Field(description='Article category/section')
class NewsResponse(BaseModel):
"""Schema for multiple news articles."""
articles: list[NewsArticle] = Field(description='List of news articles')
source_website: str = Field(description='The website where articles were found')
extracted_at: str = Field(description='When the data was extracted')
class ProductInfo(BaseModel):
"""Schema for product information."""
name: str = Field(description='Product name')
price: float = Field(description='Product price in USD')
rating: float | None = Field(description='Average rating (0-5 scale)')
availability: str = Field(description='Stock status (in stock, out of stock, etc.)')
description: str = Field(description='Product description')
class CompanyInfo(BaseModel):
"""Schema for company information."""
name: str = Field(description='Company name')
stock_symbol: str | None = Field(description='Stock ticker symbol')
market_cap: str | None = Field(description='Market capitalization')
industry: str = Field(description='Primary industry')
headquarters: str = Field(description='Headquarters location')
founded_year: int | None = Field(description='Year founded')
def create_structured_task(instructions: str, schema_model: type[BaseModel], **kwargs) -> str:
"""
Create a task that returns structured JSON output.
Args:
instructions: Task description
schema_model: Pydantic model defining the expected output structure
**kwargs: Additional task parameters
Returns:
task_id: Unique identifier for the created task
"""
print(f'📝 Creating structured task: {instructions}')
print(f'🏗️ Expected schema: {schema_model.__name__}')
# Generate JSON schema from Pydantic model
json_schema = schema_model.model_json_schema()
payload = {
'task': instructions,
'structured_output_json': json.dumps(json_schema),
'llm_model': 'gpt-4.1-mini',
'max_agent_steps': 15,
'enable_public_share': True, # Enable shareable execution URLs
**kwargs,
}
response = _request_with_retry('post', f'{BASE_URL}/run-task', headers=HEADERS, json=payload)
task_id = response.json()['id']
print(f'✅ Structured task created: {task_id}')
return task_id
def wait_for_structured_completion(task_id: str, max_wait_time: int = 300) -> dict[str, Any]:
"""Wait for task completion and return the result."""
print(f'⏳ Waiting for structured output (max {max_wait_time}s)...')
start_time = time.time()
while True:
response = _request_with_retry('get', f'{BASE_URL}/task/{task_id}/status', headers=HEADERS)
status = response.json()
elapsed = time.time() - start_time
# Check for timeout
if elapsed > max_wait_time:
print(f'\r⏰ Task timeout after {max_wait_time}s - stopping wait' + ' ' * 30)
# Get final details before timeout
details_response = _request_with_retry('get', f'{BASE_URL}/task/{task_id}', headers=HEADERS)
details = details_response.json()
return details
# Get step count from full details for better progress tracking
details_response = _request_with_retry('get', f'{BASE_URL}/task/{task_id}', headers=HEADERS)
details = details_response.json()
steps = len(details.get('steps', []))
# Build status message
if status == 'running':
status_msg = f'📋 Structured task | Step {steps} | ⏱️ {elapsed:.0f}s | 🔄 Extracting...'
else:
status_msg = f'📋 Structured task | Step {steps} | ⏱️ {elapsed:.0f}s | Status: {status}'
# Clear line and show status
print(f'\r{status_msg:<80}', end='', flush=True)
if status == 'finished':
print(f'\r✅ Structured data extracted! ({steps} steps in {elapsed:.1f}s)' + ' ' * 20)
return details
elif status in ['failed', 'stopped']:
print(f'\r❌ Task {status} after {steps} steps' + ' ' * 30)
return details
time.sleep(3)
def validate_and_display_output(output: str, schema_model: type[BaseModel]):
"""
Validate the JSON output against the schema and display results.
Args:
output: Raw JSON string from the task
schema_model: Pydantic model for validation
"""
print('\n📊 Structured Output Analysis')
print('=' * 40)
try:
# Parse and validate the JSON
parsed_data = schema_model.model_validate_json(output)
print('✅ JSON validation successful!')
# Pretty print the structured data
print('\n📋 Parsed Data:')
print('-' * 20)
print(parsed_data.model_dump_json(indent=2))
# Display specific fields based on model type
if isinstance(parsed_data, NewsResponse):
print(f'\n📰 Found {len(parsed_data.articles)} articles from {parsed_data.source_website}')
for i, article in enumerate(parsed_data.articles[:3], 1):
print(f'\n{i}. {article.title}')
print(f' Summary: {article.summary[:100]}...')
print(f' URL: {article.url}')
elif isinstance(parsed_data, ProductInfo):
print(f'\n🛍️ Product: {parsed_data.name}')
print(f' Price: ${parsed_data.price}')
print(f' Rating: {parsed_data.rating}/5' if parsed_data.rating else ' Rating: N/A')
print(f' Status: {parsed_data.availability}')
elif isinstance(parsed_data, CompanyInfo):
print(f'\n🏢 Company: {parsed_data.name}')
print(f' Industry: {parsed_data.industry}')
print(f' Headquarters: {parsed_data.headquarters}')
if parsed_data.founded_year:
print(f' Founded: {parsed_data.founded_year}')
return parsed_data
except ValidationError as e:
print('❌ JSON validation failed!')
print(f'Errors: {e}')
print(f'\nRaw output: {output[:500]}...')
return None
except json.JSONDecodeError as e:
print('❌ Invalid JSON format!')
print(f'Error: {e}')
print(f'\nRaw output: {output[:500]}...')
return None
def demo_news_extraction():
"""Demo: Extract structured news data."""
print('\n📰 Demo 1: News Article Extraction')
print('-' * 40)
task = """
Go to a major news website (like BBC, CNN, or Reuters) and extract information
about the top 3 news articles. For each article, get the title, summary, URL,
and any other available metadata.
"""
task_id = create_structured_task(task, NewsResponse)
result = wait_for_structured_completion(task_id)
if result.get('output'):
parsed_result = validate_and_display_output(result['output'], NewsResponse)
# Show execution URLs
if result.get('live_url'):
print(f'\n🔗 Live Preview: {result["live_url"]}')
if result.get('public_share_url'):
print(f'🌐 Share URL: {result["public_share_url"]}')
elif result.get('share_url'):
print(f'🌐 Share URL: {result["share_url"]}')
return parsed_result
else:
print('❌ No structured output received')
return None
def demo_product_extraction():
"""Demo: Extract structured product data."""
print('\n🛍️ Demo 2: Product Information Extraction')
print('-' * 40)
task = """
Go to Amazon and search for 'wireless headphones'. Find the first product result
and extract detailed information including name, price, rating, availability,
and description.
"""
task_id = create_structured_task(task, ProductInfo)
result = wait_for_structured_completion(task_id)
if result.get('output'):
parsed_result = validate_and_display_output(result['output'], ProductInfo)
# Show execution URLs
if result.get('live_url'):
print(f'\n🔗 Live Preview: {result["live_url"]}')
if result.get('public_share_url'):
print(f'🌐 Share URL: {result["public_share_url"]}')
elif result.get('share_url'):
print(f'🌐 Share URL: {result["share_url"]}')
return parsed_result
else:
print('❌ No structured output received')
return None
def demo_company_extraction():
"""Demo: Extract structured company data."""
print('\n🏢 Demo 3: Company Information Extraction')
print('-' * 40)
task = """
Go to a financial website and look up information about Apple Inc.
Extract company details including name, stock symbol, market cap,
industry, headquarters, and founding year.
"""
task_id = create_structured_task(task, CompanyInfo)
result = wait_for_structured_completion(task_id)
if result.get('output'):
parsed_result = validate_and_display_output(result['output'], CompanyInfo)
# Show execution URLs
if result.get('live_url'):
print(f'\n🔗 Live Preview: {result["live_url"]}')
if result.get('public_share_url'):
print(f'🌐 Share URL: {result["public_share_url"]}')
elif result.get('share_url'):
print(f'🌐 Share URL: {result["share_url"]}')
return parsed_result
else:
print('❌ No structured output received')
return None
def main():
"""Demonstrate structured output extraction."""
print('📋 Browser Use Cloud - Structured JSON Output')
print('=' * 50)
print('🎯 Features:')
print('• Type-safe Pydantic schemas')
print('• Automatic JSON validation')
print('• Structured data extraction')
print('• Multiple output formats')
try:
# Parse command line arguments
parser = argparse.ArgumentParser(description='Structured output extraction demo')
parser.add_argument('--demo', choices=['news', 'product', 'company', 'all'], default='news', help='Which demo to run')
args = parser.parse_args()
print(f'\n🔍 Running {args.demo} demo(s)...')
if args.demo == 'news':
demo_news_extraction()
elif args.demo == 'product':
demo_product_extraction()
elif args.demo == 'company':
demo_company_extraction()
elif args.demo == 'all':
demo_news_extraction()
demo_product_extraction()
demo_company_extraction()
except requests.exceptions.RequestException as e:
print(f'❌ API Error: {e}')
except Exception as e:
print(f'❌ Error: {e}')
if __name__ == '__main__':
main()
+331
View File
@@ -0,0 +1,331 @@
"""
Cloud Example 4: Proxy Usage 🌍
===============================
This example demonstrates reliable proxy usage scenarios:
- Different country proxies for geo-restrictions
- IP address and location verification
- Region-specific content access (streaming, news)
- Search result localization by country
- Mobile/residential proxy benefits
Perfect for: Geo-restricted content, location testing, regional analysis
Cost: ~$0.08 (1 task + 6-8 steps with proxy enabled)
"""
import argparse
import os
import time
from typing import Any
import requests
from requests.exceptions import RequestException
# Configuration
API_KEY = os.getenv('BROWSER_USE_API_KEY')
if not API_KEY:
raise ValueError(
'Please set BROWSER_USE_API_KEY environment variable. You can also create an API key at https://cloud.browser-use.com/new-api-key'
)
BASE_URL = os.getenv('BROWSER_USE_BASE_URL', 'https://api.browser-use.com/api/v1')
TIMEOUT = int(os.getenv('BROWSER_USE_TIMEOUT', '30'))
HEADERS = {'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'}
def _request_with_retry(method: str, url: str, **kwargs) -> requests.Response:
"""Make HTTP request with timeout and retry logic."""
kwargs.setdefault('timeout', TIMEOUT)
for attempt in range(3):
try:
response = requests.request(method, url, **kwargs)
response.raise_for_status()
return response
except RequestException as e:
if attempt == 2: # Last attempt
raise
sleep_time = 2**attempt
print(f'⚠️ Request failed (attempt {attempt + 1}/3), retrying in {sleep_time}s: {e}')
time.sleep(sleep_time)
raise RuntimeError('Unexpected error in retry logic')
def create_task_with_proxy(instructions: str, country_code: str = 'us') -> str:
"""
Create a task with proxy enabled from a specific country.
Args:
instructions: Task description
country_code: Proxy country ('us', 'fr', 'it', 'jp', 'au', 'de', 'fi', 'ca')
Returns:
task_id: Unique identifier for the created task
"""
print(f'🌍 Creating task with {country_code.upper()} proxy')
print(f'📝 Task: {instructions}')
payload = {
'task': instructions,
'llm_model': 'gpt-4.1-mini',
# Proxy configuration
'use_proxy': True, # Required for captcha solving
'proxy_country_code': country_code, # Choose proxy location
# Standard settings
'use_adblock': True, # Block ads for faster loading
'highlight_elements': True, # Keep highlighting for visibility
'max_agent_steps': 15,
# Enable sharing for viewing execution
'enable_public_share': True, # Get shareable URLs
}
response = _request_with_retry('post', f'{BASE_URL}/run-task', headers=HEADERS, json=payload)
task_id = response.json()['id']
print(f'✅ Task created with {country_code.upper()} proxy: {task_id}')
return task_id
def test_ip_location(country_code: str) -> dict[str, Any]:
"""Test IP address and location detection with proxy."""
task = """
Go to whatismyipaddress.com and tell me:
1. The detected IP address
2. The detected country/location
3. The ISP/organization
4. Any other location details shown
Please be specific about what you see on the page.
"""
task_id = create_task_with_proxy(task, country_code)
return wait_for_completion(task_id)
def test_geo_restricted_content(country_code: str) -> dict[str, Any]:
"""Test access to geo-restricted content."""
task = """
Go to a major news website (like BBC, CNN, or local news) and check:
1. What content is available
2. Any geo-restriction messages
3. Local/regional content differences
4. Language or currency preferences shown
Note any differences from what you might expect.
"""
task_id = create_task_with_proxy(task, country_code)
return wait_for_completion(task_id)
def test_streaming_service_access(country_code: str) -> dict[str, Any]:
"""Test access to region-specific streaming content."""
task = """
Go to a major streaming service website (like Netflix, YouTube, or BBC iPlayer)
and check what content or messaging appears.
Report:
1. What homepage content is shown
2. Any geo-restriction messages or content differences
3. Available content regions or language options
4. Any pricing or availability differences
Note: Don't try to log in, just observe the publicly available content.
"""
task_id = create_task_with_proxy(task, country_code)
return wait_for_completion(task_id)
def test_search_results_by_location(country_code: str) -> dict[str, Any]:
"""Test how search results vary by location."""
task = """
Go to Google and search for "best restaurants near me" or "local news".
Report:
1. What local results appear
2. The detected location in search results
3. Any location-specific content or ads
4. Language preferences
This will show how search results change based on proxy location.
"""
task_id = create_task_with_proxy(task, country_code)
return wait_for_completion(task_id)
def wait_for_completion(task_id: str) -> dict[str, Any]:
"""Wait for task completion and return results."""
print(f'⏳ Waiting for task {task_id} to complete...')
start_time = time.time()
while True:
response = _request_with_retry('get', f'{BASE_URL}/task/{task_id}', headers=HEADERS)
details = response.json()
status = details['status']
steps = len(details.get('steps', []))
elapsed = time.time() - start_time
# Build status message
if status == 'running':
status_msg = f'🌍 Proxy task | Step {steps} | ⏱️ {elapsed:.0f}s | 🤖 Processing...'
else:
status_msg = f'🌍 Proxy task | Step {steps} | ⏱️ {elapsed:.0f}s | Status: {status}'
# Clear line and show status
print(f'\r{status_msg:<80}', end='', flush=True)
if status == 'finished':
print(f'\r✅ Task completed in {steps} steps! ({elapsed:.1f}s total)' + ' ' * 20)
return details
elif status in ['failed', 'stopped']:
print(f'\r❌ Task {status} after {steps} steps' + ' ' * 30)
return details
time.sleep(3)
def demo_proxy_countries():
"""Demonstrate proxy usage across different countries."""
print('\n🌍 Demo 1: Proxy Countries Comparison')
print('-' * 45)
countries = [('us', 'United States'), ('de', 'Germany'), ('jp', 'Japan'), ('au', 'Australia')]
results = {}
for code, name in countries:
print(f'\n🌍 Testing {name} ({code.upper()}) proxy:')
print('=' * 40)
result = test_ip_location(code)
results[code] = result
if result.get('output'):
print(f'📍 Location Result: {result["output"][:200]}...')
# Show execution URLs
if result.get('live_url'):
print(f'🔗 Live Preview: {result["live_url"]}')
if result.get('public_share_url'):
print(f'🌐 Share URL: {result["public_share_url"]}')
elif result.get('share_url'):
print(f'🌐 Share URL: {result["share_url"]}')
print('-' * 40)
time.sleep(2) # Brief pause between tests
# Summary comparison
print('\n📊 Proxy Location Summary:')
print('=' * 30)
for code, result in results.items():
status = result.get('status', 'unknown')
print(f'{code.upper()}: {status}')
def demo_geo_restrictions():
"""Demonstrate geo-restriction bypass."""
print('\n🚫 Demo 2: Geo-Restriction Testing')
print('-' * 40)
# Test from different locations
locations = [('us', 'US content'), ('de', 'European content')]
for code, description in locations:
print(f'\n🌍 Testing {description} with {code.upper()} proxy:')
result = test_geo_restricted_content(code)
if result.get('output'):
print(f'📰 Content Access: {result["output"][:200]}...')
time.sleep(2)
def demo_streaming_access():
"""Demonstrate streaming service access with different proxies."""
print('\n📺 Demo 3: Streaming Service Access')
print('-' * 40)
locations = [('us', 'US'), ('de', 'Germany')]
for code, name in locations:
print(f'\n🌍 Testing streaming access from {name}:')
result = test_streaming_service_access(code)
if result.get('output'):
print(f'📺 Access Result: {result["output"][:200]}...')
time.sleep(2)
def demo_search_localization():
"""Demonstrate search result localization."""
print('\n🔍 Demo 4: Search Localization')
print('-' * 35)
locations = [('us', 'US'), ('de', 'Germany')]
for code, name in locations:
print(f'\n🌍 Testing search results from {name}:')
result = test_search_results_by_location(code)
if result.get('output'):
print(f'🔍 Search Results: {result["output"][:200]}...')
time.sleep(2)
def main():
"""Demonstrate comprehensive proxy usage."""
print('🌍 Browser Use Cloud - Proxy Usage Examples')
print('=' * 50)
print('🎯 Proxy Benefits:')
print('• Bypass geo-restrictions')
print('• Test location-specific content')
print('• Access region-locked websites')
print('• Mobile/residential IP addresses')
print('• Verify IP geolocation')
print('\n🌐 Available Countries:')
countries = ['🇺🇸 US', '🇫🇷 France', '🇮🇹 Italy', '🇯🇵 Japan', '🇦🇺 Australia', '🇩🇪 Germany', '🇫🇮 Finland', '🇨🇦 Canada']
print(''.join(countries))
try:
# Parse command line arguments
parser = argparse.ArgumentParser(description='Proxy usage examples')
parser.add_argument(
'--demo', choices=['countries', 'geo', 'streaming', 'search', 'all'], default='countries', help='Which demo to run'
)
args = parser.parse_args()
print(f'\n🔍 Running {args.demo} demo(s)...')
if args.demo == 'countries':
demo_proxy_countries()
elif args.demo == 'geo':
demo_geo_restrictions()
elif args.demo == 'streaming':
demo_streaming_access()
elif args.demo == 'search':
demo_search_localization()
elif args.demo == 'all':
demo_proxy_countries()
demo_geo_restrictions()
demo_streaming_access()
demo_search_localization()
except requests.exceptions.RequestException as e:
print(f'❌ API Error: {e}')
except Exception as e:
print(f'❌ Error: {e}')
if __name__ == '__main__':
main()
+355
View File
@@ -0,0 +1,355 @@
"""
Cloud Example 5: Search API (Beta) 🔍
=====================================
This example demonstrates the Browser Use Search API (BETA):
- Simple search: Search Google and extract from multiple results
- URL search: Extract specific content from a target URL
- Deep navigation through websites (depth parameter)
- Real-time content extraction vs cached results
Perfect for: Content extraction, research, competitive analysis
"""
import argparse
import asyncio
import json
import os
import time
from typing import Any
import aiohttp
# Configuration
API_KEY = os.getenv('BROWSER_USE_API_KEY')
if not API_KEY:
raise ValueError(
'Please set BROWSER_USE_API_KEY environment variable. You can also create an API key at https://cloud.browser-use.com/new-api-key'
)
BASE_URL = os.getenv('BROWSER_USE_BASE_URL', 'https://api.browser-use.com/api/v1')
TIMEOUT = int(os.getenv('BROWSER_USE_TIMEOUT', '30'))
HEADERS = {'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'}
async def simple_search(query: str, max_websites: int = 5, depth: int = 2) -> dict[str, Any]:
"""
Search Google and extract content from multiple top results.
Args:
query: Search query to process
max_websites: Number of websites to process (1-10)
depth: How deep to navigate (2-5)
Returns:
Dictionary with results from multiple websites
"""
# Validate input parameters
max_websites = max(1, min(max_websites, 10)) # Clamp to 1-10
depth = max(2, min(depth, 5)) # Clamp to 2-5
start_time = time.time()
print(f"🔍 Simple Search: '{query}'")
print(f'📊 Processing {max_websites} websites at depth {depth}')
print(f'💰 Estimated cost: {depth * max_websites}¢')
payload = {'query': query, 'max_websites': max_websites, 'depth': depth}
timeout = aiohttp.ClientTimeout(total=TIMEOUT)
connector = aiohttp.TCPConnector(limit=10) # Limit concurrent connections
async with aiohttp.ClientSession(timeout=timeout, connector=connector) as session:
async with session.post(f'{BASE_URL}/simple-search', json=payload, headers=HEADERS) as response:
elapsed = time.time() - start_time
if response.status == 200:
try:
result = await response.json()
print(f'✅ Found results from {len(result.get("results", []))} websites in {elapsed:.1f}s')
return result
except (aiohttp.ContentTypeError, json.JSONDecodeError) as e:
error_text = await response.text()
print(f'❌ Invalid JSON response: {e} (after {elapsed:.1f}s)')
return {'error': 'Invalid JSON', 'details': error_text}
else:
error_text = await response.text()
print(f'❌ Search failed: {response.status} - {error_text} (after {elapsed:.1f}s)')
return {'error': f'HTTP {response.status}', 'details': error_text}
async def search_url(url: str, query: str, depth: int = 2) -> dict[str, Any]:
"""
Extract specific content from a target URL.
Args:
url: Target URL to extract from
query: What specific content to look for
depth: How deep to navigate (2-5)
Returns:
Dictionary with extracted content
"""
# Validate input parameters
depth = max(2, min(depth, 5)) # Clamp to 2-5
start_time = time.time()
print(f'🎯 URL Search: {url}')
print(f"🔍 Looking for: '{query}'")
print(f'📊 Navigation depth: {depth}')
print(f'💰 Estimated cost: {depth}¢')
payload = {'url': url, 'query': query, 'depth': depth}
timeout = aiohttp.ClientTimeout(total=TIMEOUT)
connector = aiohttp.TCPConnector(limit=10) # Limit concurrent connections
async with aiohttp.ClientSession(timeout=timeout, connector=connector) as session:
async with session.post(f'{BASE_URL}/search-url', json=payload, headers=HEADERS) as response:
elapsed = time.time() - start_time
if response.status == 200:
try:
result = await response.json()
print(f'✅ Extracted content from {result.get("url", "website")} in {elapsed:.1f}s')
return result
except (aiohttp.ContentTypeError, json.JSONDecodeError) as e:
error_text = await response.text()
print(f'❌ Invalid JSON response: {e} (after {elapsed:.1f}s)')
return {'error': 'Invalid JSON', 'details': error_text}
else:
error_text = await response.text()
print(f'❌ URL search failed: {response.status} - {error_text} (after {elapsed:.1f}s)')
return {'error': f'HTTP {response.status}', 'details': error_text}
def display_simple_search_results(results: dict[str, Any]):
"""Display simple search results in a readable format."""
if 'error' in results:
print(f'❌ Error: {results["error"]}')
return
websites = results.get('results', [])
print(f'\n📋 Search Results ({len(websites)} websites)')
print('=' * 50)
for i, site in enumerate(websites, 1):
url = site.get('url', 'Unknown URL')
content = site.get('content', 'No content')
print(f'\n{i}. 🌐 {url}')
print('-' * 40)
# Show first 300 chars of content
if len(content) > 300:
print(f'{content[:300]}...')
print(f'[Content truncated - {len(content)} total characters]')
else:
print(content)
# Show execution URLs if available
if results.get('live_url'):
print(f'\n🔗 Live Preview: {results["live_url"]}')
if results.get('public_share_url'):
print(f'🌐 Share URL: {results["public_share_url"]}')
elif results.get('share_url'):
print(f'🌐 Share URL: {results["share_url"]}')
def display_url_search_results(results: dict[str, Any]):
"""Display URL search results in a readable format."""
if 'error' in results:
print(f'❌ Error: {results["error"]}')
return
url = results.get('url', 'Unknown URL')
content = results.get('content', 'No content')
print(f'\n📄 Extracted Content from: {url}')
print('=' * 60)
print(content)
# Show execution URLs if available
if results.get('live_url'):
print(f'\n🔗 Live Preview: {results["live_url"]}')
if results.get('public_share_url'):
print(f'🌐 Share URL: {results["public_share_url"]}')
elif results.get('share_url'):
print(f'🌐 Share URL: {results["share_url"]}')
async def demo_news_search():
"""Demo: Search for latest news across multiple sources."""
print('\n📰 Demo 1: Latest News Search')
print('-' * 35)
demo_start = time.time()
query = 'latest developments in artificial intelligence 2024'
results = await simple_search(query, max_websites=4, depth=2)
demo_elapsed = time.time() - demo_start
display_simple_search_results(results)
print(f'\n⏱️ Total demo time: {demo_elapsed:.1f}s')
return results
async def demo_competitive_analysis():
"""Demo: Analyze competitor websites."""
print('\n🏢 Demo 2: Competitive Analysis')
print('-' * 35)
query = 'browser automation tools comparison features pricing'
results = await simple_search(query, max_websites=3, depth=3)
display_simple_search_results(results)
return results
async def demo_deep_website_analysis():
"""Demo: Deep analysis of a specific website."""
print('\n🎯 Demo 3: Deep Website Analysis')
print('-' * 35)
demo_start = time.time()
url = 'https://docs.browser-use.com'
query = 'Browser Use features, pricing, and API capabilities'
results = await search_url(url, query, depth=3)
demo_elapsed = time.time() - demo_start
display_url_search_results(results)
print(f'\n⏱️ Total demo time: {demo_elapsed:.1f}s')
return results
async def demo_product_research():
"""Demo: Product research and comparison."""
print('\n🛍️ Demo 4: Product Research')
print('-' * 30)
query = 'best wireless headphones 2024 reviews comparison'
results = await simple_search(query, max_websites=5, depth=2)
display_simple_search_results(results)
return results
async def demo_real_time_vs_cached():
"""Demo: Show difference between real-time and cached results."""
print('\n⚡ Demo 5: Real-time vs Cached Data')
print('-' * 40)
print('🔄 Browser Use Search API benefits:')
print('• Actually browses websites like a human')
print('• Gets live, current data (not cached)')
print('• Navigates deep into sites via clicks')
print('• Handles JavaScript and dynamic content')
print('• Accesses pages requiring navigation')
# Example with live data
query = 'current Bitcoin price USD live'
results = await simple_search(query, max_websites=3, depth=2)
print('\n💰 Live Bitcoin Price Search Results:')
display_simple_search_results(results)
return results
async def demo_search_depth_comparison():
"""Demo: Compare different search depths."""
print('\n📊 Demo 6: Search Depth Comparison')
print('-' * 40)
url = 'https://news.ycombinator.com'
query = 'trending technology discussions'
depths = [2, 3, 4]
results = {}
for depth in depths:
print(f'\n🔍 Testing depth {depth}:')
result = await search_url(url, query, depth)
results[depth] = result
if 'content' in result:
content_length = len(result['content'])
print(f'📏 Content length: {content_length} characters')
# Brief pause between requests
await asyncio.sleep(1)
# Summary
print('\n📊 Depth Comparison Summary:')
print('-' * 30)
for depth, result in results.items():
if 'content' in result:
length = len(result['content'])
print(f'Depth {depth}: {length} characters')
else:
print(f'Depth {depth}: Error or no content')
return results
async def main():
"""Demonstrate comprehensive Search API usage."""
print('🔍 Browser Use Cloud - Search API (BETA)')
print('=' * 45)
print('⚠️ Note: This API is in BETA and may change')
print()
print('🎯 Search API Features:')
print('• Real-time website browsing (not cached)')
print('• Deep navigation through multiple pages')
print('• Dynamic content and JavaScript handling')
print('• Multiple result aggregation')
print('• Cost-effective content extraction')
print('\n💰 Pricing:')
print('• Simple Search: 1¢ × depth × websites')
print('• URL Search: 1¢ × depth')
print('• Example: depth=2, 5 websites = 10¢')
try:
# Parse command line arguments
parser = argparse.ArgumentParser(description='Search API (BETA) examples')
parser.add_argument(
'--demo',
choices=['news', 'competitive', 'deep', 'product', 'realtime', 'depth', 'all'],
default='news',
help='Which demo to run',
)
args = parser.parse_args()
print(f'\n🔍 Running {args.demo} demo(s)...')
if args.demo == 'news':
await demo_news_search()
elif args.demo == 'competitive':
await demo_competitive_analysis()
elif args.demo == 'deep':
await demo_deep_website_analysis()
elif args.demo == 'product':
await demo_product_research()
elif args.demo == 'realtime':
await demo_real_time_vs_cached()
elif args.demo == 'depth':
await demo_search_depth_comparison()
elif args.demo == 'all':
await demo_news_search()
await demo_competitive_analysis()
await demo_deep_website_analysis()
await demo_product_research()
await demo_real_time_vs_cached()
await demo_search_depth_comparison()
except aiohttp.ClientError as e:
print(f'❌ Network Error: {e}')
except Exception as e:
print(f'❌ Error: {e}')
if __name__ == '__main__':
asyncio.run(main())
+137
View File
@@ -0,0 +1,137 @@
# Browser Use Cloud Examples 🚀
Welcome to the Browser Use Cloud examples! This folder contains progressively complex examples to help you get started with the Browser Use Cloud API quickly and efficiently.
## 📋 Prerequisites
1. **API Key**: Get your API key from [cloud.browser-use.com](https://cloud.browser-use.com/new-api-key)
2. **Python Environment**: Python 3.11+ with dependencies
3. **Environment Variables**: Configure your API settings
### Quick Setup
```bash
# Create virtual environment and install dependencies (from project root)
uv venv --python 3.11
source .venv/bin/activate # On Windows: .venv\Scripts\activate
uv sync
# Set environment variables
export BROWSER_USE_API_KEY="your_api_key_here"
export BROWSER_USE_BASE_URL="https://api.browser-use.com/api/v1" # Optional
export BROWSER_USE_TIMEOUT="30" # Optional: request timeout in seconds
# Or use .env file (recommended)
cp examples/cloud/env.example .env
# Edit .env with your values
# Run examples from project root
python examples/cloud/01_basic_task.py
```
## 🎯 Examples Overview
### 🚀 Easy Cloud Setup Examples
- **[01_basic_task.py](./01_basic_task.py)** - Your first cloud task (start here!)
- **[02_fast_mode_gemini.py](./02_fast_mode_gemini.py)** - ⚡ Ultra-fast mode with Gemini Flash & Fireship humor
- **[03_structured_output.py](./03_structured_output.py)** - Get structured JSON responses
- **[04_proxy_usage.py](./04_proxy_usage.py)** - 🌍 Proxy for geo-restrictions & captcha solving
- **[05_search_api.py](./05_search_api.py)** - 🔍 Search API for content extraction (BETA)
## 💰 Cost Optimization Tips
1. **Use Gemini Flash** for fastest/cheapest execution ($0.01/step)
2. **Disable proxy** when not needed for captcha solving
3. **Disable element highlighting** for better performance
4. **Set max_agent_steps** to prevent runaway costs
5. **Use structured output** to reduce parsing overhead
6. **Add timeouts and retries** for reliability in production
7. **Use domain restrictions** when working with secrets
## 🎨 Fast Mode Configuration
For maximum speed and cost efficiency:
```python
{
"llm_model": "gemini-2.5-flash",
"use_proxy": False,
"highlight_elements": False,
"use_adblock": True,
"max_agent_steps": 50
}
```
## 🔐 Security & Advanced Features
### Using Proxy
```python
{
"use_proxy": True,
"proxy_country_code": "us", # 'us', 'fr', 'it', 'jp', 'au', 'de', 'fi', 'ca'
}
```
### Passing Secrets Securely
```python
{
"secrets": {
"username": "your_username",
"password": "your_password",
"api_key": "your_api_key"
},
"allowed_domains": ["*.yoursite.com"] # Recommended with secrets
}
```
## 🔍 Search API (BETA)
The Search API extracts content by actually browsing websites (not cached results):
### Simple Search (Multi-site)
```python
# Cost: 1¢ × depth × websites
{
"query": "latest AI news",
"max_websites": 5,
"depth": 2
}
```
### URL Search (Single site)
```python
# Cost: 1¢ × depth
{
"url": "https://example.com",
"query": "pricing information",
"depth": 3
}
```
## 🔗 Quick Links
- [Cloud API Documentation](https://docs.browser-use.com/cloud)
- [API Reference](https://docs.browser-use.com/api-reference)
- [Pricing](https://cloud.browser-use.com/billing)
- [Discord Community](https://link.browser-use.com/discord)
## 🔧 Production Best Practices
- **Timeouts**: All examples include 30-second timeouts with retry logic
- **Error Handling**: Comprehensive error catching and status code validation
- **Security**: Use environment variables, domain restrictions with secrets
- **Reliability**: Built-in retries for network issues and rate limits
- **Automation**: CLI arguments instead of interactive prompts for CI/CD
## 🆘 Support
Need help?
- 📧 Email: support@browser-use.com
- 💬 Discord: [Join our community](https://link.browser-use.com/discord)
- 📖 Docs: <https://docs.browser-use.com>
---
**💡 Pro Tip**: Start with `01_basic_task.py` and work your way up. Each example builds on the previous ones!
+21
View File
@@ -0,0 +1,21 @@
# Browser Use Cloud API Configuration
# Copy this file to .env and fill in your values
# Required: Your Browser Use Cloud API key
# Get it from: https://cloud.browser-use.com/new-api-key
BROWSER_USE_API_KEY=your_api_key_here
# Optional: Custom API base URL (for enterprise installations)
# BROWSER_USE_BASE_URL=https://api.browser-use.com/api/v1
# Optional: Default model preference
# BROWSER_USE_DEFAULT_MODEL=gemini-2.5-flash
# Optional: Cost limits
# BROWSER_USE_MAX_COST_PER_TASK=5.0
# Optional: Request timeout (seconds)
# BROWSER_USE_TIMEOUT=30
# Optional: Logging configuration
# LOG_LEVEL=INFO