Skip to content

Pixelmatch Same-Size Constraint

When to Use

Use this when the two images you want to diff have different dimensions — or when preventing that situation.

Decision

Cause Fix
Different viewport size between captures Capture at the same viewport
Content growth changes total page height — the common one under fullPage: true Cap what grows (a pager, an items-per-page limit) or capture a surface that does not embed an uncapped listing
Lazy-loaded content changes total page height Force-load lazy content; use fullPage: true consistently
Zoom level / DPR difference Pin deviceScaleFactor and scale
Genuinely different content sizes Normalize before pixelmatch — resize or pad to a target size

Under fullPage: true the image is as tall as the document — Playwright takes the largest of body/documentElement scrollHeight, offsetHeight, and clientHeight — so one new row in an uncapped listing changes the image height and every baseline for that surface stops comparing. Masking does not help: a mask paints over a region at its current size, it does not fix the size.

Pattern: resize to common size

import sharp from 'sharp';

const target = { width: 1440, height: 900 };

const img1 = await sharp('img1.png').resize(target).raw().toBuffer({ resolveWithObject: true });
const img2 = await sharp('img2.png').resize(target).raw().toBuffer({ resolveWithObject: true });

const diff = Buffer.alloc(target.width * target.height * 4);
pixelmatch(img1.data, img2.data, diff, target.width, target.height, { threshold: 0.1 });

Note: resizing introduces interpolation; the diff result is no longer pixel-faithful. Prefer fixing the capture so dimensions match natively.

Behavior on Mismatch

Caller Behavior
CLI Prints Image dimensions do not match: WxH vs WxH and exits 65 — no diff written
API Throws Error('Image sizes do not match. Image 1 size: …, image 2 size: …') — no diff written
Playwright toHaveScreenshot() Pads both images to the larger of the two sizes, runs the diff, writes a diff PNG — and fails regardless of tolerance

No tolerance applies to a size change. Playwright reports the size mismatch unconditionally, alongside any pixel mismatch, so threshold, maxDiffPixels, and maxDiffPixelRatio have no bearing on the outcome — a reader who has just tuned a tolerance will otherwise not understand why it did nothing. The diff PNG it writes is not much help either: the shorter image is padded with transparent black, so the whole extra height shows as difference. It tells you the page grew, not what changed.

Common Mistakes

  • Wrong: Resizing to a smaller-than-source dimension and expecting precise diffs — interpolation creates artifacts that pixelmatch interprets as differences
  • Wrong: Trying to diff against a screenshot that grew because of new content — the diff is meaningless; the test should fail at the capture stage
  • Wrong: Padding with arbitrary color where only one image is padded — the padded region adds artificial diff signal
  • Wrong: Raising a tolerance to get past a size mismatch — it cannot work; the size error is reported regardless of every tolerance key

See Also