ScreenshotNeo

BlogHow-to

Getting Started With Automated Visual Testing

Learn to build reliable visual regression checks with Playwright: capture baselines, review diffs, control rendering noise, and decide when to update snapshots.

By the ScreenshotNeo team4 October 20269 min read

Automated visual testing catches unintended changes in how a page or component looks. A test drives the interface into a known state, captures a screenshot, and compares it with a reviewed baseline. The quickest way to start is Playwright Test’s built-in toHaveScreenshot(): create a small number of stable checkpoints, review the initial images, and run comparisons in a consistent browser and operating-system environment.

Visual checks complement functional assertions. A test that confirms a button works may not notice that the button moved off screen or that a layout regressed. A screenshot comparison can reveal appearance changes, but it does not tell you whether they are defects: a person must review the difference and decide whether the baseline should change.

1. Install Playwright Test

In an existing Node.js project, add Playwright Test and install its browser. These commands use npm:

npm init playwright@latest

Follow the prompts to select JavaScript or TypeScript and install the browser. If the project already uses Playwright Test, install the browser version required by that project instead of creating a second setup.

A minimal JavaScript test file can live at tests/home.visual.spec.js. The example below assumes the application is already running at http://127.0.0.1:3000. Replace that address with your local application URL.

2. Write a first screenshot comparison

const { test, expect } = require('@playwright/test');

test('home page initial view matches its reviewed baseline', async ({ page }) => {
  await page.goto('http://127.0.0.1:3000');
  await expect(page).toHaveScreenshot('home.png');
});

Run it with:

npx playwright test tests/home.visual.spec.js

On the first run, Playwright generates a reference screenshot. Review that image to confirm the page was in the intended state and the image is suitable as a baseline. On later runs, Playwright captures the page again and compares it with the stored reference. A difference causes the assertion to fail and produces comparison artifacts for investigation. See the official Playwright visual comparisons documentation for snapshot behavior and configuration.

For TypeScript, the equivalent test is:

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

test('home page initial view matches its reviewed baseline', async ({ page }) => {
  await page.goto('http://127.0.0.1:3000');
  await expect(page).toHaveScreenshot('home.png');
});

3. Add checkpoints that represent real states

Do not start by screenshotting every route and every possible state. Choose a small, important flow, then add checkpoints for states where a visual regression would matter. Examples include the initial page view, an opened navigation menu, a form validation message, or a completed interaction.

Drive the page into the state before taking its screenshot. Use accessible locators and explicit actions so the test expresses what a user does:

const { test, expect } = require('@playwright/test');

test('menu open state matches its reviewed baseline', async ({ page }) => {
  await page.goto('http://127.0.0.1:3000');
  await page.getByRole('button', { name: 'Open menu' }).click();
  await expect(page.getByRole('navigation')).toBeVisible();
  await expect(page).toHaveScreenshot('home-menu-open.png');
});

Use stable test data and avoid depending on live content that changes between runs. If the screenshot includes a clock, rotating promotion, personalized greeting, or remote feed, either control that input in the test environment or decide whether the region should be excluded using a documented, narrowly scoped mechanism.

4. Keep the rendering environment consistent

Screenshot output can vary with the operating system, browser version, browser settings, hardware, and headless mode. Playwright specifically recommends using the same operating system and browser versions for visual regression runs. Create and compare baselines in the same environment, especially in continuous integration. See Playwright’s environment guidance.

  • Pin the Playwright version and use the browser version installed for that version.
  • Generate and update baselines in the same operating system used for comparison.
  • Use a consistent viewport, device scale, fonts, locale, and color scheme where those affect the page.
  • Wait for meaningful UI readiness, such as a heading or loaded component, before capturing.
  • Use deterministic fixtures for dates, data, and user state where possible.

When a baseline made on a developer’s machine is compared with a different CI image, operating-system or font differences can create noisy changes even if the application code did not cause them. Prefer a repeatable CI image or another shared environment for both baseline generation and routine runs.

5. Review diffs and update baselines deliberately

A changed screenshot is a signal to investigate, not an instruction to accept the new image. Review the actual page, the expected baseline, the current capture, and the difference image. If the change is intentional, approve the new reference through your team’s review process. If it is unexpected, fix the UI or stabilize the test before changing the baseline.

  1. Run the failing test and open its expected, actual, and diff artifacts.
  2. Check whether the page reached the expected state and whether test data or the rendering environment changed.
  3. Decide whether the UI change is intended. Ask the feature owner when the design change is unclear.
  4. If intended, update the baseline using the snapshot update workflow supported by the Playwright version in your project, then inspect the changed image files in the code review.
  5. Run the comparison again without update mode to confirm the new baseline passes normally.

Playwright supports updating snapshots with its test runner update option, commonly npx playwright test --update-snapshots. Review the resulting files before committing them; do not make update mode the normal CI command. Keep baseline changes alongside the code change that explains them.

6. Deal with dynamic regions carefully

First make the page predictable. Control test data, use a stable account, freeze or inject time when the application allows it, and wait for the relevant interface to settle. These approaches keep the test meaningful because the screenshot continues to cover the UI that matters.

If a region is inherently variable, use a narrowly scoped ignore or matching control supported by the tool you use. Avoid masking large portions of the page: a broad mask can hide the very regression the test is meant to catch. Hosted visual testing integrations may offer region controls; for example, Applitools documents ignored regions in its eyes.check() configuration in the Applitools Playwright integration guide.

7. Choose local or hosted review workflow

Approach What it provides Considerations
Playwright built-in comparison toHaveScreenshot() assertions and reference screenshots generated on first run. Your team manages snapshot files and controls rendering-environment variation. This is a direct starting point for a small workflow.
Applitools Eyes with Playwright A hosted integration using eyes.check(), with documented full-page capture, match levels, and ignored regions. It adds a vendor service. Check its current setup, terms, and fit for your team.
Percy with Playwright A Playwright client package and a Percy CLI workflow that uploads snapshots to a project. It adds external service setup. Confirm current configuration and terms with the vendor.

Pick based on where reviewers should inspect and approve changes, how dynamic regions are handled, required browser and device coverage, CI integration, data handling, and current cost. This guide does not claim prices or contractual terms for Applitools or Percy; check their current vendor documentation before adopting either.

For the documented Playwright integration details, see the Applitools guide and the Percy Playwright project.

8. Fit visual checks into your test workflow

Run a focused set of visual checks with the rest of the tests that protect important flows. Make ownership clear: someone should investigate unexpected diffs, and intentional baseline changes should receive review. Keep the set small enough that the team can act on failures instead of routinely ignoring them.

Visual checks validate rendered appearance. They do not establish that a page is accessible. Automated accessibility checks can catch common issues such as contrast and labeling problems, but Playwright recommends combining automation with manual assessment and inclusive user testing. See the Playwright accessibility testing guidance.

Or skip the browser setup

If you need screenshots of deployed pages for review, documentation, or a visual workflow, ScreenshotNeo is a website screenshot API and MCP server. It does not replace Playwright assertions against your application’s controlled test states, but it can take a page screenshot with one GET request. Its API accepts options for full-page capture, element selection, viewport and device presets, wait conditions, and output format; 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);

Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off. Bot checks, blank pages, and failed loads are never billed, and response headers report the page verdict and billing status. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for free and get 1,000 screenshots a month with no card.

Troubleshooting

Symptom Likely cause What to do
The first run fails because no baseline exists. Playwright is creating the reference image, and the test runner reports that a snapshot was written. Open and review the generated image, then rerun the test normally. Treat the initial image as a candidate baseline, not automatic approval.
The test fails with a large diff after a browser or CI update. The rendering environment changed, including browser, operating system, fonts, or settings. Restore a consistent environment or deliberately regenerate and review baselines under the new environment.
Small areas differ on every run. Dynamic content, animation, delayed loading, or unstable test data is changing. Control the data and state, wait for a real readiness condition, and scope any ignored region tightly.
The screenshot is blank or incomplete. The page may not have loaded the target content when capture occurred, or navigation reached an error state. Assert a meaningful locator is visible before the screenshot; inspect navigation errors and the application’s test data setup.
The screenshot includes an unwanted menu or overlay. The test started from a persisted or unintended UI state. Reset state between tests, create a fresh context where appropriate, and explicitly establish the desired state before capture.
Many tests fail after an intended redesign. The UI changed but the corresponding baselines remain old. Review representative diffs, update the affected baselines as part of the redesign change, and rerun without update mode.
Reviewers cannot tell whether a visual change is acceptable. Baseline ownership or approval expectations are unclear. Assign review ownership and include the reason for image changes with the code review.

Performance, reliability, and cost

Visual tests take browser time to navigate, establish state, render, and capture images. Keep early coverage focused on high-value checkpoints, avoid redundant screenshots of unchanged states, and run them in a stable environment. More checkpoints improve coverage only when the team can review and maintain them.

Reliability comes mainly from deterministic application state and consistent rendering conditions. Pin browser and test dependencies, use stable fixtures, wait for UI conditions instead of arbitrary timing where possible, and treat unexpected diffs as failures to investigate. Snapshot artifacts also need normal repository review and storage practices because baseline images change over time.

The Playwright built-in route does not require adopting an additional visual testing service, though it uses CI and browser resources and requires maintaining snapshots. Hosted integrations add a vendor and its current pricing, terms, and data handling considerations. The available research does not establish comparable prices or contract terms for those services; verify them directly before budgeting.

FAQ

Can Playwright compare screenshots?

Yes. Playwright Test provides toHaveScreenshot(), which creates a reference image on first execution and compares later captures with it.

Should every screenshot difference fail the build?

Unexpected differences should be investigated. An intended UI change can be accepted after review and a deliberate baseline update.

Do visual tests replace accessibility tests?

No. Appearance comparisons do not establish accessibility. Use automated accessibility checks alongside manual assessment and inclusive user testing.

How many checkpoints should I start with?

Start with a small set covering an important page and a few meaningful states. Expand when the team can maintain and review the results.