How to Mask a Webpage Region in Screenshot Change Detection
Use Playwright locator masks to exclude dynamic regions from screenshot comparisons, keep the masked area narrow, and avoid hiding regressions.
In Playwright, pass the locator for a changing element in the mask option of the screenshot assertion. Playwright covers the matched element’s bounding box with a solid color (pink, #FF00FF, by default), so those changing pixels are consistent when the screenshot is compared with its reference.
await expect(page).toHaveScreenshot({
mask: [page.getByTestId('live-timestamp')],
});
Keep the locator narrow and stable. A mask hides everything inside the matched element’s bounding box, including any real regression there. If you can make the test data deterministic instead, that preserves visual coverage of the element.
1. Add a locator mask to a Playwright screenshot assertion
This complete TypeScript example uses Playwright Test. It navigates to a page, waits for a timestamp element, and masks that element while checking the page against a screenshot baseline.
import { test, expect } from '@playwright/test';
test('page layout is stable around the live timestamp', async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 800 });
await page.goto('https://example.com');
const timestamp = page.getByTestId('live-timestamp');
await expect(timestamp).toBeVisible();
await expect(page).toHaveScreenshot('page.png', {
fullPage: true,
mask: [timestamp],
});
});
Replace https://example.com and live-timestamp with your application URL and the test attribute on the dynamic element. The example assumes your page actually renders an element with data-testid="live-timestamp".
Run the test
- Install Playwright Test:
npm install --save-dev @playwright/test. - Install its browser:
npx playwright install. - Save the example as
tests/page-visual.spec.ts. - Run
npx playwright test tests/page-visual.spec.ts. On the first run, Playwright creates a reference screenshot; review it before treating it as the expected appearance. - Run the test again after the page or code changes. Playwright compares the new screenshot with the reference.
Playwright’s screenshot assertion creates a reference on the first run and compares subsequent screenshots against it. The mask option is documented for screenshot capture, with locator masks available since Playwright v1.35. See the Playwright Page API and visual comparison documentation.
2. Choose the right region and selector
A mask is most useful for content that is expected to vary and is not itself under visual test: a clock, rotating promotion, personalized greeting, or third-party widget. It is not a way to approve a page-wide change. Mask only the smallest element that contains the volatile content.
| Selector approach | Example | When to use it |
|---|---|---|
| Test attribute | page.getByTestId('live-timestamp') |
Preferred when you can add a stable test hook. |
| Accessible role or name | page.getByRole('status') |
Useful when the element has a stable semantic role. |
| CSS selector | page.locator('.live-timestamp') |
Useful when the application already has a stable class or attribute. |
Prefer a selector that describes the element, not its position. A selector such as div:nth-child(4) can silently point at different content after a layout change.
Mask more than one region
mask accepts an array of locators. Use separate, specific locators for independent dynamic regions:
await expect(page).toHaveScreenshot({
mask: [
page.getByTestId('live-timestamp'),
page.getByTestId('personalized-greeting'),
],
});
Do not mask a large parent just to cover several small changing children unless every pixel inside that parent can safely be excluded from the comparison.
3. Configure the mask and screenshot
The Page screenshot API documents mask as an array of locators and maskColor as the color for the overlay. The default is pink (#FF00FF); set another color when it makes review artifacts easier to read. The mask still hides the covered content regardless of color.
await expect(page).toHaveScreenshot('page.png', {
fullPage: true,
mask: [page.getByTestId('live-timestamp')],
maskColor: '#000000',
});
Other screenshot settings, such as fullPage, determine what is captured. A full-page screenshot can include content below the initial viewport; make sure the locator identifies the intended element in that capture. Keep viewport size and rendering conditions consistent with the baseline.
Masking versus making the page deterministic
Use this decision order:
- Stabilize the source when practical. Freeze time, use fixed test data, or mock a changing response. The element remains visible to the visual check.
- Mask content outside the test’s purpose. Use a locator mask for a region whose changing pixels should not determine whether the page passes.
- Review what the mask hides. Inspect the rendered screenshot and diff. The overlay covers the element’s bounding box, so it can hide neighboring content if the element is oversized or overlaps other elements. This follows from the documented bounding-box behavior.
A passing comparison with a mask says nothing about the visual correctness of pixels under that mask. Keep separate functional checks for important behavior in excluded components.
4. Keep visual comparisons reliable
Screenshot output can vary with the operating system, browser version, browser settings, hardware, power source, and headless mode. Playwright recommends using the same environment for baseline creation and comparison. Pin the environment used by local and continuous-integration runs, and avoid updating snapshots until you have reviewed the actual visual change.
- Use the same browser version and operating system as the baseline run.
- Set a consistent viewport size and device scale where your test setup requires it.
- Wait for the relevant page state before capture. For example, assert that the target content is visible before taking the screenshot.
- Use stable fonts, data, and network responses where possible.
- Review the screenshot and diff before updating a reference. A baseline refresh by itself does not prove the new appearance is correct.
For masks specifically, review their size after layout changes. A locator that once covered a small timestamp can grow to cover a larger container and reduce the area the test actually checks.
5. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| The changing pixels still cause a diff. | The locator does not match the changing element, or it targets a different element. | Check the selector and confirm the locator is visible and resolves to the intended element before the screenshot. |
| Important content disappears from the screenshot. | The matched element’s bounding box is larger than expected or contains neighboring content. | Target a smaller child element. Inspect the screenshot with the mask overlay and avoid masking a broad container. |
| The screenshot differs across machines. | Rendering conditions differ, such as operating system, browser version, settings, hardware, or headless mode. | Run baseline creation and comparisons in the same environment, as Playwright recommends. |
| The test fails before it reaches the screenshot assertion. | The page did not load the expected element, or the locator is wrong. | Verify the URL and selector; wait for the application’s expected state and assert visibility before capture. |
| A baseline update makes the test pass, but the page looks wrong. | The reference was refreshed without reviewing the change. | Review the current screenshot and diff, then update the baseline only if the visual change is intended. |
6. Other region-ignore approaches
Tools expose region controls differently, so check whether a workflow changes capture pixels or comparison behavior, how it identifies regions, and how it manages reference review. Playwright’s documented mask uses locator bounding boxes during capture. Percy’s Playwright integration documents ignore regions selected by selectors, XPath, or coordinates. Applitools documents capturing a specific region and ignoring regions in visual testing. These are feature descriptions, not a pricing or equivalence comparison: Percy Playwright documentation and Applitools Visual AI options.
7. Performance, reliability, and cost
A locator mask is a screenshot capture option in an existing Playwright visual assertion. This workflow does not require a separate hosted screenshot service. Its reliability depends on selecting the intended element and keeping the rendering environment stable; a mask cannot protect against false confidence caused by hiding too much of the page.
No performance benchmark or cost comparison is established by the sources for this guide. In practice, keep selectors specific, avoid adding masks for static content, and use deterministic test data where it is straightforward. That keeps the comparison meaningful and the review surface clear.
8. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. A screenshot API can capture the page, but this Playwright mask workflow is what performs the locator-based masking in your visual assertion; do not treat a plain API capture as a Playwright visual comparison.
One GET request returns an image or PDF. For example, save a page screenshot with cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request details. ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and responses include X-Page-Verdict and X-Billed headers. Its MCP server includes take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.
Sign up for 1,000 free screenshots a month, with no card required.
9. FAQ
Does a mask change the page itself?
The documented behavior is an overlay on the screenshot at the matched element’s bounding box. Use a separate test if you need to verify the underlying component’s appearance or behavior.
Can I use a different mask color?
Yes. Set maskColor in the screenshot options. The documented default is #FF00FF.
What if the changing region is an iframe or canvas?
Choose a locator that identifies the visible element you intend to cover, then inspect the resulting screenshot to confirm the bounding box covers the right area. If the region cannot be targeted reliably, stabilize its content or use an appropriate region-control workflow in your visual testing tool.
Should I update the baseline whenever a masked test fails?
No. First determine whether the difference is an intended change, a rendering-environment mismatch, an unstable page state, or a mask selector problem. Update the reference only after reviewing the diff.


