# Browser Automation Examples Complete workflows demonstrating the `use_browser` tool capabilities. ## Table of Contents 1. [E-Commerce Workflows](#e-commerce-workflows) 2. [Form Automation](#form-automation) 3. [Data Extraction](#data-extraction) 4. [Multi-Tab Operations](#multi-tab-operations) 5. [Dynamic Content Handling](#dynamic-content-handling) 6. [Authentication Workflows](#authentication-workflows) --- ## E-Commerce Workflows ### Complete Booking Flow Navigate multi-step booking process with validation: ```json // Step 1: Search {action: "navigate", payload: "https://booking.example.com"} {action: "await_element", selector: "input[name=destination]"} {action: "type", selector: "input[name=destination]", payload: "San Francisco"} {action: "type", selector: "input[name=checkin]", payload: "2025-12-01"} {action: "click", selector: "button.search"} // Step 2: Select hotel {action: "await_element", selector: ".hotel-results"} {action: "click", selector: ".hotel-card:first-child .select"} // Step 3: Choose room {action: "await_element", selector: ".room-options"} {action: "click", selector: ".room[data-type=deluxe] .book"} // Step 4: Guest info {action: "await_element", selector: "form.guest-info"} {action: "type", selector: "input[name=firstName]", payload: "Jane"} {action: "type", selector: "input[name=lastName]", payload: "Smith"} {action: "type", selector: "input[name=email]", payload: "jane@example.com"} // Step 5: Review {action: "click", selector: "button.review"} {action: "await_element", selector: ".summary"} // Validate {action: "extract", payload: "text", selector: ".hotel-name"} {action: "extract", payload: "text", selector: ".total-price"} ``` ### Price Comparison Across Sites Open multiple stores in tabs and compare: ```json // Store 1 {action: "navigate", payload: "https://store1.com/product/12345"} {action: "await_element", selector: ".price"} // Open Store 2 {action: "new_tab"} {action: "navigate", tab_index: 1, payload: "https://store2.com/product/12345"} {action: "await_element", tab_index: 1, selector: ".price"} // Open Store 3 {action: "new_tab"} {action: "navigate", tab_index: 2, payload: "https://store3.com/product/12345"} {action: "await_element", tab_index: 2, selector: ".price"} // Extract all prices {action: "extract", tab_index: 0, payload: "text", selector: ".price"} {action: "extract", tab_index: 1, payload: "text", selector: ".price"} {action: "extract", tab_index: 2, payload: "text", selector: ".price"} // Get product info {action: "extract", tab_index: 0, payload: "text", selector: ".product-name"} {action: "extract", tab_index: 0, payload: "text", selector: ".stock-status"} ``` ### Product Data Extraction Scrape structured product information: ```json {action: "navigate", payload: "https://shop.example.com/product/123"} {action: "await_element", selector: ".product-details"} // Extract all product data with one eval {action: "eval", payload: ` ({ name: document.querySelector('h1.product-name').textContent.trim(), price: document.querySelector('.price').textContent.trim(), image: document.querySelector('.product-image img').src, description: document.querySelector('.description').textContent.trim(), stock: document.querySelector('.stock-status').textContent.trim(), rating: document.querySelector('.rating').textContent.trim(), reviews: Array.from(document.querySelectorAll('.review')).map(r => ({ author: r.querySelector('.author').textContent, rating: r.querySelector('.stars').textContent, text: r.querySelector('.review-text').textContent })) }) `} ``` ### Batch Product Extraction Get multiple products from category page: ```json {action: "navigate", payload: "https://shop.example.com/category/electronics"} {action: "await_element", selector: ".product-grid"} // Extract all products as array {action: "eval", payload: ` Array.from(document.querySelectorAll('.product-card')).map(card => ({ name: card.querySelector('.product-name').textContent.trim(), price: card.querySelector('.price').textContent.trim(), image: card.querySelector('img').src, url: card.querySelector('a').href, inStock: !card.querySelector('.out-of-stock') })) `} ``` --- ## Form Automation ### Multi-Step Registration Form Handle progressive form with validation at each step: ```json // Step 1: Personal info {action: "navigate", payload: "https://example.com/register"} {action: "await_element", selector: "input[name=firstName]"} {action: "type", selector: "input[name=firstName]", payload: "John"} {action: "type", selector: "input[name=lastName]", payload: "Doe"} {action: "type", selector: "input[name=email]", payload: "john@example.com"} {action: "click", selector: "button.next"} // Wait for step 2 {action: "await_element", selector: "input[name=address]"} // Step 2: Address {action: "type", selector: "input[name=address]", payload: "123 Main St"} {action: "type", selector: "input[name=city]", payload: "Springfield"} {action: "select", selector: "select[name=state]", payload: "IL"} {action: "type", selector: "input[name=zip]", payload: "62701"} {action: "click", selector: "button.next"} // Wait for step 3 {action: "await_element", selector: "input[name=cardNumber]"} // Step 3: Payment {action: "type", selector: "input[name=cardNumber]", payload: "4111111111111111"} {action: "select", selector: "select[name=expMonth]", payload: "12"} {action: "select", selector: "select[name=expYear]", payload: "2028"} {action: "type", selector: "input[name=cvv]", payload: "123"} // Review before submit {action: "click", selector: "button.review"} {action: "await_element", selector: ".summary"} // Extract confirmation {action: "extract", payload: "markdown", selector: ".summary"} ``` ### Search with Multiple Filters Use dropdowns, checkboxes, and text inputs: ```json {action: "navigate", payload: "https://library.example.com/search"} {action: "await_element", selector: "form.search"} // Category dropdown {action: "select", selector: "select[name=category]", payload: "books"} // Price range {action: "type", selector: "input[name=priceMin]", payload: "10"} {action: "type", selector: "input[name=priceMax]", payload: "50"} // Checkboxes via JavaScript {action: "eval", payload: "document.querySelector('input[name=inStock]').checked = true"} {action: "eval", payload: "document.querySelector('input[name=freeShipping]').checked = true"} // Search term and submit {action: "type", selector: "input[name=query]", payload: "chrome devtools\n"} // Wait for results {action: "await_element", selector: ".results"} // Count and extract {action: "eval", payload: "document.querySelectorAll('.result').length"} {action: "extract", payload: "text", selector: ".result-count"} ``` ### File Upload Handle file input using JavaScript: ```json {action: "navigate", payload: "https://example.com/upload"} {action: "await_element", selector: "input[type=file]"} // Read file and set via JavaScript (for testing) {action: "eval", payload: ` const fileInput = document.querySelector('input[type=file]'); const dataTransfer = new DataTransfer(); const file = new File(['test content'], 'test.txt', { type: 'text/plain' }); dataTransfer.items.add(file); fileInput.files = dataTransfer.files; `} // Submit {action: "click", selector: "button.upload"} {action: "await_text", payload: "Upload complete"} ``` --- ## Data Extraction ### Article Scraping Extract blog post with metadata: ```json {action: "navigate", payload: "https://blog.example.com/article"} {action: "await_element", selector: "article"} // Extract complete article structure {action: "eval", payload: ` ({ title: document.querySelector('article h1').textContent.trim(), author: document.querySelector('.author-name').textContent.trim(), date: document.querySelector('time').getAttribute('datetime'), tags: Array.from(document.querySelectorAll('.tag')).map(t => t.textContent.trim()), content: document.querySelector('article .content').textContent.trim(), images: Array.from(document.querySelectorAll('article img')).map(img => ({ src: img.src, alt: img.alt })), links: Array.from(document.querySelectorAll('article a')).map(a => ({ text: a.textContent.trim(), href: a.href })) }) `} ``` ### Table Data Extraction Convert HTML table to structured JSON: ```json {action: "navigate", payload: "https://example.com/data/table"} {action: "await_element", selector: "table"} // Extract table with headers {action: "eval", payload: ` (() => { const headers = Array.from(document.querySelectorAll('table thead th')) .map(th => th.textContent.trim()); const rows = Array.from(document.querySelectorAll('table tbody tr')) .map(tr => { const cells = Array.from(tr.cells).map(td => td.textContent.trim()); return Object.fromEntries(headers.map((h, i) => [h, cells[i]])); }); return rows; })() `} ``` ### Paginated Results Extract data across multiple pages: ```json {action: "navigate", payload: "https://example.com/results?page=1"} {action: "await_element", selector: ".results"} // Page 1 {action: "eval", payload: "Array.from(document.querySelectorAll('.result')).map(r => r.textContent.trim())"} // Navigate to page 2 {action: "click", selector: "a.next-page"} {action: "await_element", selector: ".results"} {action: "await_text", payload: "Page 2"} // Page 2 {action: "eval", payload: "Array.from(document.querySelectorAll('.result')).map(r => r.textContent.trim())"} // Continue pattern for additional pages... ``` --- ## Multi-Tab Operations ### Email Receipt Extraction Find specific email and extract data: ```json // List available tabs {action: "list_tabs"} // Switch to email tab (assume index 2 from list) {action: "click", tab_index: 2, selector: "a[title*='Receipt']"} {action: "await_element", tab_index: 2, selector: ".email-body"} // Extract receipt details {action: "extract", tab_index: 2, payload: "text", selector: ".order-number"} {action: "extract", tab_index: 2, payload: "text", selector: ".total-amount"} {action: "extract", tab_index: 2, payload: "markdown", selector: ".items-list"} ``` ### Cross-Site Data Correlation Extract from one site, verify on another: ```json // Get company phone from website {action: "navigate", payload: "https://company.com/contact"} {action: "await_element", selector: ".contact-info"} {action: "extract", payload: "text", selector: ".phone-number"} // Store result: "+1-555-0123" // Open verification site in new tab {action: "new_tab"} {action: "navigate", tab_index: 1, payload: "https://phonevalidator.com"} {action: "await_element", tab_index: 1, selector: "input[name=phone]"} // Fill and search {action: "type", tab_index: 1, selector: "input[name=phone]", payload: "+1-555-0123\n"} {action: "await_element", tab_index: 1, selector: ".results"} // Extract validation result {action: "extract", tab_index: 1, payload: "text", selector: ".verification-status"} ``` ### Parallel Data Collection Collect data from multiple sources simultaneously: ```json // Tab 0: Weather {action: "navigate", tab_index: 0, payload: "https://weather.com/city"} {action: "await_element", tab_index: 0, selector: ".temperature"} // Tab 1: News {action: "new_tab"} {action: "navigate", tab_index: 1, payload: "https://news.com"} {action: "await_element", tab_index: 1, selector: ".headlines"} // Tab 2: Stock prices {action: "new_tab"} {action: "navigate", tab_index: 2, payload: "https://stocks.com"} {action: "await_element", tab_index: 2, selector: ".market-summary"} // Extract all data {action: "extract", tab_index: 0, payload: "text", selector: ".temperature"} {action: "extract", tab_index: 1, payload: "text", selector: ".headline:first-child"} {action: "extract", tab_index: 2, payload: "text", selector: ".market-summary"} ``` --- ## Dynamic Content Handling ### Infinite Scroll Loading Load all content with scroll-triggered pagination: ```json {action: "navigate", payload: "https://example.com/feed"} {action: "await_element", selector: ".feed-item"} // Count initial items {action: "eval", payload: "document.querySelectorAll('.feed-item').length"} // Scroll and wait multiple times {action: "eval", payload: "window.scrollTo(0, document.body.scrollHeight)"} {action: "eval", payload: "new Promise(r => setTimeout(r, 2000))"} {action: "eval", payload: "window.scrollTo(0, document.body.scrollHeight)"} {action: "eval", payload: "new Promise(r => setTimeout(r, 2000))"} {action: "eval", payload: "window.scrollTo(0, document.body.scrollHeight)"} {action: "eval", payload: "new Promise(r => setTimeout(r, 2000))"} // Extract all loaded items {action: "eval", payload: ` Array.from(document.querySelectorAll('.feed-item')).map(item => ({ title: item.querySelector('.title').textContent.trim(), date: item.querySelector('.date').textContent.trim(), url: item.querySelector('a').href })) `} ``` ### Wait for AJAX Response Wait for loading indicator to disappear: ```json {action: "navigate", payload: "https://app.com/dashboard"} {action: "await_element", selector: ".content"} // Trigger AJAX request {action: "click", selector: "button.load-data"} // Wait for spinner to appear then disappear {action: "eval", payload: ` new Promise(resolve => { const checkGone = () => { const spinner = document.querySelector('.spinner'); if (!spinner || spinner.style.display === 'none') { resolve(true); } else { setTimeout(checkGone, 100); } }; checkGone(); }) `} // Now safe to extract {action: "extract", payload: "text", selector: ".data-table"} ``` ### Modal Dialog Handling Open modal, interact, wait for close: ```json {action: "click", selector: "button.open-settings"} {action: "await_element", selector: ".modal.visible"} // Interact with modal {action: "type", selector: ".modal input[name=username]", payload: "newuser"} {action: "select", selector: ".modal select[name=theme]", payload: "dark"} {action: "click", selector: ".modal button.save"} // Wait for modal to close {action: "eval", payload: ` new Promise(resolve => { const check = () => { const modal = document.querySelector('.modal.visible'); if (!modal) { resolve(true); } else { setTimeout(check, 100); } }; check(); }) `} // Verify settings saved {action: "await_text", payload: "Settings saved"} ``` ### Wait for Button Enabled Wait for form validation before submission: ```json {action: "type", selector: "input[name=email]", payload: "user@example.com"} {action: "type", selector: "input[name=password]", payload: "securepass123"} // Wait for submit button to become enabled {action: "eval", payload: ` new Promise(resolve => { const check = () => { const btn = document.querySelector('button[type=submit]'); if (btn && !btn.disabled && !btn.classList.contains('disabled')) { resolve(true); } else { setTimeout(check, 100); } }; check(); }) `} // Now safe to click {action: "click", selector: "button[type=submit]"} ``` --- ## Authentication Workflows ### Standard Login ```json {action: "navigate", payload: "https://app.example.com/login"} {action: "await_element", selector: "form.login"} // Fill credentials {action: "type", selector: "input[name=email]", payload: "user@example.com"} {action: "type", selector: "input[name=password]", payload: "password123\n"} // Wait for redirect {action: "await_text", payload: "Dashboard"} // Verify logged in {action: "extract", payload: "text", selector: ".user-name"} ``` ### OAuth Flow ```json {action: "navigate", payload: "https://app.example.com/connect"} {action: "await_element", selector: "button.oauth-login"} // Trigger OAuth {action: "click", selector: "button.oauth-login"} // Wait for OAuth provider page {action: "await_text", payload: "Authorize"} // Fill OAuth credentials {action: "await_element", selector: "input[name=username]"} {action: "type", selector: "input[name=username]", payload: "oauthuser"} {action: "type", selector: "input[name=password]", payload: "oauthpass\n"} // Wait for redirect back {action: "await_text", payload: "Connected successfully"} ``` ### Session Persistence Check ```json // Load page {action: "navigate", payload: "https://app.example.com/dashboard"} {action: "await_element", selector: "body"} // Check if logged in via cookie/localStorage {action: "eval", payload: "document.cookie.includes('session_id')"} {action: "eval", payload: "localStorage.getItem('auth_token') !== null"} // Verify user data loaded {action: "extract", payload: "text", selector: ".user-profile"} ``` --- ## Advanced Patterns ### Conditional Workflow Branch based on page content: ```json {action: "navigate", payload: "https://example.com/status"} {action: "await_element", selector: "body"} // Check status {action: "extract", payload: "text", selector: ".status-message"} // If result contains "Available": {action: "click", selector: "button.purchase"} {action: "await_text", payload: "Added to cart"} // If result contains "Out of stock": {action: "click", selector: "button.notify-me"} {action: "type", selector: "input[name=email]", payload: "notify@example.com\n"} ``` ### Error Recovery Handle and retry failed operations: ```json {action: "navigate", payload: "https://app.example.com/data"} {action: "await_element", selector: ".content"} // Attempt operation {action: "click", selector: "button.load"} // Check for error {action: "eval", payload: "!!document.querySelector('.error-message')"} // If error present, retry {action: "click", selector: "button.retry"} {action: "await_element", selector: ".data-loaded"} ``` ### Screenshot Comparison Capture before and after states: ```json // Initial state {action: "navigate", payload: "https://example.com"} {action: "await_element", selector: ".content"} {action: "screenshot", payload: "/tmp/before.png"} // Make changes {action: "click", selector: "button.dark-mode"} {action: "await_element", selector: "body.dark"} // Capture new state {action: "screenshot", payload: "/tmp/after.png"} // Or screenshot specific element {action: "screenshot", payload: "/tmp/header.png", selector: "header"} ``` --- ## Tips for Complex Workflows ### Build Incrementally Start simple, add complexity: 1. Navigate and verify page loads 2. Extract one element 3. Add interaction 4. Add waiting logic 5. Add error handling 6. Add validation ### Use JavaScript for Complex Logic When multiple operations needed, use `eval`: ```json {action: "eval", payload: ` (async () => { // Complex multi-step logic const results = []; const items = document.querySelectorAll('.item'); for (const item of items) { if (item.classList.contains('active')) { results.push({ id: item.dataset.id, text: item.textContent.trim() }); } } return results; })() `} ``` ### Validate Selectors Always test selectors return expected elements: ```json // Check element exists {action: "eval", payload: "!!document.querySelector('button.submit')"} // Check element visible {action: "eval", payload: "window.getComputedStyle(document.querySelector('button.submit')).display !== 'none'"} // Check element count {action: "eval", payload: "document.querySelectorAll('.item').length"} ```