ScreenshotNeo

BlogComparisons

Percy vs Playwright Screenshot Testing: What’s the Difference?

Playwright includes local screenshot assertions; Percy adds a hosted visual review workflow. Compare baselines, CI, maintenance, and when to use each.

By the ScreenshotNeo team4 October 202611 min read

Short answer: Playwright Test has built-in visual screenshot assertions: it captures a page and compares the result with a reference image stored alongside the test project. Percy is a hosted visual-testing and review service that can work with Playwright tests. The practical choice is usually between Playwright’s local baseline and review workflow, and Playwright plus Percy’s hosted visual review workflow.

You can use Percy with Playwright. Percy does not replace Playwright’s browser automation or functional assertions; Playwright still drives the app and Percy participates in the visual snapshot and review path. Choose Playwright alone when repository-held snapshots and your existing CI review process are enough. Consider Percy when its hosted visual review and code-workflow integrations solve a real team need.

This guide compares the workflows, provides runnable Playwright examples, explains how to add Percy, and covers the operational trade-offs. For a separate way to capture website screenshots without maintaining a browser setup, see ScreenshotNeo.

What is the difference between Percy and Playwright screenshot testing?

Question Playwright screenshot assertions Playwright with Percy
What does it do? Playwright Test captures a screenshot and asserts that it matches a reference image. Playwright runs the test and Percy adds a hosted visual-testing and review workflow.
Where are references managed? Reference images live in the test project’s snapshot directory and are normally reviewed and committed to the repository. Percy provides a hosted service and review workflow. Check its current documentation for the project’s baseline and artifact behavior.
How are changes reviewed? Through test results and the repository workflow; intentional changes can be accepted by updating snapshots. Percy describes visual review alongside code workflows, including pull or merge request integrations, notifications, and webhooks.
What do you operate? Your Playwright tests, browser setup, baseline files, CI environment, and review process. Your Playwright tests and integration, plus the Percy service and its project and code-review integrations.
When does it fit? When local assertions and your existing repository and CI workflow meet the need. When the team wants Percy’s hosted visual testing and review workflow alongside Playwright.

These are complementary layers, not identical screenshot APIs. Playwright alone is a complete option for visual assertions; Percy is an additional service that can be connected to Playwright. Percy’s product materials identify it as part of BrowserStack. See the Playwright visual comparisons documentation, Percy product page, and Percy integrations documentation.

Does Playwright have visual regression testing built in?

Yes. Playwright Test provides expect(page).toHaveScreenshot(). On its first run, it generates a reference screenshot. Later runs capture the page and compare it with that reference. The reference files are stored in a snapshot directory associated with the test, and Playwright recommends reviewing and committing them. Use --update-snapshots when a visual change is intentional and the new output should become the reference.

The comparator uses pixelmatch. Options include maxDiffPixels to set a pixel-difference threshold and stylePath to apply a stylesheet during capture, for example to hide a volatile iframe or other dynamic region. Playwright also waits for consecutive screenshots to match when creating a baseline, which helps avoid saving a transient capture.

Runnable Playwright example

The following TypeScript example uses Playwright Test to load a page, wait for its main heading, and compare the resulting screenshot. Start with a clean project:

mkdir visual-check
cd visual-check
npm init -y
npm install --save-dev @playwright/test
npx playwright install chromium

Add this test as tests/home.spec.ts:

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

test('home page visual appearance', async ({ page }) => {
  await page.goto('https://playwright.dev/', { waitUntil: 'networkidle' });
  await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
  await expect(page).toHaveScreenshot('home.png', {
    fullPage: true,
    animations: 'disabled',
    maxDiffPixels: 100,
  });
});

Run it once to create the initial reference, inspect the generated snapshot, and commit it if it represents the intended appearance. Then run it again to compare a fresh capture:

npx playwright test tests/home.spec.ts
npx playwright test tests/home.spec.ts

To intentionally accept a redesigned page as the new reference, review the change and run:

npx playwright test tests/home.spec.ts --update-snapshots

Do not routinely update snapshots just to make a failing build green: first determine whether the difference is a genuine product change or nondeterministic rendering.

Configure shared screenshot settings

Use Playwright configuration to make the browser and screenshot expectations consistent across the suite. For example, create playwright.config.ts:

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

export default defineConfig({
  testDir: './tests',
  use: {
    ...devices['Desktop Chrome'],
    baseURL: 'https://playwright.dev',
    screenshot: 'only-on-failure',
  },
  expect: {
    toHaveScreenshot: {
      animations: 'disabled',
      maxDiffPixels: 100,
    },
  },
});

The screenshot setting controls when Playwright saves diagnostic screenshots for test failures; it is separate from the toHaveScreenshot() visual assertion. Keep the assertion explicit in the test so it is clear which page state is being compared.

Hide volatile content with a stylesheet

If a region changes for reasons unrelated to the UI under test, use a screenshot stylesheet to stabilize or hide it. For example, create tests/visual.css:

.live-clock,
.rotating-promotion,
iframe {
  visibility: hidden !important;
}

Then apply it to the assertion:

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

test('stable home page', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  await expect(page).toHaveScreenshot('home.png', {
    stylePath: path.join(process.cwd(), 'tests/visual.css'),
    animations: 'disabled',
  });
});

Hide only content that is intentionally out of scope. A stylesheet that masks real layout defects makes the test less useful. The supported options and baseline behavior are described in the Playwright documentation.

How to add Percy to Playwright

Percy’s surfaced Playwright integration uses a Percy CLI and Playwright package to capture snapshots from Playwright tests. The exact package instructions and commands can change, so use the current Percy documentation for the integration version you install. The general workflow is:

  1. Create or select a Percy project and obtain its project token.
  2. Install the Percy CLI and the Percy Playwright integration according to the current Percy setup guide.
  3. Add Percy snapshot calls at the page states you want reviewed. Keep the existing Playwright navigation, setup, and functional assertions.
  4. Set the Percy token as a CI secret, not a value committed to source control.
  5. Run the test command through Percy’s CLI in CI so snapshots are sent to the Percy build.
  6. Connect the Percy project to the repository if you want its supported pull or merge request review workflow, then inspect visual changes in the resulting build.

For example, the integration call in a Playwright test is conceptually an additional snapshot step after the page is ready. Follow the current integration guide for the exact import and invocation supported by the version in your project:

// Existing Playwright test responsibilities remain in place:
await page.goto('https://your-app.example/');
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();

// Add the Percy Playwright snapshot call here, following its current SDK guide.

This is intentionally not presented as a copy-paste SDK snippet: the research materials establish the Percy Playwright integration but do not provide its current package API or exact CLI syntax. Check the live Percy integration instructions rather than pinning your implementation to an unverified command. Percy’s integration documentation describes CI/CD and source-control connections; its source-control guide explains how Percy builds can be correlated with pull or merge requests and statuses.

Which one should you choose?

Choose Playwright alone when

  • You want visual assertions inside the same test suite as browser and functional checks.
  • Committing and reviewing reference images with the application code fits your team’s workflow.
  • Your CI environment can consistently generate and compare screenshots.
  • Your team is comfortable triaging differences through test output and repository review.

Consider Percy when

  • You want a hosted visual-testing and review workflow alongside Playwright.
  • Reviewing visual changes with pull or merge request context and integrations is valuable to your team.
  • You have evaluated the current integration, security and data handling, browser coverage, plan limits, and cost for your project.

The last checks matter because the available research does not establish current Percy pricing, plan limits, service-level commitments, privacy terms, or an exhaustive browser and SDK support matrix. Verify those details directly before selecting a plan or sending application pages to a hosted service. This recommendation is an inference from the documented difference in workflow ownership, not a claim that one tool produces more accurate screenshots.

Baselines, consistency, and sources of noisy diffs

Playwright warns that screenshot rendering can vary with host operating system, browser version, settings, hardware, power source, and headless mode. A baseline generated on a developer laptop may therefore differ from a CI capture even if the application has not changed. Generate and compare references in the same environment where possible: use a consistent CI image, browser version, viewport, device scale, and test configuration.

Control the page state before capture. Wait for the specific content the assertion depends on, disable or settle animations, and make dynamic data predictable. A broad networkidle wait can help on a quiet page but may not settle pages with continuous requests; prefer a meaningful readiness condition such as a visible heading or an application-specific loaded marker. Avoid taking a screenshot while fonts, images, or client-side layout are still changing.

With Playwright, references are project files and changes can be reviewed in version control. Percy introduces a hosted review path, but the research does not establish that it eliminates rendering variation. Keep the capture conditions and test state intentional whichever workflow you choose.

Performance, reliability, and cost considerations

  • Runtime: Screenshot capture and visual comparison add work to a test run. Full-page captures cover more content than viewport captures. Capture only the meaningful states and pages needed to detect regressions.
  • CI reliability: Consistent browser versions and operating environments reduce false differences. Stabilize application data and wait for a clear ready condition before capturing.
  • Review effort: A low threshold can surface small rendering differences, while an overly generous threshold can hide meaningful changes. Tune thresholds against the actual page and review representative diffs.
  • Storage and maintenance: Playwright baselines live with the project and need review as the UI evolves. Percy adds a service and integration to configure and operate. Team-specific storage, retention, throughput, and plan costs are not established here.
  • Pricing: No current Percy price or plan limit was verified for this comparison. Check its live pricing and terms before budgeting; do not assume hosted review is free or that local Playwright assertions carry a separate service fee.

Troubleshooting visual screenshot tests

Symptom Likely cause What to do
A test fails on CI but passes locally Different OS, browser version, headless mode, fonts, hardware, or rendering settings. Generate and compare baselines in the same CI environment; align browser versions and viewport settings.
The first run has no reference to compare No baseline exists yet for this test. Run the test, inspect the generated image, and commit the approved reference.
Many pixels differ after a small content change Dynamic data, animation, timestamps, fonts, or asynchronously loaded content changed the capture. Wait for the intended page state, disable animations, stabilize test data, or hide only irrelevant volatile regions with stylePath.
Updating snapshots makes the failure disappear but feels unsafe The reference is being replaced without checking whether the change is expected. Inspect the diff first. Update only when the visual change is intentional; otherwise fix the page or stabilize its state.
The screenshot misses content lower on the page The assertion captured the viewport rather than the full page. Set fullPage: true when the test should include the entire scrollable page.
Snapshot file path or name errors The requested path is outside the allowed per-test snapshot directory or the test’s snapshot naming is inconsistent. Use a stable snapshot name within the test’s snapshot directory and follow Playwright’s snapshot path rules.
Percy build does not appear or has no snapshots The CI run may not be using the Percy integration command, token, or snapshot call configured for the project. Check the current Percy Playwright and CI documentation, confirm the token is present as a CI secret, and inspect Percy build and integration logs.
Visual changes do not show in the pull request The source-control integration or repository-to-project link may be missing, or the visual run did not execute for that commit. Review Percy’s source-control setup and confirm the CI job runs on the relevant commit. Percy documents its repository integration and status workflow in its source-control guide.

Or skip the browser setup

If you need a website screenshot for documentation, a report, or an automated workflow rather than a baseline assertion, ScreenshotNeo provides a website screenshot API and MCP server. It can return PNG, JPEG, WebP, or PDF from one GET request. The API supports full-page captures, CSS selectors, viewport and device options, custom CSS and JavaScript, wait conditions, cookies and headers, caching, asynchronous jobs, and bulk capture. See the ScreenshotNeo API documentation for the available options.

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 cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each 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 offers take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots, and every feature is on every plan.

Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month with no card.

FAQ

Can I use Percy with Playwright?

Yes. Percy’s integration materials describe capturing snapshots from Playwright tests. Playwright continues to drive the browser and run functional checks; Percy adds its hosted visual workflow.

Does Percy replace Playwright?

No. In this comparison Percy complements Playwright’s test automation with a hosted visual-testing and review service.

Does Playwright compare screenshots automatically?

Playwright Test can compare them when a test uses expect(page).toHaveScreenshot(). The first run creates a reference; later runs compare against it.

Can I use both Playwright assertions and Percy?

The workflows can coexist: Percy’s integration works with Playwright-driven tests. Decide which pages need local assertions, Percy review, or both, and configure the current integration accordingly.

Which is better for a small project?

If committed baselines and your existing test reports are enough, start with Playwright’s built-in assertion. Add Percy when its hosted review workflow addresses a concrete collaboration need.