""" 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())