Back to Blog

Visual Regression Testing: How to Compare Screenshots Across Deployments

Visual regression testing catches the bugs that unit tests miss — broken layouts, CSS regressions, overlapping elements, and styling issues that only become visible in the rendered page. By comparing screenshots between deployments, you can detect unintended visual changes before they reach production.

How Visual Regression Testing Works

  1. Baseline capture — Take screenshots of key pages in your known-good state
  2. Comparison capture — Take the same screenshots after code changes
  3. Pixel diff — Compare the two sets and highlight differences
  4. Review — A human reviews the diff to approve or reject changes

Setting Up with a Screenshot API

While tools like Percy and Chromatic offer full-service visual testing, you can build a lightweight pipeline with a screenshot API and an image comparison library.

Step 1: Define Your Critical Pages

const pages = [
  { name: 'home', url: '/' },
  { name: 'pricing', url: '/pricing' },
  { name: 'docs', url: '/docs' },
  { name: 'dashboard-empty', url: '/dashboard' },
  { name: 'blog-listing', url: '/blog' },
];

Step 2: Capture Screenshots in CI

async function captureBaselines(baseUrl: string) {
  for (const page of pages) {
    const url = encodeURIComponent(baseUrl + page.url);
    const res = await fetch(
      `https://pxshot.dev/api/capture?url=${url}&width=1280&height=800&format=png&key=${API_KEY}`
    );
    const buffer = await res.arrayBuffer();
    await fs.writeFile(`screenshots/${page.name}.png`, Buffer.from(buffer));
  }
}

Step 3: Compare with Baselines

import pixelmatch from 'pixelmatch';
import { PNG } from 'pngjs';

function compareScreenshots(baseline: Buffer, current: Buffer): number {
  const img1 = PNG.sync.read(baseline);
  const img2 = PNG.sync.read(current);
  const diff = new PNG({ width: img1.width, height: img1.height });

  const mismatchedPixels = pixelmatch(
    img1.data, img2.data, diff.data,
    img1.width, img1.height,
    { threshold: 0.1 }
  );

  return mismatchedPixels / (img1.width * img1.height);
}

Step 4: Fail the Build on Unexpected Changes

const diffPercentage = compareScreenshots(baseline, current);
if (diffPercentage > 0.01) { // More than 1% pixel difference
  console.error(`Visual regression detected: ${(diffPercentage * 100).toFixed(2)}% change`);
  process.exit(1);
}

Best Practices

When to Run Visual Tests

PxShot's API makes it easy to capture consistent screenshots across environments. See the API docs for all available parameters.

Ready to try PxShot?

Capture any webpage as an image with a single API call. Free tier included.

Get Started Free