English ·
Deutsch
A TUI tool for detecting visual regressions on websites. It automatically creates full-page screenshots of all pages in a sitemap and compares them against stored references via pixel diff.
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/michaelblaess/visual-regression-scanner/main/install.sh | bashWindows (PowerShell):
irm https://raw.githubusercontent.com/michaelblaess/visual-regression-scanner/main/install.ps1 | iex- Automatic screenshots of all URLs from an XML sitemap
- Pixel-diff comparison against stored references (baselines)
- Configurable threshold for permitted deviations
- TUI with live updates, filter, detail view
- Dynamic scan button - shows the current state in the footer
- Result cache (
results.json) - avoids recomputation on startup - HTML reports with embedded before/after/diff images (Base64)
- JSON reports for CI/CD integration
- Consent handling (Usercentrics, OneTrust, CookieBot)
- Lazy-loading detection - scrolls through pages and waits for images
- Parallel processing with configurable concurrency
# Windows
.\bootstrap.ps1
# Linux/macOS
./bootstrap.shThe bootstrap script creates a virtual environment, installs all dependencies, and downloads Chromium.
# Start the TUI
visual-regression-scanner https://example.com/sitemap.xml
# With increased tolerance
visual-regression-scanner https://example.com/sitemap.xml --threshold 0.5
# Smaller viewport
visual-regression-scanner https://example.com/sitemap.xml --viewport 1280x720
# Save HTML report automatically
visual-regression-scanner https://example.com/sitemap.xml --output-html report.html
# Only specific URLs
visual-regression-scanner https://example.com/sitemap.xml --filter /produkte
# With auth cookie
visual-regression-scanner https://example.com/sitemap.xml --cookie auth=token123| Parameter | Default | Description |
|---|---|---|
SITEMAP_URL |
- | URL of the sitemap (XML) |
--screenshots-dir PATH |
./screenshots |
Root directory (one subfolder per site) |
--threshold FLOAT |
0.1 |
Diff threshold in percent |
--viewport WxH |
1920x1080 |
Viewport size |
--concurrency N |
4 |
Max parallel browser tabs |
--timeout SEC |
30 |
Timeout per page in seconds |
--rate-limit N |
60 |
Max pages per minute (0 = no limit) |
--ignore-robots |
false |
Ignore robots.txt |
--output-json PATH |
- | Save JSON report automatically |
--output-html PATH |
- | Save HTML report automatically |
--no-headless |
false |
Start browser visibly |
--no-full-page |
false |
Screenshot only the visible area |
--filter TEXT |
- | Only URLs containing TEXT |
--user-agent UA |
Chrome 131 | Custom user agent |
--cookie NAME=VALUE |
- | Set cookie (can be used multiple times) |
Press s in the TUI to open the settings. They are stored in
~/.visual-regression-scanner/settings.json and cover diff threshold, viewport, full-page
capture, parallel tabs, rate limit, timeout, robots.txt, visible browser, user agent, cookies and
proxy - plus interface language and theme.
Command-line flags take precedence for the current run without changing the stored values. Only flags you actually pass override anything; everything else comes from the settings.
The detail pane shows the selected capture directly in the terminal - switch between reference, current and difference. By default the image is drawn from Unicode half blocks, which renders safely in any terminal; enable graphical preview in the settings for pixel-accurate output via Sixel or the Kitty protocol. The browser comparison view is still one button away.
h opens the history of previously checked sitemaps with viewport and result, so you can pick
one instead of typing the URL again.
| Key | Action |
|---|---|
c |
Start scan (dynamic text, see below) |
r |
Reset (delete all images + reload sitemap) |
R |
Save reports (HTML + JSON) |
o |
Open images in browser (lightbox with zoom) |
l |
Toggle log |
e |
Show diffs only |
/ |
Focus filter |
s |
Settings |
u |
Enter sitemap URL |
h |
History of checked sitemaps |
i |
About dialog |
q |
Quit |
Drag the handle above the log area to resize it. Copy, export and hide live in the log area's context menu (right-click).
The text of the scan button (c) adapts automatically to the current state:
| State | Button Text |
|---|---|
| No reference available | c Scan (create reference) |
| Reference available, no captures | c Scan (vs. reference) |
| Reference + captures available | c Scan (choose mode) |
Every page is fully rendered in a real browser to take the screenshot: scripts, fonts and images are loaded, and the request bypasses the server's caches. With full-page captures the tool additionally scrolls through the entire page so lazy-loaded content appears. One page therefore weighs several times an ordinary HTTP request - and a run touches every page of the sitemap.
The scanner is therefore rate-limited out of the box: 60 pages per minute.
visual-regression-scanner https://www.example.com/sitemap.xml --rate-limit 20 # gentler
visual-regression-scanner https://www.example.com/sitemap.xml --rate-limit 0 # no limit - carefulNote that --concurrency is not a rate limit: it caps how many browser tabs run at the same
time, not how many pages go out per minute.
robots.txt is honoured by default for the pages from the sitemap; blocked pages are skipped and
reported in the log. Use --ignore-robots only for systems of your own.
This program retrieves web pages automatically and thereby places load on the target systems. Depending on its settings, that load can exceed the load of an ordinary visitor many times over and can impair the availability of the target system.
By using it, you declare that:
- You will use this program only against systems for which you hold explicit authorisation from their operator.
- You bear sole responsibility for its use, for the settings you choose and for all consequences arising from them.
- Before running it against a production system, you will verify that the configured limits are appropriate for that system.
The software is provided free of charge and without warranty of any kind ("as is"), as set out in section 7 of the Apache License 2.0. The liability of the author (Michael Blaess) for damages arising from its use is excluded to the extent permitted by applicable law. Liability for intent and gross negligence, for injury to life, body or health, and under mandatory product liability law remains unaffected.
On first start the program asks you to confirm this notice.
The interface is fully available in English and German - menus, messages, settings, the
log and the command line help. Switch it in the settings (s); the choice is stored and applies
from the next start.
On the very first start the system environment decides: German only for a demonstrably German-speaking environment, everything else falls back to English.
visual-regression-scanner https://example.com/sitemap.xml- Press
s- footer shows "Scan (Referenz erstellen)" - Screenshots are created and automatically saved as the reference, status "NEU"
- Afterwards the footer shows "Scan (vs. Referenz)"
- Press
s- footer shows "Scan (vs. Referenz)" - New screenshots are created and compared against the reference
- Result: "OK" (identical) or "DIFF" (visual difference)
- Afterwards the footer shows "Scan (Modus waehlen)"
When both reference images AND current captures already exist,
the footer shows "Scan (Modus waehlen)" and pressing s
opens a dialog with two options:
Option A: Scan again
- New screenshots replace the current captures
- The reference remains unchanged
- Comparison: new screenshots vs. existing reference
Option B: Update reference + scan
- The current captures become the new reference
- The old reference is deleted
- A new scan creates new captures
- Comparison: new screenshots vs. new reference (= previous captures)
- Status "OK" = no difference, "DIFF" = visual change
- Press
R(Shift+R) - HTML report with before/after/diff images - Press
o- open images in browser (lightbox with zoom)
After each scan, the comparison results are stored in a results.json
in the site directory. On the next start, the results are loaded
from the cache instead of recomputing all diffs. The cache is
automatically invalidated when the image files have changed.
A subdirectory based on the hostname is created automatically per site:
screenshots/
www.example.com/
baseline/ # Stored reference screenshots
metadata.json # URL -> filename mapping, timestamps
{url_hash}.png # Reference images (SHA256 hash of the URL)
current/ # Current captures (last scan)
{url_hash}.png
diffs/ # Diff images (identical areas dimmed, changes in red)
{url_hash}.png
results.json # Result cache (diff values + file timestamps)
shop.example.com/
baseline/
current/
diffs/
results.json
- Python 3.12+
- Textual (TUI framework)
- Playwright (browser automation)
- Pillow (image comparison)
- httpx (HTTP client)
- Rich (formatted output)
git tag v1.6.1
git push origin v1.6.1Push the tag explicitly: git push --follow-tags leaves lightweight tags behind, and the
release build never starts.
GitHub Actions automatically builds executables for Windows, Linux, and macOS.