Playwright Screenshot Testing vs Applitools for Dynamic Pages
Compare Playwright screenshot assertions with Applitools Eyes, stabilize dynamic pages, and choose a visual testing workflow that fits your team.
For dynamic pages, use Playwright Test’s toHaveScreenshot() when your team wants screenshot assertions and baseline review inside its existing test workflow. Choose Applitools Eyes when you want its visual-checkpoint integration and ignored-region or match-level controls. Either way, first stabilize data that matters, then narrowly mask or ignore content that does not. Keep functional or content assertions for important changing values.
Neither approach makes a changing page deterministic by itself. Playwright documents that rendering can vary with the operating system, browser version, settings, hardware, power source, headless mode, and other factors; keep baseline creation and test runs in the same environment. The available research does not establish a neutral benchmark showing one tool is more accurate or has fewer false positives.
1. Decide what “dynamic” means for your page
A visual test can fail because the page changed in a meaningful way, because irrelevant content changed, or because the capture environment rendered it differently. Identify which case applies before suppressing a region.
| Change | Recommended treatment |
|---|---|
| Important value, such as an order total or status | Make test data deterministic where possible. Also assert the value semantically. Do not mask it merely to make the screenshot pass. |
| Irrelevant volatile content, such as a rotating promotion | Mask or ignore the smallest possible region for the visual check. |
| Content changes but layout still matters | Consider a layout-oriented match where supported, and separately assert any important content. Verify current Applitools match-level names and behavior in its documentation. |
| Differences across machines or runs | Use a consistent browser, operating system, settings, and capture mode. Investigate environment drift before changing a baseline. |
Masking and ignored regions reduce visual coverage of the affected pixels. They are appropriate for known noise, not a substitute for checking dynamic information that users rely on.
2. Playwright: screenshot assertions with a masked dynamic region
Playwright Test provides expect(page).toHaveScreenshot(). On the initial run it creates a reference screenshot; subsequent runs compare against it. Review baseline updates deliberately, because a new reference can represent either an intended design change or a regression. The official documentation describes locator masks and screenshot styles for suppressing selected content.
Example test file, tests/dashboard.spec.ts:
import { test, expect } from '@playwright/test';
test('dashboard layout stays stable while the live clock changes', async ({ page }) => {
await page.goto('http://127.0.0.1:3000/dashboard');
// Keep important dynamic data covered by a semantic assertion.
await expect(page.getByTestId('account-status')).toHaveText('Active');
// Mask only the volatile clock. The rest of the page remains compared.
await expect(page).toHaveScreenshot('dashboard.png', {
fullPage: true,
animations: 'disabled',
mask: [page.getByTestId('live-clock')],
});
});
Run it with the Playwright Test runner. A first run records the reference; later runs compare with it:
npx playwright test tests/dashboard.spec.ts
After reviewing a deliberate visual change, update references explicitly:
npx playwright test tests/dashboard.spec.ts --update-snapshots
The exact assertion options available depend on the Playwright version in your project. Consult the current Playwright snapshot testing guide and PageAssertions API for options such as masks, screenshot styles, and full-page capture.
Make the test repeatable
- Seed or stub data that should remain stable, especially values whose meaning matters.
- Wait for a meaningful page condition, such as a specific heading or loaded application state, rather than relying on an arbitrary delay.
- Mask only the volatile locator. If the region’s geometry matters, check its dimensions or surrounding layout separately.
- Run baseline creation and comparison with the same browser and host environment.
- Inspect visual differences before accepting a snapshot update.
3. Applitools Eyes: checkpoints and ignored regions
Applitools documents a Playwright integration that uses an Eyes fixture and eyes.check() visual checkpoints. Its integration also documents match-level settings and locator-based ignored regions. This is useful when a team wants checkpoints configured through Eyes and a separate visual review workflow.
A minimal TypeScript-style example illustrates the checkpoint shape. Confirm package setup, fixture imports, and current API details against the Applitools Playwright integration guide for the version you install:
import { test } from '@applitools/eyes-playwright';
test('dashboard visual checkpoint', async ({ page, eyes }) => {
await page.goto('http://127.0.0.1:3000/dashboard');
// Retain an ordinary assertion for important changing content.
// Use the assertion library configured in your project for this check.
const status = await page.getByTestId('account-status').textContent();
if (status?.trim() !== 'Active') {
throw new Error(`Unexpected account status: ${status}`);
}
await eyes.check('Dashboard', {
target: page,
ignoreRegions: [page.getByTestId('live-clock')],
});
});
Use ignored regions as narrowly as possible. Applitools’ older dynamic-content guidance also describes Layout matching for cases where content changes while layout remains relevant. That guidance dates to 2018; check current documentation for the current setting names and behavior before relying on it.
4. Playwright or Applitools: choose by workflow
| Decision | Playwright screenshot assertions | Applitools Eyes |
|---|---|---|
| Where visual checks live | In Playwright Test, alongside test code and screenshot references. | In the Eyes SDK integration, using named visual checkpoints. |
| Handling dynamic regions | Mask locators or apply screenshot styles to suppress known volatile content. | Configure ignored regions and match-level behavior for checkpoints. |
| Baseline and review ownership | Your team manages reference files and reviews snapshot changes in its test workflow. | Your team adopts Eyes checkpoint configuration and reviews its reporting workflow. |
| Environment control | Keep the baseline and runs consistent; Playwright explicitly warns that host differences can affect rendering. | Validate the execution coverage and service behavior you need against current Applitools documentation and terms. Vendor coverage and AI statements are product claims, not independent comparative findings here. |
| Best fit | Teams that want direct control in an existing Playwright test setup. | Teams that want an additional visual-testing service and its checkpoint workflow. |
There is no universal winner in the available evidence. Decide based on baseline review, how much environment consistency you can maintain, the number of browsers and viewports you need, and whether a visual-testing service fits your operations and budget. The research used for this guide does not establish comparative pricing, false-positive rates, or maintenance benchmarks.
5. A practical strategy for dynamic pages
- Classify each changing region. Mark it as important content, irrelevant noise, or content whose exact text changes while composition matters.
- Stabilize important values. Seed test data or arrange a predictable application state. Assert critical values with ordinary test assertions.
- Suppress only known noise. Mask a specific Playwright locator or configure a specific Eyes ignored region. Avoid masking a whole page section if only a timestamp changes.
- Check layout when text cannot be fixed. If the text is intentionally variable, retain checks for position, size, and surrounding structure. Investigate the current Eyes Layout matching behavior if using that approach.
- Pin the capture environment. Use the same operating system image, browser version, settings, and headless mode for baseline and comparison runs.
- Review every baseline update. Compare the new reference with the prior one and the intended design change before accepting it.
6. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Screenshot changes between local and CI | Different OS, browser version, settings, hardware, power state, or headless mode. | Run baseline generation and CI comparisons in a consistent environment; confirm the browser version and capture mode. |
| Test fails on a timestamp, avatar, or rotating content | The changing content is included in the visual comparison. | Seed the value if it matters. Otherwise narrowly mask or ignore that element and preserve separate assertions where needed. |
| Test passes but an important dynamic value is wrong | The value was hidden by a mask or ignored region, removing visual coverage. | Add or retain a semantic assertion for the value and narrow the suppressed region. |
| Large visual difference after a dependency update | Browser or rendering environment may have changed, or the page may have changed. | Check environment and application changes before updating references. Do not auto-approve the new baseline without review. |
| Applitools example does not match installed API | Integration versions and current setup details may differ from an illustrative snippet. | Follow the current official Playwright integration guide for package installation, fixtures, and options. |
| Layout matching option is missing or named differently | The dynamic-content article describing it is older. | Verify current Applitools documentation and UI labels; do not assume the 2018 instructions are unchanged. |
| Snapshot is too broad or noisy | Uncontrolled data, animations, or an unnecessarily large capture area. | Make application state deterministic, disable relevant animations, and capture or suppress only what the test needs. |
7. Performance, reliability, and cost
Both methods add browser rendering and image comparison work to a test run. The exact time and cost depend on your suite, environment, selected coverage, and current service terms; the available research contains no comparative benchmark or verified current Applitools pricing. Keep visual checks focused on pages and states where layout regressions matter, and avoid multiplying browser and viewport combinations without a reason.
Reliability comes mainly from controlling inputs and capture conditions: stable test data, meaningful readiness conditions, a consistent browser environment, and deliberate review of changed references. Masks can reduce irrelevant diffs, but broad masking makes a test less useful. For either workflow, maintain functional assertions for dynamic content that must be correct.
8. Or skip the browser setup
For a screenshot outside a test runner, ScreenshotNeo is the alternative to try first: it returns a screenshot or PDF from one GET request, removes cookie banners, popups, and chat widgets before the shot, and bills only clean shots. Bot checks, blank pages, and failed loads are not billed. Its MCP server gives AI agents screenshot tools. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.
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 import('node:fs/promises').then(({ writeFile }) =>
writeFile('shot.webp', Buffer.from(await res.arrayBuffer()))
);
See the ScreenshotNeo API documentation for request options. The API also supports CSS selectors, full-page capture, viewport and device settings, custom CSS and JavaScript, waits, caching, async jobs, bulk capture, and more. A screenshot API is useful for capture workflows; it does not replace Playwright or Eyes assertions and baseline review in a visual regression suite.
Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.
9. FAQ
Should I mask a dynamic element or assert it?
Assert it if its value matters to users or business logic. Mask or ignore it only when the changing pixels are irrelevant to the visual check.
Can Applitools replace Playwright tests?
Eyes adds visual checkpoints through a Playwright integration. Keep ordinary tests for behavior and content; visual comparison answers a different question.
Should I update snapshots whenever CI fails?
No. First determine whether the difference is an intended design change, uncontrolled data, or environment drift. Update references only after review.
Which should a small team start with?
If the team already runs Playwright Test and can keep its environment stable, begin with its screenshot assertions. Consider Eyes when its checkpoint and service workflow solves a specific team need.
