Visual regression testing without running browsers in CI

Capture the same pages on every deploy and compare them against a baseline. No Puppeteer in your pipeline, no Chromium download, no container that needs fonts.

Running headless Chrome inside CI means a large download, a container that needs fonts installed, and a class of flake that only shows up on the build machine.

If the pages are reachable over HTTP, capture them from outside instead.

for page in / /pricing /docs; do
  name=$(echo "$page" | tr '/' '_')
  curl -s -o "shots/${name}.png" \
    "https://api.screenshotline.com/take?url=https://example.com${page}&viewport_width=1280&full_page=true&cache=false" \
    -H "X-Access-Key: $KEY"
done

Then compare against the committed baseline with whatever image diff you already use.

The settings that make diffs stable

cache=false. A cached image is yesterday's render, which is the opposite of what a regression test wants.

A fixed viewport. Width changes layout, so pin it rather than relying on a default that might change.

block_ads=true and block_cookie_banners=true, both on by default. Third-party content is the main source of false positives in visual diffs.

hide_selector for anything that animates forever. The renderer waits for finite animations, but a carousel that rotates on a timer will differ on every capture and no renderer can fix that for you.

Check more than the pixels

Two response headers are worth asserting on in the same test:

  • X-Blank-Suspected: false, so a page that failed to render does not pass as "no visual change".
  • X-Upstream-Status: 200, so a deploy serving a 500 page is not compared as though it were content.

That turns a pixel test into a smoke test with a picture attached.

What this does not replace

Component-level snapshot tests inside your own test runner are faster and more precise for UI units. This is for whole pages, in a real browser, against a deployed environment, which is the part component tests cannot see.

Get a free key — 500 renders a month Read the docs