Use Case

Visual Regression Testing
Automated Screenshot Comparison for CI/CD

Catch CSS regressions, layout shifts, and styling bugs before they reach production. Capture pixel-perfect screenshots via API, compare against baselines, and fail builds automatically when visual diffs exceed your threshold.

The problem

Unit tests don't catch visual bugs

Your tests pass, your components render, but a CSS change just broke the checkout page layout on mobile. Unit tests and integration tests verify logic — they can't see that a button moved off-screen, a font changed weight, or a modal overlay shifted 20 pixels to the left.

Visual regression testing fills this gap. By comparing screenshots of your UI before and after changes, you catch every pixel-level difference. SnapRender's API makes this trivial — no browser infrastructure to manage, no Puppeteer servers to maintain. Just an API call.

How it works

Four steps to visual testing

1

Capture baseline screenshots

Use SnapRender to screenshot your pages at specific viewport sizes (desktop, tablet, mobile). Store these as your golden baseline images.

2

Deploy and capture again

After code changes, capture the same pages at the same viewports. SnapRender ensures consistent rendering — no flaky font loading or timing issues.

3

Compare pixel-by-pixel

Use pixelmatch (Node) or Pillow + NumPy (Python) to diff the images. Generate a visual diff highlighting exactly what changed in red.

4

Pass or fail the build

Set a diff threshold (e.g., 0.1%). If visual changes exceed it, fail the CI build and output the diff image for developer review.

Code examples

Visual testing in any language

Python + Pillow
import requests
from PIL import Image
import numpy as np

API = 'https://api.snaprender.dev/v1/screenshot'
HEADERS = {'Authorization': 'Bearer YOUR_KEY'}

def capture(url, name):
    resp = requests.post(API, headers=HEADERS, json={
        'url': url,
        'width': 1280,
        'height': 800,
        'format': 'png',
        'full_page': True
    })
    with open(f'{name}.png', 'wb') as f:
        f.write(resp.content)

# Step 1: Capture baseline
capture('https://staging.example.com', 'baseline')

# Step 2: Deploy changes, capture new version
capture('https://staging.example.com', 'current')

# Step 3: Compare images
baseline = np.array(Image.open('baseline.png'))
current = np.array(Image.open('current.png'))

diff = np.abs(baseline.astype(int) - current.astype(int))
changed_pixels = np.sum(diff > 10)  # threshold
total_pixels = baseline.shape[0] * baseline.shape[1]
diff_percent = (changed_pixels / total_pixels) * 100

print(f'Visual diff: {diff_percent:.2f}%')
if diff_percent > 0.1:
    print('FAIL: Visual regression detected!')
    exit(1)
Node.js + pixelmatch
const fs = require('fs');
const { PNG } = require('pngjs');
const pixelmatch = require('pixelmatch');

const API = 'https://api.snaprender.dev/v1/screenshot';
const HEADERS = {
  'Authorization': 'Bearer YOUR_KEY',
  'Content-Type': 'application/json'
};

async function capture(url) {
  const res = await fetch(API, {
    method: 'POST',
    headers: HEADERS,
    body: JSON.stringify({
      url,
      width: 1280,
      height: 800,
      format: 'png',
      full_page: true
    })
  });
  return Buffer.from(await res.arrayBuffer());
}

// Capture baseline and current
const baseline = PNG.sync.read(await capture(url));
const current = PNG.sync.read(await capture(url));
const { width, height } = baseline;
const diff = new PNG({ width, height });

const mismatch = pixelmatch(
  baseline.data, current.data, diff.data,
  width, height, { threshold: 0.1 }
);

const diffPercent = (mismatch / (width * height)) * 100;
console.log(`Visual diff: ${diffPercent.toFixed(2)}%`);

if (diffPercent > 0.1) {
  // Save diff image for review
  fs.writeFileSync('diff.png', PNG.sync.write(diff));
  process.exit(1);
}
Why SnapRender

Skip the browser infrastructure

No Puppeteer servers

Don't maintain headless Chrome instances. SnapRender handles rendering, fonts, and browser updates for you.

Consistent rendering

Same browser version, same fonts, same environment every time. No flaky tests from OS-level differences.

Multiple viewports

Test desktop (1280px), tablet (768px), and mobile (375px) with a single API — just change the width parameter.

Full-page capture

Capture entire scrollable pages with full_page: true. Test the complete user experience, not just the fold.

Simple pricing for visual testing

Each screenshot counts as one request. Test 10 pages across 3 viewports = 30 requests per build.

$0
100 screenshots/mo
$9
1,500 screenshots/mo
$29
5,000 screenshots/mo
Start Free

Frequently asked questions

Visual regression testing compares screenshots of your UI before and after code changes to detect unintended visual differences. It catches CSS regressions, layout shifts, and styling bugs that unit tests miss.

SnapRender's Screenshot API captures pixel-perfect screenshots of any URL or HTML. You take a baseline screenshot, make your code changes, take another screenshot, then compare the two images programmatically to detect differences.

Yes. Call the SnapRender API from your CI scripts (GitHub Actions, GitLab CI, Jenkins, etc.) to capture screenshots after each build. Compare against stored baselines and fail the build if visual diffs exceed your threshold.

SnapRender returns PNG (lossless, ideal for pixel comparison) or JPEG. For visual testing, always use PNG to avoid compression artifacts that cause false positives.

Pixel-level comparison catches even single-pixel differences. You can set a diff threshold (e.g., 0.1% tolerance) to ignore anti-aliasing differences across environments while still catching real regressions.

Each screenshot counts as one API request. The free tier includes 100 requests/month. At $9/mo for 1,500 requests, you can test dozens of pages across multiple viewports on every deploy.

Never ship a visual bug again.

Automated screenshot comparison in your CI/CD pipeline. Start free with 100 requests/month.

Start Free — 100 requests/month