Playwright Screenshot Testing vs Cypress Screenshot Testing
Compare Playwright’s built-in screenshot assertions with Cypress capture plus visual testing integrations, and learn how to choose a reliable workflow.
Playwright Test has built-in screenshot comparison through expect(page).toHaveScreenshot(). Cypress can capture screenshots with cy.screenshot(), but its core does not compare them with an approved baseline; that comparison comes from a plugin or service. Choose based on your existing test stack, how you want to manage baselines and review changes, and whether you can keep the page and rendering environment stable.
“Screenshot testing” can mean taking an image, or checking whether a new image differs from an approved reference. Those are related but distinct jobs. A screenshot proves what was rendered at a moment; a visual regression workflow captures, compares, and gives the team a way to review or accept changes.
1. What screenshot testing means
| Task | What it does | Playwright | Cypress |
|---|---|---|---|
| Capture | Saves an image of a page or element. | Page and locator screenshot APIs. | cy.screenshot(). |
| Compare | Checks a fresh image against a reference and reports differences. | Built into Playwright Test with toHaveScreenshot(). |
Requires a visual comparison plugin or service. |
| Review and approve | Lets a developer decide whether a difference is expected and update the reference. | Reference files can be reviewed and updated with the test runner. | Depends on the selected plugin or service and the team’s baseline and review process. |
Neither framework’s screenshot workflow replaces functional assertions. A visual check can catch an unexpected layout change, but it does not prove that a button works, that content is correct, or that contrast meets an accessibility standard.
2. Playwright: capture and compare with a built-in assertion
Playwright Test’s toHaveScreenshot() checks the current rendering against a reference image. On the first run, it creates the reference; later runs compare new screenshots against it. Screenshot assertions wait until two consecutive screenshots produce the same result before comparing, which helps avoid capturing a page while it is still settling.
Runnable page comparison
Start with a project using Playwright Test. Save this as tests/home.visual.spec.ts:
import { test, expect } from '@playwright/test';
test('homepage matches its visual baseline', async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 800 });
await page.goto('https://example.com');
await expect(page).toHaveScreenshot('homepage.png');
});
Run the test with npx playwright test tests/home.visual.spec.ts. The first run establishes the reference image. Commit that reference after reviewing it. Subsequent runs compare against it. When a reviewed design change should become the new expected appearance, run npx playwright test tests/home.visual.spec.ts --update-snapshots and inspect the changed reference before committing.
Use the current [Playwright screenshot assertion documentation](https://playwright.dev/docs/test-snapshots) for supported assertion options and setup details. Reference screenshots are PNG by default; a snapshot named with a .webp extension is stored as lossless WebP.
Compare a focused element
Page-wide snapshots are useful for a whole-screen checkpoint. For a focused component, use a locator assertion so unrelated page regions do not obscure the change you want to catch:
import { test, expect } from '@playwright/test';
test('navigation matches its visual baseline', async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 800 });
await page.goto('https://example.com');
await expect(page.getByRole('navigation')).toHaveScreenshot('navigation.png');
});
Choose an element whose boundaries represent a meaningful visual contract. If the element includes timestamps, rotating content, or user-specific data, stabilize or exclude that content first. Avoid broad masking that could hide a real regression.
Tolerance and volatile content
Playwright documents maxDiffPixels for controlling the allowed pixel difference. It also supports a stylePath stylesheet for filtering volatile content and improving determinism. Keep tolerances narrow and intentional: a permissive threshold can let a genuine visual defect pass. Check the current assertion documentation for exact option syntax and behavior before setting project policy.
3. Cypress: capture with a plugin or service for comparison
Cypress’s cy.screenshot() saves an image, but screenshot capture alone does not establish whether the result matches an approved visual baseline. Cypress’s documentation states: “Cypress does not perform image comparison itself.” To build a visual regression workflow, add an integration that compares captured images and supports the baseline and review process your team wants.
Runnable screenshot capture
This Cypress test captures a page after setting a consistent viewport and visiting it:
describe('homepage screenshot', () => {
it('captures the homepage', () => {
cy.viewport(1280, 800);
cy.visit('https://example.com');
cy.screenshot('homepage');
});
});
This saves a screenshot; it does not compare it with a baseline. Follow the selected integration’s current instructions to install it, configure where references are stored, invoke its comparison command or assertion, and review or approve changes. Cypress documents open-source plugins that compare locally or in CI, along with hosted services that can provide comparison and review workflows. The setup differs by integration, so use its own documentation rather than treating cy.screenshot() as a complete visual test.
Cypress names Applitools Eyes, Argos, and Chromatic among visual testing integrations. They are options to investigate, not a universal recommendation: verify current capabilities, supported workflows, and terms before choosing one.
4. How the workflows differ
| Decision point | Playwright Test | Cypress |
|---|---|---|
| Comparison included in the core test workflow | Yes. Use toHaveScreenshot(). |
No. Add a comparison plugin or service. |
| Initial baseline | The first assertion run creates the reference image. | Defined by the selected integration’s workflow. |
| Updating an expected image | Use --update-snapshots, then review the reference changes. |
Use the selected plugin or service’s baseline approval process. |
| Best fit by workflow | A direct fit when a team wants native screenshot assertions in Playwright Test. | A practical fit when a team already uses Cypress and wants to add visual comparison to that test stack. |
| Review ownership | The team manages reference images and reviews updates in its repository workflow. | May be local or CI-based with a plugin, or handled through a hosted service’s review workflow. |
The fit guidance is conditional, based on the documented workflows; it is not a performance comparison. No framework is universally better for screenshot testing. Consider the framework your application already uses, where you want baselines to live, how reviewers should approve changes, and what infrastructure your team is prepared to maintain.
5. Make visual checks stable and useful
Screenshot diffs are sensitive to rendering conditions. Operating system, browser version, fonts, display settings, hardware, headless mode, data, timing, and animation can all affect pixels. A test that captures changing content can fail even when the intended interface has not changed.
- Fix the viewport. Use an explicit, repeatable viewport for each visual checkpoint. Treat mobile and desktop layouts as separate states if both matter.
- Control test data. Prefer fixed fixtures or controlled API responses over live data that changes between runs.
- Wait for the intended state. Wait for the page or component to finish loading and for the specific content under test to appear. Avoid arbitrary sleeps when a meaningful readiness condition is available.
- Reduce motion and volatility. Disable or finish animations, and use Playwright’s stylesheet support or the chosen Cypress integration’s documented masking approach for truly dynamic regions.
- Keep the rendering environment consistent. Generate and compare baselines in the same operating system and browser environment where possible. Pin the relevant browser and dependencies in CI.
- Choose deliberate checkpoints. Capture meaningful states such as an opened menu or validation error, rather than taking a screenshot at every step.
- Review every baseline update. Updating a baseline accepts the new rendering as expected. Inspect the image diff before committing or approving it.
Focused component checks can reduce unrelated variation. Cypress notes that component testing can provide a more controlled surface for visual checks. In either framework, scope the screenshot to the part of the page whose appearance matters, while keeping enough surrounding context to catch layout problems.
6. Troubleshooting common screenshot test failures
| Symptom | Likely cause | What to do |
|---|---|---|
| Same test produces different diffs on different machines | Operating system, browser, fonts, hardware, or rendering settings differ. | Run baseline creation and comparison in a consistent environment; align browser versions and installed fonts. |
| Diffs appear around changing text, avatars, or timestamps | Live or user-specific data changes between runs. | Use fixed fixtures or controlled responses; mask or hide only the genuinely variable region. |
| Screenshot catches an incomplete page | Capture starts before the intended state is ready, or asynchronous content arrives later. | Wait for a relevant element or application-ready condition before capturing. |
| Diffs appear during animated transitions | The capture lands at different points in an animation. | Disable motion for visual tests or wait for the transition to finish using the framework or integration’s supported mechanism. |
| Playwright reports a screenshot mismatch after a deliberate redesign | The stored reference still represents the old design. | Review the new output, update with --update-snapshots, and commit the reviewed reference. |
| Cypress saves screenshots but no visual test fails | cy.screenshot() captures but does not compare. |
Add and configure a visual comparison plugin or service, then use its documented assertion or CI workflow. |
| A visual check passes but a control is broken | Pixel comparison checks appearance, not behavior. | Add functional assertions for interaction and outcomes. |
| A visually similar page fails accessibility expectations | Screenshot comparison does not evaluate accessibility rules or required contrast. | Run accessibility checks separately and test keyboard and interaction behavior. |
7. Performance, reliability, and cost
There is no documented benchmark in the cited framework material that establishes one approach as faster. Actual runtime depends on application loading, screenshot scope, CI resources, browser setup, and—on Cypress—the chosen comparison integration. Measure your own suite before making a speed claim.
- Runtime: Keep the number and size of visual checkpoints aligned with risk. Reuse normal test setup where possible and avoid repeatedly capturing large pages when a focused element is enough.
- Reliability: Deterministic data and a consistent rendering environment matter more than adding a looser diff threshold. A threshold should accommodate known rendering noise, not conceal regressions.
- Storage and review: Playwright reference images become test artifacts that teams need to store and review. Cypress plugin and hosted-service workflows have their own baseline storage, CI artifact, and review considerations.
- Cost: Playwright’s built-in assertion is part of its test workflow; account for CI time and artifact storage. Cypress comparison may use an open-source plugin or a commercial service; check the selected option’s current pricing and terms directly. Do not assume capture itself includes hosted review.
8. Which should you choose?
- Choose Playwright’s native comparison if you want screenshot assertions and baseline updates directly in Playwright Test, and are comfortable managing reference images in your test workflow.
- Choose Cypress plus an integration if Cypress is already your team’s test framework and you want to add visual comparison without changing that test stack. Select the integration based on its current baseline, CI, and review workflow.
- For a new visual regression workflow, compare the complete process: authoring checks, stabilizing the rendering, reviewing diffs, approving baselines, and storing artifacts. Native assertions can reduce integration setup; a service may offer a review workflow that suits your team. Confirm current features and terms.
Whichever you use, pair screenshot comparisons with functional tests and accessibility checks where those requirements apply. Visual regression is one signal about a rendered page, not a complete quality check.
9. Or skip the browser setup
For a rendered screenshot from a URL without setting up a browser test, [ScreenshotNeo](https://screenshotneo.com) provides a screenshot API and MCP server. It captures a page image; it does not replace Playwright or Cypress baseline comparison and review.
cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
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)
Node.js:
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);
See the [ScreenshotNeo API docs](https://screenshotneo.com/docs/) for request options and response details. Cookie banners, popups, and chat widgets are removed before the shot; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is available on every plan.
Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.
10. FAQ
Does Cypress have visual regression testing built in?
Cypress can capture screenshots, but its core does not perform image comparison. Add a plugin or service for baseline comparison.
Does Playwright create a baseline automatically?
The first run of a screenshot assertion creates the reference image. Review and commit it, then update it deliberately when the expected appearance changes.
Can screenshot testing replace accessibility testing?
No. A visual diff does not determine whether a page meets accessibility requirements. Run separate accessibility checks.
Can I use both frameworks?
Yes, if different parts of your project use them. Keep each visual test’s environment and baseline process clear so references are generated and reviewed consistently.
