What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Fix flaky Playwright screenshots by making the rendered page deterministic: use toHaveScreenshot() instead of a raw screenshot comparison, wait for application state rather than elapsed time, disable or hide motion and volatile content, pin the browser and rendering environment, and investigate failures with a trace before changing tolerances. The assertion itself waits for two consecutive identical screenshots before comparing with the baseline, so an arbitrary waitForTimeout() is rarely the right repair.

What “flaky” means in a Playwright screenshot test

A screenshot test is flaky when the same commit sometimes matches its baseline and sometimes fails without an intentional visual change. The difference can come from layout movement, late content, fonts, locale-dependent formatting, animation frames, browser rendering, or genuinely changing data. First reproduce the failure repeatedly in the same CI image and classify the diff; do not raise a pixel threshold until you know which category you are fixing.

Playwright’s page and locator screenshot assertions are designed for visual tests. expect(page).toHaveScreenshot() and expect(locator).toHaveScreenshot() wait until two consecutive screenshots are identical and then compare the last image with the expected baseline. They also disable CSS animations, CSS transitions, and Web Animations by default. Keep that behavior unless the animation itself is the feature under test.

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

A deterministic screenshot test, end to end

1. Pin test inputs and rendering settings

Set the values that affect text, layout, and color explicitly. The example uses a fixed viewport, locale, timezone, color scheme, and browser project. Keep test data stable as well: use seeded fixtures or a dedicated account instead of a live feed.

#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
import { test, expect } from '@playwright/test';
import path from 'node:path';

test.use({
  viewport: { width: 1440, height: 900 },
  locale: 'en-US',
  timezoneId: 'UTC',
  colorScheme: 'light'
});

test('dashboard is visually stable', async ({ page }) => {
  await page.goto('http://localhost:3000/dashboard', {
    waitUntil: 'domcontentloaded'
  });

  await expect(page.getByRole('heading', { name: 'Dashboard' }))
    .toBeVisible();
  await expect(page.locator('[data-testid="data-ready"]'))
    .toHaveAttribute('data-state', 'ready');

  await expect(page).toHaveScreenshot('dashboard.png', {
    fullPage: true,
    animations: 'disabled',
    stylePath: path.join(__dirname, 'visual-test.css'),
    mask: [
      page.locator('[data-testid="current-time"]'),
      page.locator('[data-testid="user-avatar"]')
    ]
  });
});

Run the test in the same project that produced the baseline. For a local reproduction, make the timezone explicit in the shell too:

TZ=UTC npx playwright test tests/dashboard.spec.ts --project=chromium

Generate a baseline only after the page is known to be correct. A baseline is tied to the browser project and rendering environment that generated it; it is not a universal image for every machine.

2. Wait for state, not a number of milliseconds

Replace await page.waitForTimeout(2000) with a web-first assertion, a stable locator, a completed request, or an application-specific ready marker. Playwright’s guidance is direct: “Tests that wait for time are inherently flaky.” A delay can be too short on a busy CI worker and unnecessarily slow when the page is already ready.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.goto('http://localhost:3000/reports');
await expect(page.getByRole('heading', { name: 'Reports' })).toBeVisible();
await expect(page.locator('[data-testid="report-table"]'))
  .toHaveAttribute('data-loaded', 'true');

// If readiness is defined by an API response, wait for that event.
const responsePromise = page.waitForResponse(response =>
  response.url().endsWith('/api/reports') && response.ok()
);
await page.reload();
await responsePromise;
await expect(page.locator('[data-testid="report-table"]')).toBeVisible();

Start the response wait before the action that triggers it. Prefer a semantic marker owned by the application over an implementation detail such as a fixed spinner duration.

Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors

3. Compare the smallest visual contract

A full-page assertion is appropriate for a page-level layout contract, but it also includes more unrelated pixels. A locator assertion limits the comparison to the component that matters and reduces exposure to unrelated ads, clocks, or navigation changes.

await expect(page.locator('[data-testid="invoice-card"]'))
  .toHaveScreenshot('invoice-card.png', {
    animations: 'disabled',
    mask: [page.locator('[data-testid="invoice-updated-at"]')]
  });

Use page screenshots for page composition and locator screenshots for a component or region. Do not switch to a smaller region merely to conceal a real regression.

Remove pixels that are not part of the contract

Mask changing values

Use mask for user-specific or time-dependent regions such as clocks, avatars, rotating recommendations, random IDs, and “last updated” labels. Masking preserves the surrounding geometry while replacing the selected pixels with a stable color.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await expect(page).toHaveScreenshot('account.png', {
  mask: [
    page.locator('.clock'),
    page.locator('.personalized-recommendations'),
    page.locator('[data-random-id]')
  ],
  maskColor: '#ff00ff'
});

Hide volatile elements with a screenshot stylesheet

Use stylePath when an element should not participate in layout or when a whole class of transient UI must be hidden during capture. Keep this stylesheet specific to visual tests; do not alter production CSS.

Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.
/* visual-test.css */
.clock,
.ad-slot,
.chat-widget,
.newsletter-popup,
.cursor-trail {
  visibility: hidden !important;
}

/* Freeze blinking carets and other incidental effects. */
*, *::before, *::after {
  animation: none !important;
  transition: none !important;
  caret-color: transparent !important;
}

Masking is useful when the element’s size is part of the layout. Hiding is useful when the element itself is not part of the visual contract. Deterministic fixture data is preferable when the content is meaningful and should remain visible.

Make the rendering environment reproducible

Playwright warns that rendering varies with the host operating system, browser version, browser settings, hardware, power source, and headless mode. Generate and execute baselines in the same browser, OS or container image, and font environment. A baseline made on a developer laptop can legitimately differ from one rendered in a Linux CI container.

  • Use a committed Playwright browser project and pin the Playwright version in your lockfile.
  • Run visual tests in one known container image or runner image.
  • Install and pin the fonts used by the application; a fallback font changes line wrapping and element height.
  • Keep viewport dimensions, device scale factor, color scheme, and headless mode consistent.
  • Set locale and timezoneId in the project. Also set the runner’s TZ environment variable when dates or numbers appear in the image.
  • Use fixed seed data and freeze server-side “now” values where your application supports it.

Keep baselines associated with the project and browser that generated them. If you intentionally upgrade the browser, fonts, or OS image, review the resulting baseline update as a deliberate migration rather than accepting every changed pixel.

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

Use CI traces to find the actual cause

Enable first-retry tracing in CI so a failure includes timing and page evidence without producing a large trace for every passing test.

Rank #4
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    trace: 'on-first-retry'
  }
});

Open the trace for the failed retry and inspect the action timeline, DOM snapshots, screenshots, network requests, and image diff. Look for a request that completed after the capture, a font that loaded late, a locator that moved, or a different response body. A trace often distinguishes an application race from harmless anti-aliasing noise faster than repeated reruns.

Choose tolerances only after stabilizing the test

Strict equality is the best default. If a known rendering difference remains after the environment is pinned, choose the narrowest appropriate control:

Option Use it for Risk
maxDiffPixels A small, known number of changed pixels A fixed count can be too strict for a larger image and too loose for a small one
maxDiffPixelRatio A proportional amount of known noise across image sizes Can hide a larger absolute change on a large screenshot
threshold Small color or anti-aliasing differences Can conceal genuine color regressions if set broadly

Document why the chosen value is safe and keep it local to the affected assertion where possible. Never use a tolerance to cover unknown movement, missing content, a wrong font, or an intermittent timeout; fix that cause instead.

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.

A practical repair sequence

  1. Reproduce the failure repeatedly in the same CI image and classify the diff as movement, content, font or rendering, or color noise.
  2. Use toHaveScreenshot on the page or the relevant locator instead of comparing an immediate raw screenshot.
  3. Keep animations and transitions disabled; mask volatile regions or hide them with stylePath.
  4. Wait for a meaningful application state, completed request, stable locator, or ready marker rather than waitForTimeout.
  5. Pin viewport, browser project, OS or container image, fonts, locale, timezone, and test data.
  6. Enable trace: 'on-first-retry' in CI and inspect the trace before rerunning blindly.
  7. Apply the smallest justified pixel or color tolerance only if the remaining difference is understood.

Troubleshooting common failures

Symptom Likely cause Fix
The diff shows a shifted card or changing line wrap Late content, font swap, or a layout reflow Wait for the ready marker, ensure fonts are installed, and verify the same viewport and browser project.
Only a clock, avatar, ad, or recommendation area changes Volatile application data Use deterministic fixtures, a targeted mask, or a screenshot stylesheet.
The first retry passes but the first attempt fails Timing race or resource loading variance Inspect the first-retry trace, replace sleeps with state waits, and check network requests and font loading.
Everything changes after a CI image update OS, browser, font, hardware, or headless-rendering difference Restore the prior image or intentionally regenerate and review baselines in the new pinned environment.
Changing threshold makes the test pass but defects remain Tolerance is hiding an unknown instability Revert the broad tolerance and fix the underlying data, motion, layout, or environment problem.
The test times out before taking a screenshot A locator or readiness condition never becomes true Check the trace and application logs, verify the selector and test data, and distinguish a product failure from a test wait.
A locator screenshot misses content below the fold The assertion intentionally captures only that element’s box Use fullPage: true on a page assertion when the page-level contract includes below-the-fold content.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If you need a clean image of a URL rather than a repository-bound visual assertion, ScreenshotNeo provides a website screenshot API and MCP server. It accepts the consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

One GET request is enough. The complete API documentation is at https://screenshotneo.com/docs/.

Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.

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,
)
r.raise_for_status()
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 failed: ${res.status}`);
require('node:fs').writeFileSync('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo also supports PNG, JPEG, and PDF output; full-page captures with lazy images loaded; CSS-selector element capture; dark mode; device presets and custom viewports; retina scale; PDF paper size, margins, landscape, and page ranges; custom CSS and JavaScript; clicks; selector or network-idle waits; request and resource blocking; custom headers, cookies, user agents, Authorization, timezone, and geolocation; transparent backgrounds; resizing; configurable-TTL caching; signed links; asynchronous jobs with signed webhooks; bulk capture for 100 URLs per call; a usage API; and an OpenAPI specification. Its parameter names are compatible with those used by other screenshot APIs, which helps when switching.

For AI workflows, its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account to try it.

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

FAQ

Frequently Asked Questions

Should I use waitForTimeout before toHaveScreenshot?

Usually no. The assertion already waits for two consecutive identical screenshots; add a state-based wait only for an application condition that the assertion cannot observe directly.

When should I update a visual baseline?

Update it only after confirming the UI change is intentional and the test still runs in the pinned environment. Review the diff as a code change rather than accepting it automatically.

Is a full-page screenshot always better than a locator screenshot?

No. Use a full-page assertion for page composition and a locator assertion for a component’s visual contract; the narrower capture often removes unrelated volatility.

Why can the same CSS render differently in CI?

The host OS, browser version and settings, fonts, hardware, power source, and headless mode can all affect rasterization and layout. Baselines and executions need the same environment.

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

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.