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.

Playwright has two screenshot workflows: automatic screenshots saved as test artifacts, and visual regression assertions that compare a fresh capture with an expected image. Set automatic capture in the Playwright Test configuration; use toHaveScreenshot() when a visual difference should fail the test. They solve different problems, and you can use both.

Choose the screenshot workflow you need

Workflow What it does Use it when
Automatic screenshot artifact Captures a screenshot according to the test runner’s configured policy. You want an image to inspect, especially when a test fails. It does not compare the image with a baseline.
Visual assertion Captures a page or locator and compares it with an expected snapshot; a mismatch can fail the test. You want to detect unintended visual changes over time.

These settings belong to Playwright Test. The examples use its configuration and runner APIs, not just the browser automation library. The documented behavior below reflects Playwright’s official documentation consulted on September 29, 2026; check the documentation for your installed version before relying on defaults.

Configure automatic screenshot artifacts

Set screenshot in the top-level use object to apply a policy across the configuration. The documented default is 'off'.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    screenshot: 'only-on-failure',
  },
});

The available string modes are:

  • 'off': do not take automatic screenshots.
  • 'on': take them for every test.
  • 'only-on-failure': take them when a test fails.
  • 'on-first-failure': take a screenshot on the first failure.

You can set a narrower policy on a project using that project’s use options. Automatic screenshot capture also accepts an object for capture options, including fullPage and omitBackground; consult the configuration reference for the shape supported by your installed version. This setting governs runner artifacts, not baseline assertions.

Add visual regression assertions

Use await expect(page).toHaveScreenshot() for a page-level visual assertion. Playwright Test creates or compares the expected image as part of its snapshot workflow.

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

test('home page matches its visual baseline', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveScreenshot();
});

Run the test using the Playwright Test runner. The assertion waits for two consecutive page screenshots to yield the same result, then compares the last capture with the expectation. That settling behavior helps avoid comparing a transient frame, but it cannot make nondeterministic page content identical; control dynamic content where necessary.

You can also assert on a locator when the intended contract is a component rather than the whole page:

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.
await expect(page.getByRole('main')).toHaveScreenshot();

A named screenshot can use a .png or .webp extension; the documentation describes both formats as lossless.

Set shared comparison tolerances

Configure defaults for screenshot assertions in expect.toHaveScreenshot. For example, an absolute pixel budget is useful when a small number of antialiasing differences are expected:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  expect: {
    toHaveScreenshot: {
      maxDiffPixels: 20,
    },
  },
});

Choose tolerances deliberately. A permissive setting can allow a meaningful visual regression to pass.

Option Meaning How to use it
maxDiffPixels Maximum absolute number of differing pixels allowed. Use when you can define a concrete pixel-count budget.
maxDiffPixelRatio Maximum proportion of differing pixels allowed. Use when a proportional allowance is more appropriate than a fixed count.
threshold Per-pixel perceived color tolerance, not a count or ratio of differing pixels. The documented pixelmatch default is 0.2; lower values are stricter and higher values more tolerant. The documented range is 0 (strict) to 1 (lax).

Other documented screenshot assertion defaults include animations, caret, scale, and stylePath. Set them when the default capture behavior does not match the contract you want to test; consult the Playwright Test configuration reference for exact option details.

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

Choose page, full-page, clipped, or locator scope

Viewport screenshot

A page screenshot assertion without extent options captures the viewport. This is usually the clearest choice when the test concerns what users see at a particular viewport size.

Full-page screenshot

Pass fullPage: true when content below the fold is part of the visual contract:

await expect(page).toHaveScreenshot({ fullPage: true });

Clipped region or component

Use clip to compare a fixed rectangle, or assert directly on a locator to focus on a component. A whole-page comparison provides surrounding context; a narrower assertion isolates the part whose appearance matters. Pick the smallest scope that still represents the requirement under test.

Mask dynamic regions

Use mask to cover content such as timestamps or changing avatars, and optionally set maskColor so the covered region is visually explicit:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await expect(page).toHaveScreenshot({
  mask: [page.locator('.timestamp'), page.locator('.avatar')],
  maskColor: '#888888',
});

The documented default mask color is pink, #FF00FF. The API says masks apply to matching elements even when those elements are invisible, unless matching behavior is adjusted. Avoid masking large or meaningful areas: a mask prevents the underlying pixels from helping detect a regression.

Make captures more stable

Visual assertions can fail for reasons unrelated to the intended UI change. Stabilize the page and capture conditions before relaxing comparison thresholds.

  • Animations: direct page.screenshot() allows animations by default; toHaveScreenshot() disables them by default. For assertion captures, finite animations are fast-forwarded and infinite animations are canceled when animations are disabled.
  • Hover state: the screenshot includes hover styling present at capture time. If hover effects are not part of the test, move the mouse to a neutral position before asserting: await page.mouse.move(-1, -1);
  • Changing content: mask narrowly targeted dynamic regions rather than broad page areas, or make the test data deterministic.
  • Capture scope: ensure the viewport, full-page extent, clip rectangle, or locator matches the part of the interface being tested.
  • Color differences: tune threshold for per-pixel color sensitivity; use maxDiffPixels or maxDiffPixelRatio for the amount of overall difference accepted. These settings control different things.

Organize snapshot paths

Use snapshotPathTemplate when you need a shared rule for where snapshots are stored. For screenshot-assertion-specific placement, configure expect.toHaveScreenshot.pathTemplate. The documented template tokens include {testDir}, {testFilePath}, {arg}, {ext}, {platform}, {projectName}, and {snapshotDir}.

For example, a template can include the project name to keep browser-project baselines distinct. Choose a layout that makes it clear which test and project own each expected image; do not share a baseline across environments that are intentionally expected to render differently.

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.

See the configuration reference for the applicable template setting and token behavior in your Playwright version.

Update baselines safely

After a deliberate UI change, update expected screenshots with:

npx playwright test --update-snapshots

The CLI supports update modes all, changed, missing, and none. Updating snapshots changes the expected artifacts; inspect the generated image diffs and commit only changes that represent the intended interface. Do not use a snapshot refresh as a way to make an unexplained failure disappear.

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

Troubleshoot screenshot failures

No screenshot artifact appears

Check whether automatic screenshot capture is set to 'off' or whether the test outcome does not match the selected mode. Remember that automatic artifacts and visual assertion snapshots are separate workflows.

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

The test has no visual assertion support

toHaveScreenshot() is provided by Playwright Test’s expect API. Run the test with the Playwright Test runner and import test and expect from @playwright/test, rather than treating it as a plain browser screenshot call.

A visual assertion fails intermittently

Inspect the diff first. Look for animation frames, hover state, timestamps, avatars, or other changing pixels; stabilize or mask only the genuinely dynamic area. Confirm the page is at the intended state before loosening tolerances.

A baseline update creates too many changes

Check that test, project, platform, and snapshot path are the intended ones. Review each changed image and use an update mode appropriate to the intended scope rather than blindly accepting every generated artifact.

The whole page comparison is noisy

Consider asserting on a locator or clipping to the intended rectangle. Keep a page-level assertion when the surrounding layout itself is what the test is meant to protect.

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 website screenshot outside your Playwright test suite, ScreenshotNeo is a screenshot API and MCP server. One GET request can return PNG, JPEG, WebP, or PDF. For example, this cURL request saves a WebP screenshot of a URL:

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 are accepted before capture and 60+ known consent platforms, newsletter popups, and chat widgets are removed; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. 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 shots per month with no card; paid plans start at $5 for 3,000 shots.

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

Frequently Asked Questions

Can I use automatic screenshots and visual assertions in the same Playwright project?

Yes. Automatic capture creates test artifacts under its configured policy; a screenshot assertion compares against an expected baseline.

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

Does `toHaveScreenshot()` capture the full page automatically?

No. The default is the viewport; pass `fullPage: true` for the full scrollable page.

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.