ScreenshotNeo

BlogGuides

How to Run Fast Cross-Browser Tests With Playwright

Configure Playwright projects for Chromium, Firefox, and WebKit, then tune workers, sharding, and test isolation to improve CI speed without sacrificing reliable results.

By the ScreenshotNeo team4 October 20268 min read

Use Playwright projects to run the same test suite against Chromium, Firefox, and WebKit. For faster runs, start with a stable worker count, isolate test data, and use CI sharding when you can add machines. Run a single project while developing a browser-specific change, but keep the full browser matrix in the checks that protect compatibility.

This guide configures a TypeScript Playwright Test suite, explains parallelism and sharding, and covers setup, debugging, reliability, and common CI failures.

1. Configure a cross-browser project matrix

Projects are named configurations. A project can specify a browser engine, device profile, or browser channel; the same test files can run under each configuration. The example below defines the three major engines. See the official projects guide and browser documentation.

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 1 : 0,
  // A stable starting point for CI; tune after measuring your own suite.
  workers: process.env.CI ? 1 : undefined,
  reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list',
  use: {
    baseURL: process.env.BASE_URL ?? 'http://127.0.0.1:3000',
    trace: 'on-first-retry',
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit', use: { ...devices['Desktop Safari'] } },
  ],
});

Install the test package and browser binaries, then run the matrix:

npm init playwright@latest
npx playwright install
npx playwright test

For a smaller install in a Linux CI image, install only the engines the configured job needs. For example, if a job runs Chromium alone, use npx playwright install chromium. Keep the package version and browser binaries aligned; install browsers again when updating Playwright. The official best practices cover browser installation and CI setup.

Run one project during focused development

npx playwright test --project=webkit
npx playwright test --project=chromium

Use the full configured matrix for compatibility coverage. A targeted project is a feedback-loop shortcut, not a replacement for the other browsers in your intended release checks.

Use the same tests where behavior should match

Keep functional tests shared across projects when the feature should behave the same in each engine. Add project-specific tests only for behavior that actually differs, such as a browser-specific interaction or a device layout. Projects can also represent mobile device emulation or branded browser channels; check Playwright’s project and browser documentation for the configuration supported by the installed version.

2. Make parallel execution faster without making it flaky

Playwright runs test files in parallel by default, while tests inside a file run in order by default. The worker setting limits parallel workers. fullyParallel: true lets Playwright schedule individual tests more flexibly, which can help when a few files contain much more work than others. Read Playwright parallelism and the TestConfig API reference for the behavior and options in your version.

The API’s default worker count is half the logical CPU cores, while Playwright’s CI guidance recommends one worker in CI for reproducibility and stability. These address different priorities: the default offers local parallelism; a conservative CI baseline reduces contention and makes runs more predictable. One worker is guidance, not a universal performance optimum.

Choose a worker count by measurement

  1. Record the current suite duration and failure rate on a representative runner.
  2. Start CI with workers: 1 for a stable baseline.
  3. On a capable runner, raise the limit in small steps, for example --workers=2 and then --workers=4.
  4. Compare elapsed time, resource pressure, and retries or flaky failures. Keep the highest setting that improves throughput without destabilizing the suite.
# Limit this run to four workers
npx playwright test --workers=4

More workers can reduce elapsed time when there is spare CPU and memory. They can also make a run slower if browser processes compete for resources. The right value depends on the machine, suite shape, application, and test data.

Isolate shared state before adding concurrency

Each test gets a separate browser context, which isolates cookies and browser storage. It does not create a separate database, external account, queue, or output directory. Two parallel tests that update the same record or write to the same file can still race. See browser contexts and isolation.

  • Give each test unique backend records and clean them up safely.
  • Use unique filenames and per-test output paths.
  • Use worker-scoped fixtures only when sharing within a worker is intentional and safe.
  • Remove dependencies on test order; a test should establish its own preconditions.

fullyParallel is useful only when tests are independently runnable. If your suite depends on a sequence of mutations, first redesign or isolate that data instead of expecting a larger worker pool to make it safe.

3. Scale across CI machines with sharding

Workers add concurrency inside one runner. Sharding divides a suite into indexed partitions so separate CI jobs or machines can run parts of it. For a three-shard matrix, run one command in each of three jobs:

# CI job 1
npx playwright test --shard=1/3

# CI job 2
npx playwright test --shard=2/3

# CI job 3
npx playwright test --shard=3/3

Each job needs the same code, dependencies, browser installation, and compatible test environment. Configure your CI provider to start the three jobs and retain or merge reports and artifacts according to its workflow. See the official CLI reference and CI guide.

Sharding helps when additional machines provide additional capacity. It adds job startup and setup overhead, and it cannot make one constrained machine more powerful. Actual elapsed time depends on shard balance, setup costs, test duration variation, and runner contention; there is no guaranteed speedup.

Approach Where concurrency comes from Use it when Watch for
More workers Processes on one machine The runner has spare CPU and memory Resource contention and shared-data races
More shards Separate CI jobs or machines You can provision parallel agents and the suite is large enough to offset setup overhead Uneven partitions, artifact handling, duplicated setup
One project locally Less work in the run You are investigating one browser’s behavior Other engines receive no coverage in that run

4. Reduce setup and failure-diagnosis time

Install and cache only what the job uses

A job that runs only Chromium need not download Firefox and WebKit. Use the matching install command for the project’s browsers. In CI, cache browser downloads to avoid repeated fetches, and key that cache to the Playwright version so the binaries stay aligned with the package. Follow the provider-specific caching instructions and Playwright’s current CI documentation.

Capture traces on retry

The configuration above sets trace: 'on-first-retry', which collects a trace on the retry after a failure. Open it with the Trace Viewer to inspect actions, snapshots, and network activity. Tracing every passing test can add performance and storage overhead; retry-based capture keeps a useful failure artifact without collecting that artifact for every success. Consult the official best practices for current debugging guidance.

5. A practical CI checklist

  • Define explicit browser projects that match the compatibility you support.
  • Use the same test suite across engines for shared behavior.
  • Begin CI with one worker; raise it only after checking speed and stability on the actual runner.
  • Make backend records, accounts, and file paths safe for concurrent execution.
  • Use shards when separate machines are available and the suite is large enough to benefit.
  • Install only the browsers used by each job and cache downloads keyed to the Playwright version.
  • Keep traces on retry or another deliberate failure-focused policy.
  • Retain reports and traces from failed jobs so a fast run remains diagnosable.

6. Troubleshooting

Symptom Likely cause Fix
Browser executable is missing The installed Playwright package and browser binaries are out of sync, or that browser was not installed in the job. Run npx playwright install, or install just the configured engine, after installing the package version used by the job.
CI is slower after increasing workers Browser processes are competing for CPU or memory, or the app/server is saturated. Reduce --workers, inspect runner capacity, and compare duration and stability at each setting.
Failures appear only with parallel workers or shards Tests share database state, external accounts, filenames, or other mutable resources. Use unique test data and paths, make setup independent, and clean up per test or worker.
One shard takes much longer than the others Test durations or setup costs are uneven across partitions. Inspect per-test durations and suite composition; reduce expensive shared setup and adjust suite organization. Do not infer equal work from the shard count.
Trace files are absent for a failure The trace is configured for retry, but the test did not reach a retry or the CI job did not retain its artifacts. Confirm retry configuration and publish the Playwright output directory as a CI artifact. Temporarily choose a broader trace policy when diagnosing a specific issue.
Tests fail against a local server in CI The server is unavailable, the configured base URL is wrong, or startup has not completed before tests begin. Set BASE_URL to the reachable address and configure the CI job to start and wait for the application before invoking Playwright.
A browser-specific failure is hard to reproduce The local run uses a different project, browser version, or configuration from CI. Run npx playwright test --project=NAME with the same package, project, and browser installation as the failing job.

7. Or skip the browser setup

For a rendered page image, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. This does not replace interactive cross-browser tests: use it when you need page captures without managing browser automation yourself. See the ScreenshotNeo API documentation.

# 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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) => writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits cost nothing, and response headers identify the page verdict and whether the request was billed. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

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

8. FAQ

Should I run all three browser engines on every pull request?

That depends on the feedback time and compatibility risk you need to cover. Keep the full matrix in the checks that provide your release confidence; use focused project runs for local investigation or a deliberately staged CI strategy.

Does a new browser context make parallel tests fully independent?

No. It isolates browser state such as cookies and storage. Shared backend data, service accounts, and filesystem paths still need separate handling.

Can sharding replace workers?

They work at different levels: workers share a runner, while shards use separate jobs or machines. You can use both if resources and test isolation support the combined concurrency.

Is one worker always fastest in CI?

No. It is a stability-oriented baseline from Playwright’s CI guidance. Measure the actual suite on the actual runner before choosing a higher limit.