ScreenshotNeo

BlogEngineering

Why Do Playwright Screenshots Differ Between Linux and macOS?

Playwright screenshots can differ across Linux and macOS because rendering depends on the OS, fonts, browser build, settings, and capture mode. Learn how to diagnose the cause and keep visual baselines reliable.

By the ScreenshotNeo team4 October 20267 min read

Playwright screenshots can differ between Linux and macOS even when the HTML, CSS, and application code are unchanged. A screenshot records the result of a rendering environment: the operating system, available fonts, browser build, settings, hardware, headless mode, and screenshot scale can all affect the pixels.

For reliable visual regression tests, create and compare each baseline in the same controlled environment. If both Linux and macOS matter, keep separate expected screenshots for each platform instead of expecting every pixel to match. Playwright documents that screenshots differ across browsers and platforms because of rendering and fonts, and recommends using the same environment as the one that generated the baseline. See Playwright visual comparisons.

Why the same page renders differently

Fonts and operating-system rendering

Different installed fonts, font versions, fallback choices, and platform rendering behavior can change glyph shapes and spacing. A small change in text width can cause a line to wrap, which changes element height and shifts everything below it. Before increasing a visual diff threshold, check which font the browser actually loaded and whether the CI image has the same font files as the baseline environment.

Browser version and build

Browser updates can change layout or painting behavior. Record the Playwright package version and browser version used to create a baseline, and pin them in CI where practical. When intentionally upgrading Playwright or its browser binaries, review visual diffs as part of the upgrade; some baselines may need deliberate updates. Playwright also recommends keeping browsers current when you want to test against newer browser versions. See Playwright browsers.

Host settings, hardware, and headless mode

Playwright lists operating-system version, settings, hardware, power source, and headless mode among factors that can affect rendering. A local headed run and a Linux headless CI run are not a controlled comparison. Align these conditions before deciding whether a difference is an application regression or an expected platform-specific rendering result.

Screenshot scale

Playwright’s screenshot scale option controls output pixels. 'css' produces one image pixel per CSS pixel; 'device' captures device pixels and can produce larger images on high-DPI displays. Use the same scale in both runs. See the Page API screenshot options.

Capture timing and changing page content

Animations, blinking carets, timestamps, rotating content, network-loaded data, and delayed fonts can make captures unstable. Playwright’s screenshot assertions wait until two consecutive screenshots match before comparing with the expected image, and provide controls for animations, carets, and injected styles. Those controls help stabilize a capture; they do not make Linux and macOS rendering identical. See PageAssertions screenshot options.

A practical workflow for consistent snapshots

  1. Choose the authoritative environment. Specify the OS image and version, Playwright version, browser project/build, headless or headed mode, viewport, and screenshot scale for each baseline.
  2. Generate and compare in that environment. Run visual assertions in the same environment that created the expected screenshots. If users on Linux and macOS both matter, maintain platform-specific snapshots.
  3. Stabilize the page state. Wait for required application data and fonts, disable or finish animations, hide the caret, and mask or hide genuinely volatile content using screenshot styles where appropriate.
  4. Inspect a diff in a useful order. Check environment and browser version first, then loaded fonts and text wrapping, screenshot scale, dynamic state and timing, and finally application changes.
  5. Use thresholds deliberately. Pixel thresholds and maximum differing-pixel options can tolerate small variations, but they do not explain a systematic mismatch. Diagnose broad shifts, different line breaks, or missing content before relaxing comparison settings.

Runnable Playwright example

This JavaScript example pins a viewport and CSS-pixel screenshot scale, waits for fonts, and uses screenshot assertion controls to reduce animation and caret noise. Run it from a Playwright Test project with the relevant browser installed.

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

test('homepage visual baseline', async ({ page }) => {
  await page.setViewportSize({ width: 1280, height: 800 });
  await page.goto('https://example.com', { waitUntil: 'networkidle' });
  await page.evaluate(() => document.fonts.ready);

  await expect(page).toHaveScreenshot('homepage.png', {
    fullPage: true,
    scale: 'css',
    animations: 'disabled',
    caret: 'hide',
    maxDiffPixelRatio: 0.001,
  });
});

Replace the example URL with your page. Keep the same options when updating and checking the baseline. If networkidle is unsuitable for a page with ongoing requests, use a page-specific readiness condition, such as waiting for the main content selector, and keep that condition consistent across runs.

Separate projects and snapshots by platform

Use distinct CI jobs or projects for the platforms whose output you intend to support. Playwright can include browser and platform information in generated snapshot names; configure snapshot naming so expected files cannot be confused across environments. A Linux WebKit run is useful for WebKit coverage, but it is not a substitute for macOS Safari fidelity: Playwright’s WebKit is derived from WebKit main, and Playwright recommends macOS when the closest Safari experience is the goal. Linux WebKit can be a more affordable CI choice. See Playwright browser platform guidance.

Relevant screenshot and assertion options

Option or setting What it controls When it helps
scale: 'css' | 'device' Output pixel density Keep scale consistent; use CSS scale when one output pixel per CSS pixel is desired.
fullPage Whether to capture the full scrollable page Use the same value for baseline creation and comparison.
animations Screenshot assertion animation behavior Disable transitions or animations that create unstable frames.
caret Whether a text caret appears in the snapshot Hide the caret to prevent blink-state diffs.
stylePath / injected style Styles applied during screenshot capture Hide or neutralize timestamps, ads, or other known volatile elements; keep the style consistent.
threshold and maxDiffPixelRatio How much image difference an assertion accepts Allow a justified small rendering variance after environment control, not to conceal layout shifts.
Viewport and device scale factor Layout dimensions and device pixel ratio Match both across baseline and comparison runs.

Consult the current screenshot assertion API and Page screenshot API for the exact option types available in your installed Playwright version.

Troubleshooting common mismatches

Symptom Likely cause What to do
Text differs or wraps onto another line Font missing, fallback font selected, or font version differs Inspect the computed font and loaded font resources; install or bundle the intended fonts in every baseline environment.
Nearly every edge has a small pixel diff Different OS/browser rendering, screenshot scale, or browser build Align the environment, browser version, viewport, and scale; use platform-specific baselines if the platform difference is expected.
Large regions shift vertically Text wrapping, changed content, viewport mismatch, or delayed layout Compare DOM state and dimensions, wait for page readiness and fonts, and verify viewport settings.
Only animated or live regions differ Capture occurred at a different animation or data state Disable animations, wait for a stable condition, or hide/mask the volatile region with screenshot styles.
Local passes but CI fails Local and CI environments differ in OS, fonts, browser build, headless mode, or settings Run baseline generation and comparison in the same pinned CI image and browser configuration.
WebKit result does not match Safari on macOS Playwright WebKit is not branded Safari and the host platform differs Run on macOS for the closest Safari experience; treat Linux WebKit as a distinct target.
Increasing tolerance hides meaningful regressions Threshold used to mask a systematic rendering difference Restore a useful threshold and investigate fonts, layout, environment, and timing before accepting the change.

Performance, reliability, and cost considerations

Visual comparisons add browser execution and image comparison work to a test run. Keep the number of platform/browser combinations tied to the coverage you need: each additional combination increases CI work and requires its own baseline maintenance. Reusing a pinned CI image improves repeatability; updating it should be treated as a baseline-affecting change. No universal mismatch rate or runtime applies, so measure the effect in your own CI setup.

For reliability, make the baseline environment explicit and preserve the relevant version and configuration with the test. For cost, Linux CI can be a more affordable option for WebKit coverage, while macOS is the recommended environment when matching Safari most closely; decide which platform-specific confidence your project needs.

Or skip the browser setup

For a one-off screenshot or a capture outside your test suite, ScreenshotNeo provides a screenshot API and MCP server. A single request returns an image or PDF, and the documented capture options include viewport and full-page captures.

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 the request options. Cookie and consent banners, newsletter popups, and chat widgets are removed before capture. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, with response headers indicating the page verdict and billing status. Its MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Learn more at ScreenshotNeo.

Sign up free for 1,000 screenshots a month, with no card required.

FAQ

Why do my Playwright snapshots fail on Linux but pass on Mac?

The baseline and test run likely use different rendering environments. Compare OS image, browser build, fonts, headless mode, viewport, and screenshot scale before changing the threshold.

Can I make Linux and macOS screenshots pixel-identical?

Not reliably across all pages and browser configurations. Control the environment for each baseline and maintain separate snapshots where platform rendering differs.

Does a larger diff threshold fix cross-platform rendering?

No. It changes what the assertion accepts; it does not make rendering the same or identify the cause. Use tolerance only for small, understood differences.

Should I use CSS or device scale?

Choose one deliberately and keep it consistent. CSS scale produces one image pixel per CSS pixel; device scale captures device pixels and may produce larger images on high-DPI displays.