Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Add Docs
Chrome PHP
https://github.com/chrome-php/chrome
Admin
A PHP library to programmatically control Chrome/Chromium in headless mode, allowing for web
...
Tokens:
17,192
Snippets:
100
Trust Score:
6.2
Update:
5 months ago
Context
Skills
Chat
Benchmark
88.8
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Chrome PHP - Headless Chrome Automation Library Chrome PHP is a powerful PHP library that provides programmatic control over headless Chrome/Chromium browsers. It enables developers to automate browser interactions, perform web scraping, generate screenshots and PDFs, and execute JavaScript within page contexts. The library communicates with Chrome using the DevTools Protocol over WebSocket connections, offering both synchronous and asynchronous operation modes. Built with a focus on developer experience, Chrome PHP provides an intuitive, fluent API for common browser automation tasks. It supports PHP 7.4-8.4 and requires Chrome/Chromium 65 or higher. The library handles complex scenarios like navigation events, frame management, cookie manipulation, and input emulation while maintaining a simple, understandable interface for everyday use cases. ## Creating and Configuring Browser Instances Initialize a browser factory and create browser instances with customizable options. ```php <?php use HeadlessChromium\BrowserFactory; // Create browser factory with default Chrome binary $browserFactory = new BrowserFactory(); // Or specify custom Chrome/Chromium executable $browserFactory = new BrowserFactory('chromium-browser'); // Create browser with options $browser = $browserFactory->createBrowser([ 'headless' => true, // Enable headless mode 'windowSize' => [1920, 1080], // Set window dimensions 'noSandbox' => true, // Disable sandbox (useful in Docker) 'enableImages' => true, // Load images 'ignoreCertificateErrors' => true, // Ignore SSL errors 'userAgent' => 'MyBot/1.0', // Set custom user agent 'startupTimeout' => 30, // Chrome startup timeout (seconds) 'sendSyncDefaultTimeout' => 5000, // Default sync message timeout (ms) 'debugLogger' => 'php://stdout', // Enable debug logging 'customFlags' => [ // Additional Chrome flags '--disable-web-security', '--disable-features=IsolateOrigins,site-per-process' ] ]); try { // Use the browser $page = $browser->createPage(); $page->navigate('https://example.com')->waitForNavigation(); // Your automation code here } finally { // Always close the browser to free resources $browser->close(); } ``` ## Persistent Browser Connections Connect to an existing Chrome instance across multiple script executions. ```php <?php use HeadlessChromium\BrowserFactory; use HeadlessChromium\Exception\BrowserConnectionFailed; $socketFile = '/tmp/chrome-php-socket.txt'; // Try to connect to existing browser try { if (file_exists($socketFile)) { $socket = file_get_contents($socketFile); $browser = BrowserFactory::connectToBrowser($socket); echo "Connected to existing browser\n"; } else { throw new BrowserConnectionFailed('No socket file found'); } } catch (BrowserConnectionFailed $e) { // Browser not running, start a new one $factory = new BrowserFactory(); $browser = $factory->createBrowser([ 'keepAlive' => true, // Keep browser alive after script exits 'headless' => true ]); // Save WebSocket URI for future connections $socketUri = $browser->getSocketUri(); file_put_contents($socketFile, $socketUri, LOCK_EX); echo "Started new persistent browser: {$socketUri}\n"; } // Use the browser normally $page = $browser->createPage(); $page->navigate('https://example.com')->waitForNavigation(); echo "Page title: " . $page->evaluate('document.title')->getReturnValue() . "\n"; // Note: Don't call $browser->close() if you want to keep it running ``` ## Page Navigation and Lifecycle Events Navigate to URLs and wait for specific page load events. ```php <?php use HeadlessChromium\Page; use HeadlessChromium\Exception\OperationTimedOut; use HeadlessChromium\Exception\NavigationExpired; $page = $browser->createPage(); // Basic navigation with default LOAD event (30 second timeout) $navigation = $page->navigate('https://example.com'); $navigation->waitForNavigation(); // Navigate and wait for DOM content loaded (faster) $navigation = $page->navigate('https://example.com'); $navigation->waitForNavigation(Page::DOM_CONTENT_LOADED, 10000); // Wait for network idle (useful for SPAs) $navigation = $page->navigate('https://app.example.com'); $navigation->waitForNavigation(Page::NETWORK_IDLE, 15000); // Handle navigation errors gracefully try { $navigation = $page->navigate('https://slow-site.com'); $navigation->waitForNavigation(Page::LOAD, 5000); } catch (OperationTimedOut $e) { echo "Page took too long to load\n"; } catch (NavigationExpired $e) { echo "Navigation was interrupted by another page load\n"; } // Check current URL after navigation $currentUrl = $page->evaluate('window.location.href')->getReturnValue(); echo "Current URL: {$currentUrl}\n"; // Available lifecycle events (in order): // Page::INIT - DevTools connection initialized // Page::DOM_CONTENT_LOADED - DOM fully loaded // Page::FIRST_PAINT - First pixel painted // Page::FIRST_CONTENTFUL_PAINT - First content element painted // Page::FIRST_IMAGE_PAINT - First image painted // Page::FIRST_MEANINGFUL_PAINT - Primary content visible // Page::INTERACTIVE_TIME - Scripts loaded, main thread unblocked // Page::LOAD - Page and all resources loaded (default) // Page::NETWORK_IDLE - No network activity for 500ms ``` ## JavaScript Execution and Evaluation Execute JavaScript code and retrieve results from the page context. ```php <?php use HeadlessChromium\Exception\JavascriptException; use HeadlessChromium\Exception\EvaluationFailed; $page = $browser->createPage(); $page->navigate('https://example.com')->waitForNavigation(); // Evaluate simple expressions $title = $page->evaluate('document.title')->getReturnValue(); echo "Title: {$title}\n"; // Evaluate complex JavaScript $evaluation = $page->evaluate(' const links = Array.from(document.querySelectorAll("a")); return links.map(link => ({ text: link.textContent.trim(), href: link.href })); '); $links = $evaluation->getReturnValue(); foreach ($links as $link) { echo "{$link['text']}: {$link['href']}\n"; } // Call functions with arguments $result = $page->callFunction( 'function(a, b, c) { return a + b + c; }', [10, 20, 30] )->getReturnValue(); echo "Sum: {$result}\n"; // Outputs: Sum: 60 // Evaluate and wait for page reload $page->evaluate('document.querySelector("form").submit()')->waitForPageReload(); // Handle evaluation errors try { $page->evaluate('nonExistentFunction()')->getReturnValue(); } catch (JavascriptException $e) { echo "JavaScript error: " . $e->getMessage() . "\n"; } // Add jQuery or other libraries dynamically $page->addScriptTag([ 'url' => 'https://code.jquery.com/jquery-3.6.0.min.js' ])->waitForResponse(); $jQueryVersion = $page->evaluate('jQuery.fn.jquery')->getReturnValue(); echo "jQuery version: {$jQueryVersion}\n"; // Or inject script content directly $page->addScriptTag([ 'content' => file_get_contents('/path/to/local/script.js') ])->waitForResponse(); ``` ## Screenshot Capture Capture page screenshots with various formats and options. ```php <?php use HeadlessChromium\Clip; $page = $browser->createPage(); $page->navigate('https://example.com')->waitForNavigation(); // Simple viewport screenshot (PNG, default) $screenshot = $page->screenshot(); $screenshot->saveToFile('/tmp/screenshot.png'); // JPEG with quality setting $screenshot = $page->screenshot([ 'format' => 'jpeg', 'quality' => 80 // 0-100, only for JPEG/WebP ]); $screenshot->saveToFile('/tmp/screenshot.jpg'); // WebP format with speed optimization $screenshot = $page->screenshot([ 'format' => 'webp', 'quality' => 90, 'optimizeForSpeed' => true // Faster encoding, larger file size ]); $screenshot->saveToFile('/tmp/screenshot.webp'); // Capture specific area using Clip $clip = new Clip( 10, // x coordinate 10, // y coordinate 500, // width 400 // height ); $screenshot = $page->screenshot([ 'format' => 'png', 'clip' => $clip ]); $screenshot->saveToFile('/tmp/partial-screenshot.png'); // Full-page screenshot (beyond viewport) $screenshot = $page->screenshot([ 'captureBeyondViewport' => true, 'clip' => $page->getFullPageClip(), 'format' => 'jpeg', 'quality' => 85 ]); $screenshot->saveToFile('/tmp/fullpage-screenshot.jpg'); // Screenshot specific element $element = $page->dom()->querySelector('#main-content'); $screenshot = $page->screenshotElement($element); $screenshot->saveToFile('/tmp/element-screenshot.png'); // Get screenshot as base64 string (for inline display) $base64Data = $screenshot->getBase64(); echo "<img src='data:image/png;base64,{$base64Data}' />"; ``` ## PDF Generation Generate PDF documents from web pages with extensive customization. ```php <?php $page = $browser->createPage(); $page->navigate('https://example.com')->waitForNavigation(); // Simple PDF generation $pdf = $page->pdf(); $pdf->saveToFile('/tmp/document.pdf'); // PDF with full customization $pdf = $page->pdf([ 'landscape' => true, // Orientation 'printBackground' => true, // Include background graphics 'displayHeaderFooter' => true, // Show header/footer 'preferCSSPageSize' => false, // Use CSS @page size 'scale' => 1.0, // Scale factor (0.1 to 2.0) // Paper dimensions (in inches) 'paperWidth' => 8.5, // US Letter width 'paperHeight' => 11.0, // US Letter height // Margins (in inches) 'marginTop' => 0.5, 'marginBottom' => 0.5, 'marginLeft' => 0.5, 'marginRight' => 0.5, // Page ranges to print 'pageRanges' => '1-5, 8, 11-13', 'ignoreInvalidPageRanges' => false, // Header template (HTML with special classes) 'headerTemplate' => '<div style="font-size:10px; text-align:center; width:100%;"> <span class="title"></span> - Page <span class="pageNumber"></span> </div>', // Footer template 'footerTemplate' => '<div style="font-size:10px; text-align:center; width:100%;"> <span class="date"></span> - <span class="url"></span> </div>' ]); $pdf->saveToFile('/tmp/custom-document.pdf'); // Output PDF directly to browser header('Content-Type: application/pdf'); header('Content-Disposition: inline; filename="document.pdf"'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); echo base64_decode($pdf->getBase64()); // Template classes for headerTemplate/footerTemplate: // - date: Formatted print date // - title: Document title // - url: Document location // - pageNumber: Current page number // - totalPages: Total pages in document ``` ## Mouse Input Simulation Simulate mouse movements, clicks, and scrolling. ```php <?php use HeadlessChromium\Input\Mouse; $page = $browser->createPage(); $page->navigate('https://example.com')->waitForNavigation(); // Move mouse and click $page->mouse() ->move(100, 200) // Move to x=100, y=200 ->click(); // Left click at current position // Right-click $page->mouse() ->move(300, 400) ->click(['button' => Mouse::BUTTON_RIGHT]); // Middle-click $page->mouse() ->move(500, 600) ->click(['button' => Mouse::BUTTON_MIDDLE]); // Smooth mouse movement with multiple steps $page->mouse() ->move(0, 0) // Start position ->move(800, 600, ['steps' => 10]); // Move in 10 equal steps // Double-click $page->mouse() ->move(250, 300) ->click() ->click(); // Click and wait for page reload (e.g., clicking a link) $page->mouse() ->move(150, 250) ->click(); $page->waitForReload(); // Find element by CSS selector and click use HeadlessChromium\Exception\ElementNotFoundException; try { $page->mouse() ->find('#submit-button') // Find element with id="submit-button" ->click(); // Find nth element with class $page->mouse() ->find('.menu-item', 3) // Find 3rd element with class="menu-item" ->click(); } catch (ElementNotFoundException $e) { echo "Element not found: " . $e->getMessage() . "\n"; } // Scroll down and up $page->mouse() ->scrollDown(300) // Scroll down 300 pixels ->scrollUp(100); // Scroll up 100 pixels // Complex interaction: hover and click $page->mouse() ->find('.dropdown-trigger') ->move(10, 10); // Move slightly to trigger hover usleep(500000); // Wait 500ms for dropdown to appear $page->mouse() ->find('.dropdown-item') ->click(); ``` ## Keyboard Input Simulation Simulate keyboard typing and key combinations. ```php <?php $page = $browser->createPage(); $page->navigate('https://example.com/login')->waitForNavigation(); // Type text into focused element $page->mouse()->find('#username')->click(); $page->keyboard()->typeText('john.doe@example.com'); // Type with delay between keystrokes (more human-like) $page->mouse()->find('#password')->click(); $page->keyboard() ->setKeyInterval(50) // 50ms delay between keys ->typeText('SecurePassword123'); // Press Tab key to navigate $page->keyboard()->typeRawKey('Tab'); // Type Enter to submit form $page->keyboard()->typeRawKey('Enter'); $page->waitForReload(); // Key combinations: Ctrl+A (select all) $page->keyboard() ->press('Control') // Press and hold ->type('a') // Press and release 'a' ->release('Control'); // Release Control // Key combinations: Ctrl+C (copy) and Ctrl+V (paste twice) $page->mouse()->find('textarea')->click(); $page->keyboard() ->press('Ctrl') // 'Ctrl' is alias for 'Control' ->type('a') // Select all ->type('c') // Copy ->release('Ctrl'); $page->mouse()->find('input[name="destination"]')->click(); $page->keyboard() ->press('Ctrl') ->type('v') // Paste once ->type('v') // Paste again ->release(); // Release all pressed keys // Shift+Arrow keys for selection $page->keyboard() ->press('Shift') ->typeRawKey('ArrowRight') ->typeRawKey('ArrowRight') ->typeRawKey('ArrowRight') ->release('Shift'); // Complex form filling $page->mouse()->find('#search-input')->click(); $page->keyboard() ->setKeyInterval(75) ->typeText('headless chrome automation') ->typeRawKey('Enter'); $page->waitForReload(Page::NETWORK_IDLE, 10000); // Available key aliases: // Control: 'Control', 'Ctrl', 'Ctr' // Alt: 'Alt', 'AltGr', 'Alt Gr' // Meta: 'Meta', 'Command', 'Cmd' // Shift: 'Shift' ``` ## Cookie Management Get, set, and filter browser cookies. ```php <?php use HeadlessChromium\Cookies\Cookie; $page = $browser->createPage(); // Set cookies for a specific domain $page->setCookies([ Cookie::create('session_id', 'abc123def456', [ 'domain' => 'example.com', 'path' => '/', 'expires' => time() + 3600, // Expires in 1 hour 'httpOnly' => true, 'secure' => true, 'sameSite' => 'Lax' // Lax, Strict, or None ]), Cookie::create('user_preferences', 'theme=dark', [ 'domain' => 'example.com', 'path' => '/', 'expires' => time() + (365 * 24 * 3600) // 1 year ]) ])->await(); // Navigate after setting cookies $page->navigate('https://example.com')->waitForNavigation(); // Get all cookies for current page $cookies = $page->getCookies(); foreach ($cookies as $cookie) { echo "{$cookie->getName()}: {$cookie->getValue()}\n"; } // Get all browser cookies (across all domains) $allCookies = $page->getAllCookies(); // Filter cookies by name $sessionCookies = $cookies->filterBy('name', 'session_id'); // Find single cookie by name $userPrefCookie = $cookies->findOneBy('name', 'user_preferences'); if ($userPrefCookie) { echo "User preferences: {$userPrefCookie->getValue()}\n"; } // Filter cookies by domain $domainCookies = $allCookies->filterBy('domain', '.example.com'); // Working with CookiesCollection $collection = $page->getCookies(); echo "Total cookies: " . count($collection) . "\n"; // Session cookies example (no expiration) $page->setCookies([ Cookie::create('temp_token', 'xyz789', [ 'domain' => 'example.com' // No 'expires' means session cookie ]) ])->await(); ``` ## DOM Manipulation and Element Interaction Query and interact with page elements using CSS and XPath selectors. ```php <?php use HeadlessChromium\Dom\Selector\XPathSelector; use HeadlessChromium\Exception\ElementNotFoundException; $page = $browser->createPage(); $page->navigate('https://example.com/form')->waitForNavigation(); // Find single element by CSS selector $emailInput = $page->dom()->querySelector('#email'); // Find all elements by CSS selector $allLinks = $page->dom()->querySelectorAll('a.external-link'); foreach ($allLinks as $link) { $href = $link->getAttribute('href'); $text = $link->getText(); echo "{$text}: {$href}\n"; } // Find elements by XPath $headings = $page->dom()->search('//h1 | //h2 | //h3'); foreach ($headings as $heading) { echo $heading->getText() . "\n"; } // Wait for element to appear $page->waitUntilContainsElement('#dynamic-content', 10000); // Wait for element using XPath $page->waitUntilContainsElement( new XPathSelector('//div[contains(text(), "Loading complete")]'), 15000 ); // Get element text content $element = $page->dom()->querySelector('.article-title'); $titleText = $element->getText(); echo "Article title: {$titleText}\n"; // Get element attributes $link = $page->dom()->querySelector('a.download'); $downloadUrl = $link->getAttribute('href'); $linkClass = $link->getAttribute('class'); // Send text to input elements $usernameInput = $page->dom()->querySelector('input[name="username"]'); $usernameInput->click(); // Focus the element $usernameInput->sendKeys('testuser'); $passwordInput = $page->dom()->querySelector('input[name="password"]'); $passwordInput->click(); $passwordInput->sendKeys('password123'); // Upload file to file input $fileInput = $page->dom()->querySelector('input[type="file"]'); $fileInput->sendFile('/path/to/local/file.pdf'); // Click elements $submitButton = $page->dom()->querySelector('button[type="submit"]'); $submitButton->click(); // Find nested elements $mainContent = $page->dom()->querySelector('#main-content'); $nestedLinks = $mainContent->querySelectorAll('a'); // Complex XPath queries $rows = $page->dom()->search('//table[@id="data-table"]//tr[position() > 1]'); foreach ($rows as $row) { $cells = $row->querySelectorAll('td'); echo "Row data: "; foreach ($cells as $cell) { echo $cell->getText() . " | "; } echo "\n"; } // Check if element exists before interaction try { $optionalElement = $page->dom()->querySelector('.optional-banner'); $optionalElement->click(); } catch (ElementNotFoundException $e) { echo "Optional element not found, continuing...\n"; } ``` ## Viewport and Device Emulation Configure viewport size and emulate device characteristics. ```php <?php $page = $browser->createPage(); // Set custom viewport size $page->setViewport(1366, 768)->await(); $page->navigate('https://example.com')->waitForNavigation(); // Mobile device emulation $page->setDeviceMetricsOverride([ 'width' => 375, 'height' => 812, 'deviceScaleFactor' => 3, 'mobile' => true, 'screenOrientation' => [ 'type' => 'portraitPrimary', 'angle' => 0 ] ])->await(); // Set mobile user agent $page->setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1'); // Navigate after device emulation setup $page->navigate('https://m.example.com')->waitForNavigation(); // Tablet emulation $page->setViewport(768, 1024)->await(); $page->setDeviceMetricsOverride([ 'width' => 768, 'height' => 1024, 'deviceScaleFactor' => 2, 'mobile' => true ])->await(); // Desktop with high DPI $page->setViewport(1920, 1080)->await(); $page->setDeviceMetricsOverride([ 'width' => 1920, 'height' => 1080, 'deviceScaleFactor' => 2, 'mobile' => false ])->await(); // Override timezone use HeadlessChromium\Exception\InvalidTimezoneId; try { $page->setTimezone('America/New_York')->await(); $page->navigate('https://example.com')->waitForNavigation(); $timezone = $page->evaluate('Intl.DateTimeFormat().resolvedOptions().timeZone')->getReturnValue(); echo "Browser timezone: {$timezone}\n"; } catch (InvalidTimezoneId $e) { echo "Invalid timezone ID\n"; } // Get layout metrics $metrics = $page->getLayoutMetrics()->waitForResponse(); $contentSize = $metrics->getContentSize(); echo "Content width: {$contentSize['width']}, height: {$contentSize['height']}\n"; ``` ## Pre-Scripts and Page Hooks Execute JavaScript before page navigation. ```php <?php $page = $browser->createPage(); // Add script to execute on every new page $page->addPreScript(' // Override navigator.webdriver to avoid detection Object.defineProperty(navigator, "webdriver", { get: () => false }); // Mock permissions API const originalQuery = window.navigator.permissions.query; window.navigator.permissions.query = (parameters) => ( parameters.name === "notifications" ? Promise.resolve({ state: Notification.permission }) : originalQuery(parameters) ); '); // Add script that runs after DOM loads $page->addPreScript(' console.log("Page loaded at:", window.location.href); // Inject custom analytics blocker window.ga = function() { console.log("Analytics blocked"); }; ', ['onLoad' => true]); // Set pre-script at browser level (affects all pages) $browser->setPagePreScript(' // Global script for all pages window.customGlobal = "Available on all pages"; '); // Navigate after setting pre-scripts $page->navigate('https://example.com')->waitForNavigation(); // Verify script executed $webdriverValue = $page->evaluate('navigator.webdriver')->getReturnValue(); echo "navigator.webdriver: " . ($webdriverValue ? 'true' : 'false') . "\n"; ``` ## Advanced Communication Protocol Directly communicate with Chrome DevTools Protocol. ```php <?php use HeadlessChromium\Communication\Connection; use HeadlessChromium\Communication\Message; // Get WebSocket URI from browser $webSocketUri = 'ws://127.0.0.1:9222/devtools/browser/xxxxx'; // Create low-level connection $connection = new Connection($webSocketUri); $connection->connect(); // Send message and wait for response $responseReader = $connection->sendMessage( new Message('Target.createTarget', ['url' => 'about:blank']) ); $response = $responseReader->waitForResponse(5000); // 5 second timeout if ($response->isSuccessful()) { $targetId = $response->getResultData()['targetId']; echo "Created target: {$targetId}\n"; } else { echo "Error: " . $response->getErrorMessage() . "\n"; } // Create session for specific target $session = $connection->createSession($targetId); // Send message to target via session $response = $session->sendMessageSync( new Message('Page.navigate', ['url' => 'https://example.com']) ); // Set connection delay for debugging $connection->setConnectionDelay(500); // 500ms delay between operations // Check connection status if ($connection->isConnected()) { echo "Connected to Chrome\n"; } // Standalone browser from connection $browser = new \HeadlessChromium\Browser($connection); $page = $browser->createPage(); // Disconnect when done $connection->disconnect(); ``` ## Error Handling and Debugging Handle exceptions and enable debugging features. ```php <?php use HeadlessChromium\Exception\BrowserConnectionFailed; use HeadlessChromium\Exception\OperationTimedOut; use HeadlessChromium\Exception\NavigationExpired; use HeadlessChromium\Exception\JavascriptException; use HeadlessChromium\Exception\ElementNotFoundException; use HeadlessChromium\Exception\CommunicationException; // Enable verbose debugging $browserFactory = new BrowserFactory(); $browser = $browserFactory->createBrowser([ 'headless' => false, // Disable headless to see browser 'debugLogger' => 'php://stdout', // Log to stdout 'connectionDelay' => 0.5, // 500ms delay between operations 'startupTimeout' => 60 // Extended startup timeout ]); try { $page = $browser->createPage(); // Navigation error handling try { $navigation = $page->navigate('https://slow-website.com'); $navigation->waitForNavigation(Page::LOAD, 5000); } catch (OperationTimedOut $e) { echo "Navigation timed out after 5 seconds\n"; // Continue with partially loaded page or retry } catch (NavigationExpired $e) { echo "Navigation was interrupted\n"; } // JavaScript error handling try { $result = $page->evaluate('undefinedFunction()')->getReturnValue(); } catch (JavascriptException $e) { echo "JavaScript error: {$e->getMessage()}\n"; } // Element not found handling try { $page->mouse()->find('#non-existent-element')->click(); } catch (ElementNotFoundException $e) { echo "Element not found: {$e->getMessage()}\n"; } // Communication error handling try { $page->evaluate('complex.operation()')->getReturnValue(); } catch (CommunicationException $e) { echo "Communication error: {$e->getMessage()}\n"; } } catch (\Exception $e) { echo "Unexpected error: {$e->getMessage()}\n"; echo $e->getTraceAsString() . "\n"; } finally { // Always clean up if (isset($browser)) { $browser->close(); } } // Connection error handling try { $browser = BrowserFactory::connectToBrowser('ws://invalid:9222'); } catch (BrowserConnectionFailed $e) { echo "Failed to connect: {$e->getMessage()}\n"; } ``` ## Use Cases and Integration Patterns Chrome PHP excels at automated web testing, content generation, and data extraction scenarios. Common use cases include generating PDF invoices and reports from web templates, capturing screenshots for visual regression testing, scraping dynamic JavaScript-rendered content, automating form submissions and login workflows, and testing responsive designs across different viewport sizes. The library integrates seamlessly into PHP applications, batch processing scripts, CI/CD pipelines, and scheduled cron jobs. Integration patterns typically involve creating a browser factory at application startup, maintaining persistent browser instances for performance-critical scenarios, implementing retry logic for flaky network conditions, and proper resource cleanup using try-finally blocks. For high-throughput scenarios, consider using the keepAlive option to maintain browser processes across multiple script executions, reducing startup overhead. The library's synchronous API simplifies sequential workflows, while the underlying async architecture enables concurrent page operations when needed. Always configure appropriate timeouts, enable debug logging during development, and handle specific exceptions to build robust automation solutions.