Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@

## About

Playwright for PHP lets you launch real browsers (Chromium, Firefox, WebKit), drive pages and locators, and write reliable end‑to‑end tests — all from PHP.
Playwright for PHP lets you launch real browsers (Chromium, Firefox, WebKit), drive pages and locators, and write
reliable end‑to‑end tests — all from PHP.

- **Familiar model**: browser → context → page → locator
- **Auto‑waiting** interactions reduce flakiness
Expand All @@ -21,6 +22,7 @@ Playwright for PHP lets you launch real browsers (Chromium, Firefox, WebKit), dr
- No separate server to manage — a lightweight Node server is started for you

Requirements:

- PHP 8.2+
- Node.js 20+ (used by the bundled Playwright server and browsers)

Expand Down Expand Up @@ -48,7 +50,6 @@ vendor/bin/playwright-install --with-deps
vendor/bin/playwright-install --dry-run --with-deps
```


## Quick start

Open a page and print its title:
Expand All @@ -69,13 +70,20 @@ echo $page->title().PHP_EOL; // Example Domain
$context->close();
```

## Documentation

- [Quick Start Guide](docs/guide.md)
- [Playwright Inspector](docs/inspector.md)
- [Contributing: Testing](docs/contributing/testing.md)

## Usage

### Browser

- Choose a browser: `Playwright::chromium()`, `Playwright::firefox()`, or `Playwright::webkit()`.
- `Playwright::safari()` is an alias of `webkit()`.
- Common launch options: `headless` (bool), `slowMo` (ms), `args` (array of CLI args), and an optional `context` array with context options.
- Common launch options: `headless` (bool), `slowMo` (ms), `args` (array of CLI args), and an optional `context` array
with context options.

```php
$context = Playwright::webkit([
Expand Down Expand Up @@ -165,6 +173,7 @@ final class HomePageTest extends TestCase
```

Notes:

- The trait provides `$this->playwright`, `$this->browser`, `$this->context`, and `$this->page` properties.
- Call `setUpPlaywright()` in `setUp()` and `tearDownPlaywright()` in `tearDown()` for proper lifecycle management.
- Use `$this->expect($locator)` or `$this->expect($page)` for fluent assertions.
Expand Down Expand Up @@ -198,12 +207,14 @@ jobs:
```

Tips:

- Cache Node and Composer if you need faster builds.
- You can also cache Playwright browsers under `~/.cache/ms-playwright`.

## Contributing

Contributions are welcome. Please use Conventional Commits, include tests for behavior changes, and ensure docs/examples are updated when relevant. A typical first run inside the repository is:
Contributions are welcome. Please use Conventional Commits, include tests for behavior changes, and ensure docs/examples
are updated when relevant. A typical first run inside the repository is:

```bash
composer install # installs PHP deps and the bundled Playwright server
Expand All @@ -214,5 +225,5 @@ See `docs/contributing/testing.md` for more details on the local workflow.

## License

This package is released by the [Playwright PHP](https://playwright-php.dev)
This package is released by the [Playwright PHP](https://playwright-php.dev)
project under the MIT License. See the [LICENSE](LICENSE) file for details.
65 changes: 65 additions & 0 deletions docs/examples/connect_external_browser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

/*
* This file is part of the community-maintained Playwright PHP project.
* It is not affiliated with or endorsed by Microsoft.
*
* (c) 2025-Present - Playwright PHP - https://github.com/playwright-php
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

require __DIR__.'/../../vendor/autoload.php';

use Playwright\Exception\PlaywrightException;
use Playwright\PlaywrightFactory;

$playwright = PlaywrightFactory::create();

// Example 1: launchServer() exposes a Playwright WebSocket endpoint that can be reused
// by other processes. This endpoint is ephemeral and valid while the server is running.
echo "=== Example 1: Launch Browser Server ===\n";
$server = $playwright->launchServer('chromium', ['headless' => true]);
$wsEndpoint = $server->wsEndpoint();
echo "Browser server started at: {$wsEndpoint}\n";

// Example 2: connect() uses Playwright protocol, so it must target a launchServer() endpoint.
echo "\n=== Example 2: Connect to Browser Server ===\n";
$browser = $playwright->chromium()->connect($wsEndpoint);
$context = $browser->newContext();
$page = $context->newPage();
$page->goto('https://example.com');
echo "Page title: {$page->title()}\n";

$browser->close();
// Closing the client connection does not stop the server process.
$server->close();

// Example 3: connectOverCDP() is Chromium-only and attaches to a running Chrome instance.
// First, start Chrome with remote debugging enabled.
echo "\n=== Example 3: Connect Over CDP (Chromium only) ===\n";
echo "To use this example:\n";
echo "1. Start Chrome with remote debugging on port 9222\n";
echo " macOS example:\n";
echo " \"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome\" --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-pw\n";
echo "2. Optionally set CDP_ENDPOINT (default: http://127.0.0.1:9222)\n";

$cdpEndpoint = getenv('CDP_ENDPOINT') ?: 'http://127.0.0.1:9222';

try {
$cdpBrowser = $playwright->chromium()->connectOverCDP($cdpEndpoint);
$cdpContext = $cdpBrowser->newContext();
$cdpPage = $cdpContext->newPage();
$cdpPage->goto('https://playwright.dev');
echo "Connected via CDP! Title: {$cdpPage->title()}\n";
$cdpBrowser->close();
} catch (PlaywrightException $e) {
echo "CDP connection failed at {$cdpEndpoint}: {$e->getMessage()}\n";
}

$playwright->close();

echo "\nDone!\n";
71 changes: 71 additions & 0 deletions docs/examples/connect_remote_browser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

/*
* This file is part of the community-maintained Playwright PHP project.
* It is not affiliated with or endorsed by Microsoft.
*
* (c) 2025-Present - Playwright PHP - https://github.com/playwright-php
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

require __DIR__.'/../../vendor/autoload.php';

use Playwright\PlaywrightFactory;

// Connect to an external Playwright browser-server instance started elsewhere.
// This expects a Playwright WebSocket endpoint, not a Chrome DevTools (CDP) URL.
// launchServer() starts a browser process and exposes wsEndpoint() for connect().

$playwright = PlaywrightFactory::create();

// Provide the wsEndpoint() emitted by a process that called launchServer().
$remoteWsEndpoint = getenv('REMOTE_WS_ENDPOINT');

if (false === $remoteWsEndpoint || '' === $remoteWsEndpoint) {
echo "REMOTE_WS_ENDPOINT is not set.\n";
echo "This example needs the exact wsEndpoint() value from launchServer().\n";
echo "\nQuick setup:\n";
echo "1. In another PHP process, run:\n";
echo " \$server = \$playwright->launchServer('chromium', ['headless' => true]);\n";
echo " echo \$server->wsEndpoint();\n";
echo " while (true) { sleep(1); }\n";
echo "2. Run this example with:\n";
echo " REMOTE_WS_ENDPOINT='ws://127.0.0.1:PORT/ID' php docs/examples/connect_remote_browser.php\n";
$playwright->close();

exit(1);
}

echo "Attempting to connect to remote browser at: {$remoteWsEndpoint}\n";

try {
$browser = $playwright->chromium()->connect($remoteWsEndpoint);
echo "Successfully connected to remote browser!\n";

$context = $browser->newContext();
$page = $context->newPage();

$page->goto('https://example.com');
echo "Page title: {$page->title()}\n";
echo "URL: {$page->url()}\n";

// Keep remote servers alive for other clients; only close this client connection.
$browser->close();
echo "Browser connection closed.\n";
} catch (Exception $e) {
echo "Failed to connect: {$e->getMessage()}\n";
echo "Tip: REMOTE_WS_ENDPOINT must be the full wsEndpoint() value, including path.\n";
echo "\nTo set up an external Playwright browser-server instance:\n";
echo "1. Start any PHP process with:\n";
echo " \$server = \$playwright->launchServer('chromium', ['headless' => true]);\n";
echo " echo \$server->wsEndpoint();\n";
echo " while (true) { sleep(1); }\n";
echo "2. Copy its wsEndpoint() value (ws://...)\n";
echo "3. Set REMOTE_WS_ENDPOINT to that value and run this script again\n";
}

$playwright->close();
41 changes: 41 additions & 0 deletions docs/examples/launch_server.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

/*
* This file is part of the community-maintained Playwright PHP project.
* It is not affiliated with or endorsed by Microsoft.
*
* (c) 2025-Present - Playwright PHP - https://github.com/playwright-php
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

require __DIR__.'/../../vendor/autoload.php';

use Playwright\PlaywrightFactory;

// Start a reusable Playwright browser server for external clients.
// This is useful when you want one long-lived browser shared by many scripts.

$playwright = PlaywrightFactory::create();

echo "Launching browser server...\n";

$server = $playwright->launchServer('chromium', [
'headless' => true,
]);

$wsEndpoint = $server->wsEndpoint();

echo "Browser server running!\n";
echo "WebSocket endpoint: {$wsEndpoint}\n";
echo "\nOther processes can connect using:\n";
echo "\$browser = \$playwright->chromium()->connect('{$wsEndpoint}');\n";
echo "\nPress Ctrl+C to stop the server...\n";

// Keep serving until interrupted so clients can keep connecting to this endpoint.
while (true) {
sleep(1);
}
13 changes: 13 additions & 0 deletions docs/guide/advanced-recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@
This page contains recipes for common but more advanced automation scenarios. Use these examples to leverage the full
power of Playwright for PHP.

## Table of Contents

* [File Uploads](#file-uploads)
* [Network Interception](#network-interception)
* [Handling Dialogs](#handling-dialogs)
* [Working with Frames](#working-with-frames)
* [Connecting to External Browsers](#connecting-to-external-browsers)
* [Browser Configuration with `PlaywrightConfigBuilder`](#browser-configuration-with-playwrightconfigbuilder)

## File Uploads

You can upload one or more files to an `<input type="file">` element using the `setInputFiles()` method on a `Locator`.
Expand Down Expand Up @@ -88,6 +97,10 @@ $frameButton = $frame->locator('button:has-text("Submit")');
$frameButton->click();
```

## Connecting to External Browsers

This topic has its own page: **[Connecting to External Browsers](connect-browser.md)**.

## Browser Configuration with `PlaywrightConfigBuilder`

For advanced browser setups, such as using a proxy server or setting custom launch arguments, you can use the
Expand Down
Loading