What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Use Playwright Test’s expect(page).toHaveScreenshot() to compare a page with a reviewed reference image, or expect(locator).toHaveScreenshot() to compare just one component. The first run creates the reference; later runs compare new renders against it. Reliable screenshot diffing depends less on taking an image than on making the page state and rendering environment repeatable, setting a measured tolerance, and reviewing changes before updating the reference.

How Playwright screenshot diffing works

Visual regression testing checks whether a rendered page or component has changed in a way that matters. Playwright Test’s screenshot assertions capture the current render and compare it with an expected image stored alongside your tests. On the first run, the expected image does not exist, so Playwright creates it. On later runs, a mismatch fails the assertion and produces images you can inspect.

Use the page assertion when the overall page is the subject of the test. Use the locator assertion when the important contract is a particular element, such as a navigation bar, pricing card, or dialog. These screenshot assertions belong to the Playwright Test runner; they are not a generic image-diff method for arbitrary scripts.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Playwright waits for two consecutive screenshot captures to match before comparing the final capture with the reference. This helps with transient rendering, but it cannot make changing data, external content, or unpredictable application state deterministic.

Write a visual regression test

The following TypeScript example assumes a Playwright Test project and a page in your application at /pricing. Replace the path and any test setup with the route and state your application needs.

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

test('pricing page matches its visual reference', async ({ page }) => {
  await page.goto('/pricing');
  await expect(page).toHaveScreenshot('pricing-page.png');
});

For a focused comparison, target a locator instead:

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

test('primary plan card matches its visual reference', async ({ page }) => {
  await page.goto('/pricing');
  const card = page.getByTestId('plan-card-primary');
  await expect(card).toHaveScreenshot('primary-plan-card.png');
});

Run the test with your project’s normal Playwright Test command, for example npx playwright test. If the reference is missing, the run creates it; inspect the resulting image and commit it with the test. Snapshot names and locations are associated with test identity and project context, and can be configured, so use a stable, descriptive name and keep the generated snapshot directory in version control.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Create and maintain trustworthy baselines

Generate the first reference deliberately

  1. Choose a page or component state that matters to users and that your test can reproduce.
  2. Run the test to create the missing reference image.
  3. Open the image and confirm it represents the intended state, viewport, and content.
  4. Commit the test and reference image together so future runs compare against the same reviewed expectation.

Review changes before updating

When an assertion fails, inspect the expected image, actual image, and generated difference image. Decide whether the rendering change is a defect or an intentional design change. For an intentional update, run npx playwright test --update-snapshots, review the new image, and include it in the same code review as the change that caused it. Updating references without inspection turns a regression check into a mechanism for accepting whatever rendered.

Make screenshot captures repeatable

Visual output can vary with the host operating system, browser version, settings, hardware, power source, and headless mode. Match the operating system and browser versions used to establish your baseline, especially when comparing images in CI. A baseline created on one environment may differ from a render on another even when the application code is unchanged.

  • Control visible data: use stable fixtures or controlled network responses for content that affects the screenshot. Avoid live timestamps, randomized values, changing advertisements, and third-party content where practical.
  • Wait for the right state: navigate to the actual state under test and wait for relevant content or application conditions. The assertion’s consecutive-capture settling behavior is helpful, but it does not replace deterministic test data.
  • Keep the pointer out of the way: move it away from hover-sensitive controls before capture if hover styling is not what the test intends to exercise.
  • Suppress transient elements selectively: use the screenshot assertion’s stylePath option to hide volatile elements, such as a rotating promotion or live clock. Its stylesheet can pierce Shadow DOM and inner frames. Avoid hiding the UI whose correctness you are trying to test.
  • Use animation handling intentionally: screenshot assertions disable animations by default. If the animation itself is under test, account for that behavior rather than assuming the screenshot captures an arbitrary frame.
  • Keep capture scale consistent: the assertion can capture in CSS-pixel or device-pixel scale. Device-pixel images can be larger on high-DPI settings. Use the same choice for baselines and later runs.

PNG is the default screenshot format. A snapshot name ending in .webp can use WebP; Playwright documents both PNG and WebP as lossless for assertion snapshots. Do not change formats or capture scale casually after baselines have been established, because the comparison target itself will change.

Set a meaningful difference tolerance

Playwright uses pixelmatch for visual comparisons. Its threshold controls the acceptable perceived color difference for an individual pixel, in YIQ color space; the documented default is 0.2. That value does not mean that 20% of the image may differ. Larger threshold values allow more per-pixel color variation to be treated as a match.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Separate options bound how many pixels may differ overall:

  • maxDiffPixels sets an absolute limit on the number of differing pixels.
  • maxDiffPixelRatio sets a limit on the proportion of differing pixels.

For example, a test can set a small absolute allowance while keeping the per-pixel threshold deliberate:

await expect(page).toHaveScreenshot('dashboard.png', {
  threshold: 0.2,
  maxDiffPixels: 25,
});

This is an example configuration, not a universal recommended tolerance. Choose values after inspecting the kinds of rendering variation your environment produces. If a test repeatedly fails on irrelevant noise, first stabilize the page and environment or hide only genuinely volatile content. Raising thresholds broadly can also make meaningful visual regressions pass.

Run screenshot tests reliably in CI

Install Playwright’s required browsers and operating-system dependencies in the CI environment, then run the same test suite against a predictable browser and platform setup. Playwright’s CI guidance recommends one worker in CI for stability and reproducibility; sharding can increase throughput across multiple jobs. Containers can also help keep visual-regression environments consistent. If you choose parallel workers on a capable self-hosted machine, verify that the parallel configuration does not introduce resource contention or unstable rendering.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep test reports and relevant screenshot artifacts when a run fails so reviewers can inspect the expected, actual, and diff images. Treat snapshot updates as code changes: the reviewer should be able to see what the test now accepts, not just that a command regenerated files.

Common Playwright screenshot-diff failures

The first run fails because a snapshot is missing

This is the baseline-creation step, not evidence that the page failed visually. Run the test to generate the reference, inspect the image, and commit it. If it was generated under an unintended project or environment, correct that setup before establishing the baseline.

The test fails intermittently with small differences

Look for changing content, animations, hover state, asynchronous updates, or environment differences. Stabilize test data and timing, move the pointer away when appropriate, use the built-in animation handling, and consider a narrowly scoped stylePath rule for irrelevant volatile elements. Do not start by increasing tolerance without identifying the source of the variation.

The diff is large after a browser or machine change

Check the operating system, browser version, headless mode, and capture scale against the environment that produced the baseline. Make the environments consistent where possible. If the environment change is deliberate, regenerate and review references as a coordinated update rather than accepting unexplained differences piecemeal.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

An intentional UI change keeps failing

Inspect the actual render first. If it is the new approved design, update references with npx playwright test --update-snapshots and review the resulting images. If the render is not intended, fix the application or test state instead of replacing the reference.

A test passes despite a visible mismatch

Review the configured threshold, maxDiffPixels, and maxDiffPixelRatio. A permissive per-pixel threshold can ignore color changes, while generous pixel-count limits can allow broad changed areas. Tighten the relevant limit and reduce capture noise rather than assuming a passing assertion means every visual change is harmless.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When to use hosted visual-testing services

Playwright’s built-in assertions are a practical starting point when your team wants reference images in its repository, direct integration with Playwright Test, and control over comparison settings. Hosted products may suit teams that need a different baseline-review or browser-coverage workflow, but their documented capabilities do not establish independent comparative quality or pricing here.

  • Applitools Eyes for Playwright: its documentation describes integration into existing Playwright tests, visual checkpoints, hosted baselines, and cross-browser rendering through its service.
  • Chromatic for Playwright: its documentation describes a Playwright integration that captures pages and related assets for cloud comparison and a hosted visual-review workflow.

Before choosing a hosted service, compare the comparison approach, local versus hosted baseline management, browser and viewport coverage, approval workflow, CI integration, and current pricing directly with the vendor. If local reference images and manual review fit your team, adding a service is not a prerequisite for screenshot diffing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Or skip the browser setup

If you need a screenshot capture rather than an in-test baseline assertion, ScreenshotNeo can return a page image with one GET request. It is a capture API and MCP server; it does not replace Playwright’s reference-image comparison assertion. Cookie and consent banners, newsletter popups, and chat widgets are removed before capture by default, with each step configurable. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify page verdict and billing status in headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for AI agents.

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

For other supported options and setup details, see the ScreenshotNeo API documentation. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up for ScreenshotNeo’s free plan to try it.

Frequently Asked Questions

Can I use `toHaveScreenshot()` outside Playwright Test?

No. Playwright’s screenshot assertion is part of the Playwright Test runner; use a separate image-comparison approach if you need a standalone script.

Does `threshold: 0.2` mean 20% of the screenshot may change?

No. It is the documented pixelmatch default for per-pixel perceived color difference in YIQ space; aggregate difference is controlled separately by `maxDiffPixels` or `maxDiffPixelRatio`.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can ScreenshotNeo replace Playwright visual regression assertions?

No. ScreenshotNeo captures images through an API, while `toHaveScreenshot()` compares a Playwright render with a stored reference.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.