enm1989/chromedriver
A PHP package for managing ChromeDriver installations, making it easier to download and use the correct ChromeDriver binary for browser automation and testing. Useful for Laravel Dusk or Selenium-style workflows that need reliable Chrome and ChromeDriver version matching.
This package is a thin process manager for ChromeDriver: it resolves a compatible chromedriver binary, starts it on a local port, and hands you a WebDriver endpoint that Laravel Dusk (or Symfony Panther) can talk to. It does not drive the browser itself — it owns the lifecycle of the ChromeDriver server. That mental model makes the rest of the package obvious.
Minimal steps:
composer require --dev enm1989/chromedriveruse Enm1989\ChromeDriver\ChromeDriver;
$driver = new ChromeDriver();
$driver->start();
echo $driver->getUrl(); // http://127.0.0.1:9515
$driver->stop();
php artisan dusk work on a box where you don't want to hand-manage chromedriver binaries. Wire it into tests/DuskTestCase.php and delete the "install chromedriver manually" step from your onboarding docs.Where to look first:
ChromeDriver class — start(), stop(), getUrl(), and whatever options array the constructor accepts. The whole public surface is small; read it before reading the README.bin or cache path). This is where downloads land and where version mismatches will bite you.Dusk suite wiring (the 90% case). Start one driver per test run and point Dusk at it instead of letting Dusk spawn its own:
protected static $chrome;
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
static::$chrome = (new ChromeDriver())->start();
}
public static function tearDownAfterClass(): void
{
static::$chrome?->stop();
parent::tearDownAfterClass();
}
protected function driver(): RemoteWebDriver
{
return RemoteWebDriver::create(
static::$chrome->getUrl(),
DesiredCapabilities::chrome()
);
}
Start/stop around a single workflow. For an artisan command, screenshot command, or smoke-test script that needs a browser once, wrap the lifecycle in try/finally so a thrown exception never leaves an orphan process:
$driver = (new ChromeDriver())->start();
try {
$remote = RemoteWebDriver::create($driver->getUrl(), DesiredCapabilities::chrome());
// ... your work
} finally {
$driver->stop();
}
CI integration. Use it in the pipeline to guarantee a driver exists rather than trusting the base image. Install Chrome, run the package's start step (or let your test bootstrap start it), run artisan dusk, and upload screenshots on failure. Keep the binary cache directory inside the workspace cache so CI doesn't re-download every run.
Panther / raw WebDriver. There is nothing Dusk-specific here — the URL is a plain WebDriver endpoint. Feed it to ChromeManager::start() in Panther or to RemoteWebDriver::create() directly for scraping jobs.
Multiple drivers. If you run tests in parallel, start one driver per worker on a distinct port rather than sharing a single instance — sessions on the same driver contend for the browser.
chromedriver must match the installed Chrome's major version. Pin or override the version the package downloads, and run the same Chrome version locally and in CI.NOASSERTION. There is no clean declared license. Confirm with your team before shipping this into a commercial codebase; treat it as an internal-tooling-only dependency until verified.stop() is not optional. A crashed suite leaves chromedriver processes and bound ports behind. Diagnose with ps aux | grep chromedriver and lsof -i :9515, and prefer the try/finally pattern above.--headless=new (or your Chrome version's equivalent) through the chrome options, and on Linux containers add --no-sandbox and --disable-dev-shm-usage — the default /dev/shm size causes silent Chrome crashes that surface as "session not created".How can I help you explore Laravel packages today?