Yes, Symfony Panther is fully compatible with headless browsers including Chrome and Firefox. Panther is a PHP library that provides a unified API for browser automation using the WebDriver protocol, making it ideal for both automated testing and web scraping applications.
Browser Support
Symfony Panther supports:
- Chrome/Chromium via ChromeDriver
- Firefox via GeckoDriver
- Headless mode (default behavior)
- Non-headless mode for debugging
Installation
Install Symfony Panther using Composer:
composer require symfony/panther
Prerequisites
Before using Panther, ensure you have the required drivers:
For Chrome
- Chrome or Chromium browser
- ChromeDriver (can be installed via
chromedriver-binary
package)
composer require --dev dbrekelmans/bdi
vendor/bin/bdi detect drivers
For Firefox
- Firefox browser
- GeckoDriver
# Download GeckoDriver from GitHub releases
wget https://github.com/mozilla/geckodriver/releases/download/v0.33.0/geckodriver-v0.33.0-linux64.tar.gz
tar -xzf geckodriver-v0.33.0-linux64.tar.gz
sudo mv geckodriver /usr/local/bin/
Usage Examples
Basic Chrome Setup (Default)
<?php
use Symfony\Component\Panther\PantherTestCase;
class WebScrapingTest extends PantherTestCase
{
public function testScraping()
{
// Creates headless Chrome client by default
$client = static::createPantherClient();
$crawler = $client->request('GET', 'https://example.com');
// Extract data
$title = $crawler->filter('title')->text();
$headings = $crawler->filter('h1, h2, h3')->each(function ($node) {
return $node->text();
});
$this->assertStringContainsString('Example', $title);
}
}
Firefox Configuration
<?php
use Symfony\Component\Panther\PantherTestCase;
class FirefoxScrapingTest extends PantherTestCase
{
public function testWithFirefox()
{
// Configure Firefox as browser
$client = static::createPantherClient([
'browser' => static::FIREFOX,
]);
$crawler = $client->request('GET', 'https://example.com');
// Wait for dynamic content
$client->waitFor('h1');
$heading = $crawler->filter('h1')->text();
$this->assertNotEmpty($heading);
}
}
Environment Variables Configuration
<?php
// Set environment variables for Firefox
$_SERVER['PANTHER_BROWSER'] = 'firefox';
$_SERVER['PANTHER_NO_HEADLESS'] = 0; // 0 = headless, 1 = with GUI
$_SERVER['PANTHER_WEB_SERVER_PORT'] = 9080;
use Symfony\Component\Panther\PantherTestCase;
class ConfiguredTest extends PantherTestCase
{
public function testWithEnvironmentConfig()
{
$client = static::createPantherClient();
// Will use Firefox in headless mode due to environment variables
$crawler = $client->request('GET', 'https://httpbin.org/json');
$jsonText = $crawler->filter('pre')->text();
$data = json_decode($jsonText, true);
$this->assertIsArray($data);
}
}
Custom Browser Options
<?php
use Symfony\Component\Panther\PantherTestCase;
class CustomOptionsTest extends PantherTestCase
{
public function testWithCustomOptions()
{
$client = static::createPantherClient([
'browser' => static::CHROME,
], [
'--window-size=1920,1080',
'--user-agent=Custom Bot 1.0',
'--disable-web-security',
'--disable-features=VizDisplayCompositor'
]);
$crawler = $client->request('GET', 'https://httpbin.org/user-agent');
$userAgent = json_decode($crawler->filter('pre')->text(), true);
$this->assertStringContainsString('Custom Bot', $userAgent['user-agent']);
}
}
Web Scraping with Form Interaction
<?php
use Symfony\Component\Panther\PantherTestCase;
class FormScrapingTest extends PantherTestCase
{
public function testFormInteraction()
{
$client = static::createPantherClient();
$crawler = $client->request('GET', 'https://httpbin.org/forms/post');
// Fill and submit form
$form = $crawler->selectButton('Submit')->form([
'custname' => 'John Doe',
'custtel' => '123-456-7890',
'custemail' => 'john@example.com',
]);
$client->submit($form);
$client->waitFor('pre'); // Wait for response
$response = json_decode($client->getCrawler()->filter('pre')->text(), true);
$this->assertEquals('John Doe', $response['form']['custname']);
}
}
Configuration Options
Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| PANTHER_BROWSER
| Browser to use (chrome
or firefox
) | chrome
|
| PANTHER_NO_HEADLESS
| Disable headless mode (0=headless, 1=GUI) | 0
|
| PANTHER_CHROME_DRIVER_BINARY
| Path to ChromeDriver binary | Auto-detected |
| PANTHER_FIREFOX_DRIVER_BINARY
| Path to GeckoDriver binary | Auto-detected |
| PANTHER_WEB_SERVER_PORT
| Port for built-in web server | 9080
|
Client Options
$client = static::createPantherClient([
'browser' => static::FIREFOX, // Browser type
'hostname' => 'localhost', // Hostname
'port' => 4444, // WebDriver port
'base_uri' => 'http://localhost:8000', // Base URI for requests
]);
Best Practices
Performance Optimization
- Use headless mode for production scraping
- Disable unnecessary browser features
- Set appropriate timeouts
$client = static::createPantherClient([], [
'--no-sandbox',
'--disable-gpu',
'--disable-dev-shm-usage',
'--disable-extensions',
'--disable-images', // Skip image loading
]);
Error Handling
try {
$client = static::createPantherClient();
$crawler = $client->request('GET', 'https://example.com');
// Wait for element with timeout
$client->waitFor('.content', 10);
$content = $crawler->filter('.content')->text();
} catch (\Exception $e) {
// Handle WebDriver exceptions
echo "Error: " . $e->getMessage();
} finally {
if (isset($client)) {
$client->quit(); // Clean up browser session
}
}
Key Advantages
- Unified API: Same code works with both Chrome and Firefox
- JavaScript Support: Fully renders dynamic content
- Selenium Integration: Compatible with existing WebDriver infrastructure
- Symfony Integration: Seamlessly works with Symfony applications
- Testing Framework: Built-in PHPUnit integration
Symfony Panther provides a robust solution for headless browser automation in PHP, making it an excellent choice for both web scraping and end-to-end testing scenarios.