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

To capture every route for visual regression testing, build an explicit, normalized route manifest, then run a Playwright Test for each route, viewport, and important UI state. Playwright can save reference screenshots and compare later runs against them; it does not discover every route automatically. The test covers only the URLs and states you actually set up.

What “every route” means in a visual regression test

A route list is not the same as a complete coverage claim. A screenshot test checks a page at a particular URL, viewport, browser configuration, and application state. A route that needs sign-in, a query parameter, seeded data, or a particular interaction needs an explicit fixture or test case.

Start with the application’s route configuration as the authoritative inventory for known routes. For a public site, supplement it with sitemap URLs and a same-origin link crawl, but keep the crawl bounded and deduplicate its results. Neither a sitemap nor a crawl necessarily finds unlinked pages, authenticated routes, parameterized routes, or client-only routes.

Decide what belongs in the manifest

  • Normalize URLs according to the application: trailing slashes, locale prefixes, query-string rules, and URL encoding can otherwise create duplicate or misleading cases.
  • Mark routes that require authentication or special data, and provide the corresponding setup rather than silently treating them as public pages.
  • Exclude routes that are intentionally inaccessible or not part of the visual contract, and document the reason in the manifest.
  • Keep parameterized routes explicit: include representative values or a defined set of meaningful cases rather than assuming one URL covers them all.

Create a route manifest and parameterized Playwright tests

Use a machine-readable manifest so coverage is reviewable and test generation is repeatable. For example, save this as visual-routes.json:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
[{"path":"/","name":"home"},{"path":"/pricing/","name":"pricing"},{"path":"/account/","name":"account","auth":true}]

The following example uses Playwright Test and its screenshot assertion. It assumes the application runs at http://localhost:3000, and that the test environment has deterministic data. Replace the authentication placeholder with your actual login or storage-state setup; a protected page must be tested in the correct state to produce a meaningful baseline.

import { test, expect } from '@playwright/test';
import routes from './visual-routes.json' assert { type: 'json' };

const baseURL = process.env.BASE_URL ?? 'http://localhost:3000';
const viewports = [
  { name: 'desktop', width: 1440, height: 900 },
  { name: 'mobile', width: 390, height: 844 },
];

test.describe('visual routes', () => {
  for (const route of routes) {
    for (const viewport of viewports) {
      test(`${route.name} - ${viewport.name}`, async ({ page }) => {
        await page.setViewportSize({
          width: viewport.width,
          height: viewport.height,
        });

        if (route.auth) {
          // Perform the application's login or load its authenticated state here.
        }

        await page.goto(new URL(route.path, baseURL).toString());
        await page.getByTestId('app-ready').waitFor();
        await expect(page).toHaveScreenshot(`${route.name}-${viewport.name}.png`);
      });
    }
  }
});

app-ready is an example of an application-specific readiness marker, not a built-in Playwright selector. Use a selector, response, or state that means the content under test is ready. A generic delay can be useful for known animation or third-party timing issues, but it is not a substitute for waiting on the right application state.

Handle route normalization deliberately

Normalize routes before generating tests, using rules that match your application rather than a universal URL transformation. Decide whether /about and /about/ are the same route, whether locale prefixes are separate coverage, and whether query strings change visible content. If they do, represent meaningful query variants as separate manifest entries. Remove duplicates only after applying those rules.

How Playwright creates and updates visual baselines

Playwright Test’s toHaveScreenshot() creates a reference image on its first run. Later runs capture the page and compare it with that reference. Review the generated baseline as a code change and commit approved images with the test suite. When a design change is intended, regenerate snapshots deliberately with npx playwright test --update-snapshots, inspect the differences, and commit the accepted updates.

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

The assertion waits until two consecutive screenshots match before comparing, which helps with transient rendering. It does not know whether the page contains the correct user, data, or state: the test must establish those itself. See the Playwright PageAssertions documentation and visual comparisons documentation for assertion behavior and baseline workflow.

Keep comparison conditions aligned

Playwright warns: “Browser rendering can vary based on the host OS, version, settings, hardware, power source (battery vs. power adapter), headless mode, and other factors.” This warning appears in its Visual comparisons documentation. Run baseline creation and comparison with aligned operating system, browser version, browser settings, and execution mode where possible. Otherwise, environment differences can produce pixel changes unrelated to the code change.

Choose coverage across viewports and UI states

One screenshot per URL is only evidence for the viewport and state captured. Add cases for dimensions that matter to the visual contract, not every theoretical combination.

Viewports

Choose named sizes that reflect the layouts you support, such as desktop and mobile breakpoints. If a layout changes at a breakpoint, include sizes on both sides of it. Keep the chosen viewport dimensions stable between baseline and comparison runs.

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.

Interactive states

Where appearance matters, create separate tests for states such as an open navigation menu, validation errors, an empty state, or a populated state. Reach the state with deterministic actions and data before capturing. Do not imply that a closed-menu screenshot validates the open-menu state.

Authentication and data

Use a test account, seeded records, or another repeatable fixture for protected and data-dependent routes. Remove dependencies on changing production data where possible. If a route’s appearance depends on account role or content variation, define which representative state the screenshot is intended to protect.

Reduce noisy diffs without hiding real defects

Visual assertions can fail on changes that are technically real but irrelevant to the intended comparison, such as a blinking caret, animation frame, or live timestamp. Playwright supports animation handling and screenshot styling; its Page API documentation describes screenshot options and stylesheet controls.

  • Disable or finish animations where motion itself is not under test.
  • Use screenshot styles or masks selectively for volatile content whose exact pixels are outside the visual contract.
  • Do not mask content merely because it changes: a price, error message, or account status may be exactly what the test should catch.
  • Keep the application state and data deterministic first; masking is not a replacement for stable fixtures.

Native Playwright or hosted visual review?

Native Playwright comparison keeps reference snapshots with the test suite and lets the test run compare them locally or in CI. Percy offers a hosted review workflow through its Playwright integration. These are workflow choices, not different ways to discover routes: either approach still depends on the route and state coverage you define.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Decision axis Native Playwright Percy with Playwright
Review location Reference screenshots are managed with the test suite. Snapshots are routed through Percy for hosted review.
Baseline workflow Review and commit accepted baseline files; update them deliberately. Confirm baseline behavior and project setup in current Percy documentation.
CI behavior Tests compare against local/project baselines as part of the test run. BrowserStack documents a review and approval workflow; add the appropriate wait or gate step if unapproved visual changes must fail CI.
Best fit Teams that want repository-managed references and a direct test-runner workflow. Teams that want hosted visual review and can maintain the related service and approval workflow.

Before adopting Percy, verify current token type, project setup, package and test-runner version requirements, and baseline behavior in the Percy integration documentation and BrowserStack’s guide to CI gating with Playwright. Hosted review is optional; it is not required to screenshot every route.

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

Troubleshoot common failures

A route is missing from the run

Check that it appears in the manifest after normalization, that the test generator includes it, and that any filter or project configuration is not excluding it. A crawl or sitemap is not proof that every route was found.

The screenshot is blank or captured too early

Verify the base URL and route, inspect navigation failures, and wait for an application-specific readiness condition. Check that authentication and required data setup completed before the assertion.

Many unrelated pixels differ

Compare the browser, OS, headless mode, viewport, and data setup used to create the baseline with the current run. Also check animations and volatile content. Avoid accepting a bulk baseline update until you understand why the images changed.

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

Only authenticated routes fail

The test may be redirecting to login or reaching a different account state than the baseline. Implement the actual authentication fixture or load a valid test storage state, then verify the final URL and visible identity before capturing.

A snapshot update makes the suite pass but may accept regressions

--update-snapshots replaces references; it does not decide whether a visual change is correct. Review the image diffs, confirm the change was intended, and commit only approved baselines.

Or skip the browser setup

ScreenshotNeo can capture a URL with one GET request, returning an image or PDF. It is useful for direct captures, but it does not discover your app’s routes or replace Playwright’s route manifest, authenticated fixtures, and baseline assertions. For repeatable regression checks, keep the route and state inventory in your test suite.

Example cURL request for a single route; see the ScreenshotNeo API documentation for request options:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/pricing -o shot.webp

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

Sign up for ScreenshotNeo’s free plan to try 1,000 screenshots a month without a card.

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.