ScreenshotNeo

BlogHow-to

How to Update Playwright Visual Snapshots Without Hiding Unintended Changes

Refresh Playwright screenshot baselines without approving regressions. Diagnose failures first, update only intended changes, and review every diff before committing.

By the ScreenshotNeo team4 October 20266 min read

Update Playwright visual snapshots safely by first running tests without update mode, investigating every failure, and deciding whether each visual change is intentional. Then update only the affected baselines, inspect the expected, actual, and diff images alongside the application code, and commit reviewed snapshots with the code change. Updating a baseline changes what the test expects; it does not prove the new appearance is correct.

1. Run tests normally and diagnose the failure

Start with the existing expectations intact. Run the relevant test or project without --update-snapshots so Playwright reports mismatches instead of replacing the evidence.

npx playwright test path/to/example.spec.ts

For a particular project, add its configured project name:

npx playwright test path/to/example.spec.ts --project=chromium

Inspect the failing test and the expected, actual, and diff images. Check the application change that produced the screenshot: was a layout, color, font, or content change intended? Can you explain the changed pixels from the code or product requirement? If not, treat the mismatch as an unresolved failure. Do not update the reference merely to make the test pass.

Playwright’s screenshot assertion waits for consecutive screenshots to stabilize, and animations are disabled by default. These reduce capture noise, but they cannot decide whether an observed change is a product improvement or a regression. See the Playwright visual comparisons guide and PageAssertions API.

2. Choose the narrowest snapshot update mode

After confirming that a difference is expected, rerun with an explicit update mode. The current Playwright CLI documents these modes:

Mode Effect Use when
changed Updates snapshots that differ from the current output. You reviewed the failures and want to refresh only changed baselines.
all Updates all snapshots in the selected test run. You intentionally need to regenerate every baseline in that scope and can review the larger diff.
missing Creates missing snapshots without refreshing existing ones. A new test or configuration needs its first reference image.
none Prevents snapshot updates. You want an explicit no-update setting in a command or script.
npx playwright test path/to/example.spec.ts --update-snapshots=changed

Use the same project selection when updating a project-specific baseline:

npx playwright test path/to/example.spec.ts --project=chromium --update-snapshots=changed

Update mode defaults and behavior can vary by Playwright version. Check the installed version and its CLI help before relying on a mode in a script; explicit options make the command’s scope clearer and more reproducible. The Playwright command-line documentation and release notes describe current and versioned behavior.

3. Review the generated baselines before committing

  1. Inspect each changed snapshot’s expected, actual, and diff images.
  2. Confirm that the visual change matches the intended application change and that nearby layout, text, and controls remain correct.
  3. Review the related source code and test changes. A plausible screenshot does not rule out a functional regression.
  4. Check that the changed files belong to the intended test and project; investigate unexpected snapshot churn.
  5. Commit the reviewed snapshot files with the application change so the expectation and implementation stay together.

Playwright’s Trace Viewer can help inspect screenshot comparisons and test context, including browser and viewport information. Snapshot files are test expectations maintained in version control, so review their diff as part of the change.

4. Keep screenshot comparisons sensitive to real regressions

Control the rendering environment

Screenshot output can vary with the operating system, browser version, browser settings, hardware, power conditions, and headless mode. Generate and verify baselines in a consistent environment where practical. When comparing failures, consider the browser project and viewport before deciding that the application changed.

Set tolerances narrowly

threshold, maxDiffPixels, and maxDiffPixelRatio allow some visual difference. A larger tolerance can make genuine regressions pass. Use a narrow allowance only for an identified source of rendering noise, and inspect the affected region rather than increasing tolerance until the test is green. See the screenshot assertion options for the available settings and defaults.

Mask only truly volatile details

Screenshot assertions support locator masks and a stylePath stylesheet for content that cannot be made deterministic. Broad masks or styles can conceal layout and content problems. Target the smallest volatile value or region, document why it is excluded, and retain visibility of meaningful surrounding content. Styles can affect shadow DOM and frames, so check the scope of the rule you add.

5. Troubleshooting

Symptom Likely cause What to do
Update mode appears to refresh more or fewer files than expected The selected mode, test scope, project, or installed Playwright version differs from your assumption. Check the version and CLI help; pass an explicit mode and project, then inspect the complete changed-file list.
Snapshots change across machines or CI runs Rendering environment differences such as OS, browser version, settings, hardware, or headless mode. Compare in a consistent environment and verify browser/project and viewport context before refreshing references.
A diff contains a large region after a small code change A genuine layout or styling side effect, changed viewport, or environment drift. Inspect actual and diff images, confirm the test configuration, and trace the affected styles and application code before updating.
Dynamic content makes screenshots flaky Uncontrolled timestamps, rotating content, animation, or other volatile details. Make the test data deterministic where possible; otherwise mask a narrowly scoped element or use a focused stylePath rule.
A test passes after increasing a tolerance, but the page looks wrong The tolerance is broad enough to accept a meaningful visual change. Reduce the tolerance and investigate the changed area. Do not use thresholds as a substitute for reviewing the intended design change.
A test fails even though the baseline looks right locally The test may run with a different project, viewport, browser, or rendering environment. Compare the failing run’s metadata and environment with the baseline-generation environment before replacing snapshots.

6. Performance, reliability, and maintenance

Updating only changed snapshots keeps the review focused; updating all snapshots creates a larger review burden and can obscure unrelated changes. Keep test selection and project scope as narrow as the intended application change. Stable inputs and a consistent rendering environment reduce noisy diffs, while explicit update modes make maintenance commands easier to reason about.

Keep snapshot updates in the same change as the UI code they represent, and review the image artifacts as well as the text diff. Playwright’s stabilization and animation handling improve repeatability, but visual review remains necessary for correctness.

7. Or skip the browser setup

For a standalone capture of a deployed page, ScreenshotNeo provides a website screenshot API and MCP server. It is not a replacement for Playwright’s in-test snapshot assertions; it can provide a screenshot without setting up a browser capture script. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
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 Bun.write('shot.webp', res);

ScreenshotNeo accepts and removes cookie or consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

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

FAQ

Should I update snapshots in CI?

Update mode changes expectations. Keep ordinary verification runs in comparison mode, and review baseline changes as deliberate code changes.

Does a stable screenshot mean the change is safe?

No. Stability makes captures more repeatable; it does not judge whether the resulting interface is correct.

Should I commit Playwright snapshot files?

Yes. They are the references used by the tests, and Playwright’s visual comparison guidance recommends reviewing and committing them in version control.