ScreenshotNeo

BlogGuides

Playwright Framework: Getting Started with Browser Testing

Install Playwright Test, write a meaningful browser test, run and debug it locally, and add a basic CI job with practical troubleshooting.

By the ScreenshotNeo team4 October 20269 min read

Playwright Test is an end-to-end testing framework for browser-based applications. It includes a test runner, assertions, isolated test environments, parallel execution, and debugging tools. With npm, start with npm init playwright@latest, install the matching browser binaries, write a test using the page fixture and user-facing locators, then run it with npx playwright test.

This guide takes you from setup to a first meaningful test, explains locator and assertion behavior, shows local debugging and a basic CI workflow, and covers common setup failures. The examples use TypeScript and npm. For version-specific Node.js and operating system requirements, check the official installation guide when you set up the project.

1. Install Playwright Test

In the root of your application or test project, run:

npm init playwright@latest

The setup wizard can create a new project or add Playwright to an existing one. Follow the prompts to choose JavaScript or TypeScript, select a tests directory, and decide whether to add a CI workflow. Keep the generated configuration and example test at first: they give you a working reference for the installed version.

For an existing npm project, the wizard adds the Playwright Test package and configuration. Commit the resulting lockfile so local and CI installs use the same dependency versions. Other package managers are supported; the official installation guide lists their current commands.

2. Install the browsers Playwright uses

Playwright uses browser binaries matched to its installed version. Install the default browser set with:

npx playwright install

The core browser engines are Chromium, Firefox, and WebKit. A test suite can run against one or more of them. Broader engine coverage can catch browser-specific behavior, while each additional project adds execution time. There is no single browser matrix that suits every application.

For Linux CI runners that need operating-system packages as well as browser binaries, install both with:

npx playwright install --with-deps

When you update the Playwright package, its required browser builds may change. If a browser launch reports that an executable is missing, reinstall the browsers with the Playwright CLI. Playwright also documents branded Chrome and Edge channels and device emulation for narrower compatibility checks; consult the browser documentation for current options.

3. Write your first meaningful test

Create tests/get-started.spec.ts (or use the test directory selected by setup) with this example:

import { test, expect } from '@playwright/test';

test('get started link opens installation page', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  await page.getByRole('link', { name: 'Get started' }).click();
  await expect(
    page.getByRole('heading', { name: 'Installation' })
  ).toBeVisible();
});

The test follows the same pattern you can apply to your own product: go to a page, interact as a user would, and assert a visible result.

  1. test(...) declares a test case with a descriptive name.
  2. async ({ page }) => { ... } asks Playwright Test to provide its built-in page fixture.
  3. page.goto(...) navigates to the starting URL.
  4. getByRole('link', { name: 'Get started' }) locates a link by its accessible role and name.
  5. click() performs the user action.
  6. expect(...).toBeVisible() checks that the destination state appears.

A meaningful application test should verify an outcome that matters, such as a submitted form showing a confirmation, a saved item appearing in a list, or an invalid value producing an error message. Merely checking that a page loaded does not verify the behavior the user came for.

4. Choose robust locators and assertions

Prefer locators that describe the interface as a user experiences it. Common choices include:

Locator Useful when Example
Role and accessible name Finding buttons, links, headings, and other accessible controls page.getByRole('button', { name: 'Save' })
Label Finding a form field by its associated label page.getByLabel('Email address')
Placeholder Finding a field identified by placeholder text page.getByPlaceholder('Search')
Text Finding visible text when that text identifies the target clearly page.getByText('Order received')
Test ID Using an explicit testing contract maintained by the application team page.getByTestId('cart-count')

Role and label locators often reveal accessibility gaps as well as test failures: if a control has no useful accessible name, consider improving the interface. Use a test ID when it is useful to give an element a stable selector that does not depend on copy or presentation. Avoid long chains of CSS classes tied to implementation details unless that is the deliberate contract.

Locators are resolved when an action or assertion uses them. Playwright can wait for an element to become actionable, and web-first assertions retry while waiting for the expected state. For example:

const saveButton = page.getByRole('button', { name: 'Save' });
await saveButton.click();
await expect(page.getByText('Changes saved')).toBeVisible();
await expect(page).toHaveTitle(/Settings/);

Use awaited assertions such as toBeVisible() and toHaveTitle() to express the condition you expect. Avoid using a fixed sleep as the usual synchronization strategy: a short delay may be insufficient on a slow run and waste time on a fast one. If a particular application state matters, wait for that state with a locator or assertion.

5. Understand test isolation and fixtures

The built-in page fixture is backed by a browser context that gives a test an isolated browser environment. A context resembles a fresh browser profile, so a test should not depend on cookies, local storage, or page state created by a different test. This isolation helps tests run independently and makes failures easier to reproduce.

Fixtures provide the environment a test needs. Start with the built-in fixtures. Add a custom fixture when repeated setup or shared test behavior makes the suite easier to maintain, rather than creating abstraction for a single test.

Isolation does not automatically reset state held by your application server or external services. If a test creates a user or record on the server, arrange for unique test data or cleanup so reruns and parallel tests do not collide.

6. Run tests locally

Run all configured tests with:

npx playwright test

Tests run headlessly by default. To watch the browser while a test runs, use:

npx playwright test --headed

For interactive test selection and inspection, use UI Mode:

npx playwright test --ui

After a run, open the HTML report with:

npx playwright show-report

Use the mode that answers the question you have: headless execution is convenient for routine feedback, headed mode makes browser behavior visible, and UI Mode helps you select and inspect runs interactively. The test-running guide documents current CLI options.

7. Add a basic CI job

A CI run needs the project dependencies and the browser binaries before it can execute tests. For an npm project, the basic sequence is:

  1. Check out the repository.
  2. Set up a Node.js version supported by the installed Playwright release.
  3. Install the lockfile-pinned dependencies with npm ci.
  4. Install Playwright browsers and, on Linux where needed, their system dependencies.
  5. Run npx playwright test.

For example, the shell commands within a CI job are:

npm ci
npx playwright install --with-deps
npx playwright test

The exact workflow syntax depends on your CI provider; use its current checkout and runtime setup actions. Playwright’s CI guide recommends one worker as a stable default in CI. You can consider parallel workers or sharding when your runner capacity and test data setup support them. Browser caching is not always worthwhile, especially when Linux system dependencies still need installation.

8. Troubleshoot common problems

Symptom Likely cause Fix
Browser executable is missing The browser binaries for this Playwright package version were not installed, or the package was updated afterward. Run npx playwright install; on Linux CI, use npx playwright install --with-deps.
A locator times out The target did not appear, the locator does not match the current accessible name or role, or the page did not reach the expected state. Check the locator against the rendered page, confirm the expected state and test data, and prefer a role or label locator that matches the actual interface.
Click fails because the element is not actionable The element may be hidden, covered, disabled, or still moving. Confirm that the intended control is visible and enabled, and that overlays or animations have settled. Use the user-facing locator for the actual control.
Works locally, fails in CI CI may lack browser system dependencies, use different environment configuration, or expose a race in test data or application readiness. Install browsers with --with-deps on Linux, verify runtime and environment settings, and wait for the meaningful application state rather than adding a guessed delay.
Tests fail when run together but pass individually Tests may share server-side records or rely on state from another test. Make test data independent, reset state where appropriate, and do not rely on test ordering.
Several tests run against the wrong URL or configuration The test configuration may define a base URL or projects that differ from the assumption in the test. Review the generated Playwright configuration and use the configured project and application URL consistently.
Intermittent failures after a page transition The test may assert before the application has reached the expected state. Use a web-first assertion on the destination element or page state. Avoid fixed sleeps as the default fix.

When a failure is unclear, first determine whether it is a browser launch problem, a locator/action problem, an assertion failure, or an application/test-data problem. Headed mode and UI Mode can help narrow that down without changing the test’s intended behavior.

9. Browser coverage, performance, and reliability

Chromium, Firefox, and WebKit cover distinct browser engines. Running against multiple engines is useful when browser-specific compatibility is part of your risk, but it increases the number of executions. Branded Chrome or Edge channels and emulated devices answer more specific compatibility questions; they do not replace a deliberate choice of which engines and environments your users need you to cover.

Keep the initial suite focused on important user flows. Add engines or projects when the additional coverage is useful to the application. In CI, one worker is the documented stable starting point; increase parallelism only when infrastructure and test data can handle concurrent runs. Isolation helps prevent browser state from leaking between tests, but it cannot prevent collisions in shared backend data.

There is no universal execution-time or cost figure for a Playwright suite: it depends on the tests, browsers, runner, and CI configuration. The practical tradeoff is straightforward: each additional browser project or shard needs execution capacity, while a narrow suite returns faster feedback. Prefer assertions on application state over arbitrary waits to avoid needless delays and timing assumptions.

Or skip the browser setup

If your immediate need is a screenshot rather than an interactive browser test, ScreenshotNeo provides a website screenshot API and MCP server. A single GET request can return a PNG, JPEG, WebP, or PDF. For example, save a WebP screenshot with cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for request options. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000.

Sign up free for 1,000 screenshots a month, with no card required.

FAQ

Is Playwright Test the same thing as a browser?

No. Playwright Test is the test framework and runner; it installs and runs browser binaries to test web applications.

Do I need to write a test for every browser?

No. Choose browser projects based on the compatibility coverage your application needs. Chromium, Firefox, and WebKit are the core engines Playwright supports.

Can Playwright take screenshots?

Playwright is used here for browser testing. If you need a standalone website screenshot through an API or an MCP tool for an AI agent, ScreenshotNeo is an alternative described above.

Should I use a fixed timeout to make a flaky test pass?

Usually, no. Prefer an assertion or locator action that waits for the state or actionability the test requires, then investigate whether the application or test data is inconsistent.