How to Run Playwright Tests
Run Playwright tests from install to CI, debug failures, select browsers, filter tests, and read HTML reports with practical commands.
Use npx playwright test to run the configured Playwright test suite. It runs tests headlessly and in parallel by default. Before the first run, install the Playwright test package and the browser binaries:
npm init playwright@latest
npx playwright install
npx playwright test
Playwright’s generated configuration controls browsers, projects, timeouts, retries, reporters, and other execution settings. Playwright supports Windows, macOS, and Linux, both locally and in CI. The official installation guide describes the package as including the test runner, assertions, isolation, parallelization, and tooling.
Sources: installation and introduction, running and debugging tests.
1. Install Playwright and its browsers
Start a new project
npm init playwright@latest
The setup wizard creates example tests, a Playwright configuration file, and the required package scripts. Accept the TypeScript or JavaScript choice that matches your project.
Add Playwright to an existing project
npm install --save-dev @playwright/test
npx playwright install
Run npx playwright install after upgrading Playwright as well. Each Playwright version requires specific browser binary versions.
Install browsers selectively
npx playwright install chromium
npx playwright install firefox webkit
On Linux CI machines, install operating-system dependencies with:
npx playwright install-deps
npx playwright install --with-deps chromium
The second command installs Chromium and its required system packages together. A headless-shell-only installation can reduce CI downloads when a full browser channel is unnecessary. See the browser installation guide.
2. Write a runnable test
A minimal TypeScript test uses a page fixture, navigates to a URL, and asserts a user-visible result:
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveTitle(/Example Domain/);
});
Save it as tests/example.spec.ts, then run:
npx playwright test tests/example.spec.ts
Prefer role- and label-based locators and web-first assertions. They wait for the expected condition and express what a user can observe:
import { test, expect } from '@playwright/test';
test('user can add a todo', async ({ page }) => {
await page.goto('https://example.com/todos');
await page.getByRole('textbox', { name: 'New todo' }).fill('Buy milk');
await page.getByRole('button', { name: 'Add' }).click();
await expect(page.getByRole('listitem')).toContainText('Buy milk');
});
Each test receives an isolated BrowserContext, so cookies, local storage, and other browser state do not leak between tests.
3. Run all tests
npx playwright test
With no file or filter arguments, Playwright runs every test matched by the configuration. Tests run in parallel by default and in headless mode, so no browser window opens and results are printed in the terminal.
Useful execution controls include:
# Run serially
npx playwright test --workers=1
# Retry failed tests (for example, twice)
npx playwright test --retries=2
# Stop after a failure limit
npx playwright test --max-failures=1
# Run a shard in CI
npx playwright test --shard=3/5
Retries and sharding change execution; they do not repair a flaky test. Review the report and failure artifacts before increasing retries.
4. Run a subset of tests
Use the narrowest filter that answers your question:
# One file
npx playwright test tests/example.spec.ts
# Multiple files or directories
npx playwright test tests/todo-page/ tests/landing-page/
# Filename keywords
npx playwright test landing login
# Test title or regular expression
npx playwright test -g "add a todo item"
# Tests that failed in the previous run
npx playwright test --last-failed
# A test at a source line
npx playwright test my-spec.ts:42
Path filters are resolved against the test files selected by the project configuration. If a title pattern contains shell metacharacters, quote it.
5. Choose a browser, device, or project
Projects let one test body run against different engines, branded browsers, or device profiles. A typical configuration looks like this:
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
timeout: 30_000,
retries: process.env.CI ? 2 : 0,
reporter: [['html', { open: 'never' }]],
use: {
baseURL: 'http://127.0.0.1:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure'
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
{ name: 'mobile-chrome', use: { ...devices['Pixel 5'] } }
]
});
Run every configured project with:
npx playwright test
Select one or more projects with:
npx playwright test --project=chromium
npx playwright test --project=firefox --project=webkit
npx playwright test --project=mobile-chrome tests/example.spec.ts
Playwright documents Chromium, Firefox, WebKit, branded Chrome and Edge channels, and emulated mobile devices. Keep assertions the same across projects so browser differences remain visible.
6. Run headed, UI, and debug modes
Headed mode
npx playwright test --headed
Headed mode opens the browser while retaining normal test execution.
UI Mode
npx playwright test --ui
UI Mode provides an interactive test list, step timeline, trace details, and a way to rerun individual tests. It is useful when you need to see what happened before, during, and after each action.
Inspector debugging
npx playwright test example.spec.ts:10 --debug
The Inspector pauses execution, shows debug logs, and helps explore locators. You can also add a breakpoint in code:
await page.pause();
Remove pauses before committing a test. For repeatable failure analysis, enable traces, screenshots, and videos in the project configuration rather than leaving every run in debug mode.
7. Read the HTML report
npx playwright show-report
The HTML Reporter lets you filter and search by browser, passed or failed state, skipped tests, flaky tests, errors, and individual steps. If the report is on a different port:
npx playwright show-report --port 9324
In CI, publish the report and trace artifacts from the configured output directory. A failure should be investigated with its error, trace, screenshot, network context, and browser project together.
8. Run tests against a local web server
Use the webServer setting so Playwright starts your application before tests and stops it afterward:
import { defineConfig } from '@playwright/test';
export default defineConfig({
webServer: {
command: 'npm run dev',
url: 'http://127.0.0.1:3000',
reuseExistingServer: !process.env.CI
},
use: {
baseURL: 'http://127.0.0.1:3000'
}
});
Then navigate with a relative path:
await page.goto('/login');
Make the server command deterministic and ensure the URL is reachable from the same environment that runs the browser.
9. CI execution
A reliable CI run normally installs exact dependencies, installs browser binaries, runs headless tests, and stores reports and artifacts:
npm ci
npx playwright install --with-deps chromium
npx playwright test
Use multiple projects when browser coverage matters. Use --workers=1 when a shared test environment cannot safely handle parallel sessions. Use retries sparingly and inspect flaky results instead of treating retries as a pass condition.
10. Troubleshooting common failures
| Symptom | Cause | Fix |
|---|---|---|
| Executable doesn’t exist | Browser binaries are missing or belong to another Playwright version. | Run npx playwright install after installing or upgrading @playwright/test. |
| Linux launch or shared-library error | CI image lacks browser system dependencies. | Run npx playwright install --with-deps chromium or install dependencies with npx playwright install-deps. |
| No tests found | File naming, directory, project, or grep filters exclude the test. | Check testDir, use a *.spec.ts or *.test.ts filename, and remove filters temporarily. |
| Test times out waiting for a locator | The locator is wrong, the page is not ready, or a navigation failed. | Use a role or label locator, inspect the trace, verify the URL, and wait for a meaningful web-first assertion instead of a fixed sleep. |
| Works headed but fails headless | Timing, viewport, missing dependency, or headless-only environment differences. | Reproduce with --headed, inspect trace and console output, then fix synchronization or environment setup. |
| Flaky test passes on retry | Race condition, unstable data, shared state, or external dependency. | Use isolated fixtures, deterministic test data, locator-based waits, and trace-on-first-retry; keep the test visible as flaky. |
| Web server never becomes ready | The command exits, binds another host, or the configured URL is wrong. | Run the command locally, bind to 127.0.0.1, and make webServer.url match the actual address. |
| Report is empty or unavailable | The reporter was not enabled, artifacts were discarded, or the wrong directory was opened. | Configure the HTML reporter, preserve the output directory in CI, and run npx playwright show-report. |
11. Reliability and performance practices
- Keep tests independent so parallel workers can run safely.
- Use locators and web-first assertions rather than arbitrary sleeps.
- Control data and external services with fixtures or mocks where appropriate.
- Set explicit timeouts for genuinely slow operations, but fix synchronization before raising global timeouts.
- Run Chromium, Firefox, and WebKit in separate projects when cross-engine coverage is required.
- Use sharding to distribute large suites across CI jobs, and keep each shard’s artifacts.
- Capture traces on the first retry, screenshots only on failure, and videos only when needed to limit storage and runtime.
- Pin dependency versions with a lockfile and reinstall matching browser binaries after upgrades.
12. Or skip the browser setup
If your goal is to capture a page image during a test or build workflow, ScreenshotNeo provides a website screenshot API without managing Playwright browsers. Cookie banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.
See the ScreenshotNeo API documentation for all options.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
const data = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', data));
ScreenshotNeo supports full-page and element captures, dark mode, device presets, custom viewports, retina scale, PDF output, custom CSS and JavaScript, clicks, waits, blocked requests, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, caching, signed links, asynchronous jobs, webhooks, bulk capture, usage reporting, and an OpenAPI specification. Parameter names used by other screenshot APIs also work.
Plans include 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
13. Cost and resource planning
Playwright itself is an open-source test framework, but your costs come from CI minutes, browser workers, artifact storage, and any hosted test infrastructure. Parallel workers reduce wall-clock time while increasing CPU and memory use. Sharding reduces time for large suites but requires more CI jobs and artifact management. Retaining videos and traces for every test can grow storage quickly, so keep them for failures or selected retries.
For page snapshots where browser installation and CI maintenance are unnecessary, ScreenshotNeo charges only for clean shots. Its plans are Free: 1,000 shots/month; Starter: $5 for 3,000; Growth: $15 for 15,000; Pro: $39 for 60,000; Scale: $99 for 250,000; and Business: $249 for 1,000,000. Yearly billing gives two months free, and every feature is included on every plan.
FAQ
What command runs all Playwright tests?
npx playwright test runs all tests selected by the configuration.
How do I run only Chromium?
Use npx playwright test --project=chromium when the configuration defines a project named chromium.
How can I see the browser?
Run npx playwright test --headed, or use --ui for an interactive runner.
How do I rerun only failures?
Run npx playwright test --last-failed.
Why must I install browsers after upgrading Playwright?
Each Playwright version needs specific browser binary versions, so rerun npx playwright install.
Where do I inspect a failed test?
Open the HTML report with npx playwright show-report, then inspect the error, steps, trace, screenshot, and project details.


