Speedofmastery's picture
Merge Landrun + Browser-Use + Chromium with AI agent support (without binary files)
d7b3d84
"""
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())