Object model

Understand the public PHP objects, their responsibilities, and their lifecycles.

Playwright PHP exposes small PHP objects for the browser concepts you work with: clients, browsers, contexts, pages, frames, locators, network messages, and artifacts. Each object has a specific scope. Choosing the right scope keeps tests easier to isolate and debug.

Two entry styles

For a script or a first test, use the convenience entry point:

php
use Playwright\Playwright;

$context = Playwright::chromium();
$page = $context->newPage();

Playwright::chromium(), firefox(), and webkit() return a BrowserContextInterface directly. Browser and client setup are managed for you.

Use the explicit client when you need configuration, browser builders, a long-lived process, or more control over cleanup:

php
use Playwright\PlaywrightFactory;

$client = PlaywrightFactory::create();
$browser = $client->chromium()
    ->withHeadless(true)
    ->launch();

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

Both styles reach the same browser engine. The difference is how much lifecycle and configuration you own.

The useful hierarchy

text
PlaywrightClient
  -> Browser
      -> BrowserContext
          -> Page
              -> Frame
              -> Locator
              -> Keyboard / Mouse / Touchscreen
              -> Request / Response / Route
              -> Download / Video

Client

PlaywrightClient owns the connection to the Node.js bridge. It creates browser builders, exposes selector configuration, and closes the transport.

Most application code does not need to pass the client around. Treat it as runtime infrastructure.

Browser

BrowserInterface represents a launched browser process. It can create contexts and report browser-level information.

Launching browsers is relatively expensive. A test suite normally reuses a browser while creating a fresh context for each isolated scenario.

Browser context

BrowserContextInterface is the main isolation boundary. It owns:

  • cookies and storage;
  • permissions, locale, timezone, viewport, and user agent;
  • pages;
  • routes and browser-level events;
  • tracing and video configuration.

Use a new context when the scenario needs a new user or clean browser state. Opening another page is not equivalent: pages in one context share session state.

Page and frame

PageInterface represents one tab. It is the normal surface for navigation, locators, input, events, network observation, screenshots, and PDF capture.

A frame is a document embedded in the page. Prefer frameLocator() when you need to locate and act inside an iframe. It keeps the frame boundary visible in the test and avoids storing a frame that may be replaced during navigation.

Locator

LocatorInterface is a live description of how to find an element. It is not a cached DOM node.

That distinction matters: when the page re-renders, a locator resolves against the current document before each action or assertion. Prefer role, label, text, and test-id locators over storing element-like state yourself.

Supporting objects

Network and runtime objects describe a moment in a browser run:

  • RequestInterface describes an outgoing request.
  • ResponseInterface describes its response.
  • RouteInterface controls an intercepted request.
  • ConsoleMessage, DialogInterface, DownloadInterface, and WebErrorInterface carry event-specific information.

These are not good places to store application state. Read what you need while handling the event, then assert the user-visible result or save the relevant artifact.

Interfaces and implementations

The public API commonly returns interfaces such as PageInterface, LocatorInterface, and BrowserContextInterface. Type your helpers against those interfaces:

php
use Playwright\Locator\LocatorInterface;

function submitButton(LocatorInterface $form): LocatorInterface
{
    return $form->getByRole('button', ['name' => 'Save']);
}

Use the API reference for exact return types. Avoid depending on transport classes from test code; they are infrastructure, not browser concepts.

Close the owner you created

Ownership flows downward:

  • closing a context closes its pages;
  • closing a browser closes its contexts;
  • closing the client disconnects the bridge.

Use try/finally when your code creates the explicit runtime:

php
$client = PlaywrightFactory::create();

try {
    $browser = $client->chromium()->launch();
    $context = $browser->newContext();
    $page = $context->newPage();
    // Work with the page.
} finally {
    $client->close();
}

For PHPUnit, centralize this lifecycle in the provided testing helpers instead of rebuilding it in every test.

Choose the right level

Need Work with
A new isolated user Browser context
Another tab in the same session Page
Content inside an iframe Frame locator
A resilient element target Locator
Observe one HTTP exchange Request and response
Modify browser traffic Route
Configure or supervise the runtime Client and browser

Go next

  • Browser for user-facing browser, context, page, and locator guidance.
  • Events for console, dialogs, errors, popups, and network events.
  • Transport for the process boundary behind these objects.