amagi-site-diff
See what changed between two versions of a website before your client does.
amagi-site-diff takes two base URLs (production and staging, or the old build and the new one),
crawls the same pages on both, screenshots each page in headless Chromium, and writes one
markdown report: pixel-diff images, changed regions named by page element, text diffs, new console
errors, broken requests, and pages that went missing.
It's for freelancers and agencies shipping redesigns, CMS migrations and theme updates who want a page-by-page check before launch. The report is plain markdown, so you can read it yourself or hand it to Claude.
Demo
Install
pipx install amagi-site-diff
(Not yet published to PyPI. Until it is, install from a clone of this repo with
pipx install ..)
Requires Python 3.10+. The first run downloads Playwright's Chromium if it isn't
already installed. To use the Chrome or Edge you already have instead, pass --channel chrome or
--channel msedge.
Usage
amagi-site-diff https://example.com https://staging.example.com
A is "before", B is "after". Starting from /, it follows links on both sides, staying on each
site's own origin and path, and compares up to 20 pages. Either side can also be a local folder,
such as a static build, which is served on 127.0.0.1 for the run.
This repo ships two versions of a fictional bike shop site, so you can try it without touching a real one:
cd examples
amagi-site-diff site-v1 site-v2
A: site-v1 (local folder)
B: site-v2 (local folder)
Comparing up to 20 pages, following links...
/ changed 1.61% pixels, 3 region(s); text +3 -3
/services/ changed 0.76% pixels, 3 region(s); text +1 -1; meta description; 2 new console error(s); 1 new failed request(s)
/about/ identical
/contact/ missing on B B: HTTP 404
/blog/ new on B A: HTTP 404
/blog/winter-chain-care/ new on B A: HTTP 404
6 page(s) compared: 2 changed, 1 identical, 1 missing on B, 2 new on B
Report: site-diff-report/report.md
The report
site-diff-report/report.md opens with a summary table, then one section for each page that
differs. Each section has a diff image: B faded to grey, changed pixels in red, and numbered
blue boxes around each changed region.
The boxes are listed with the element under them on each side, followed by the text diff:
1. `160,214 225x42` (9,039 px): B `main > a.button` "Book a repair"; A `main > a.button` "See services and prices"
2. `384,172 689x18` (5,885 px): B `main > p.lead:nth-of-type(1)` "Drop your bike off before 11 am and pick it up the same a..."; A `main > p.lead:nth-of-type(1)` "Drop your bike off before 10 am and pick it up the same a..."
-Drop your bike off before 10 am and pick it up the same afternoon. Flat tyres, brakes, gears and full tune-ups.
-See services and prices
+Drop your bike off before 11 am and pick it up the same afternoon. Flat tyres, brakes, gears and full tune-ups.
+Book a repair
It also catches the problems that don't show up in a screenshot:
- Meta description: "Repair prices." -> "Repair prices, labour included."
Console errors on B only:
- `Uncaught: bookingWidget is not defined`
Failed requests on B only:
- `404 /img/workshop.jpg`
## Missing on B: `/contact/`
A serves this page and B does not. A's title: "Contact | Fernhill Bike Works".
B still links to it from: `/`, `/services/`, `/about/`, `/blog/`, `/blog/winter-chain-care/`. Those links are broken on B.
(Trimmed. The full report has every changed page, region and image link.)
Next to it:
report.json: the same results in machine-readable form.pages/<page>/a.png,b.png,diff.png: full-page screenshots and the diff image, written only for pages that differ.
The images use relative links, so Claude Code can open them alongside the text. Point it at the report ("read site-diff-report/report.md and tell me what will break for users"). The repo's SKILL.md teaches Claude how to run the tool and summarize the report.
Options
amagi-site-diff A B --path /pricing --path /contact --no-crawl # only these pages
amagi-site-diff A B --max-pages 100 # crawl further (default 20)
amagi-site-diff A B --hide "#cookie-banner" --hide ".chat-widget" # hide noise on both sides
amagi-site-diff A B --viewport 390x844 # phone width (default 1280x800)
amagi-site-diff A B --viewport-only # first screenful instead of the full page
amagi-site-diff A B --threshold 40 # ignore smaller colour shifts (default 24 of 255)
amagi-site-diff A B --wait 1500 # extra settle time for slow widgets, in ms
amagi-site-diff A B --keep-query # treat ?page=2 as its own page
amagi-site-diff A B --out diff-report # report folder (default site-diff-report)
amagi-site-diff A B --exit-code # exit 1 when anything differs, for CI
In Git Bash on Windows, write --path pricing without the leading slash. Git Bash rewrites
/pricing into a Windows file path before the tool sees it, and the tool stops with an error.
Exit codes: 0 done, 1 differences found (only with --exit-code), 2 bad arguments, the
browser failed to start, no page loaded on either side, or one site never responded at all
(a typo in the URL or a server that is down).
Limits
- No logins. Pages behind auth are compared as a logged-out visitor sees them.
- Live content is noise. Ads, rotating banners, A/B tests and live data change on every load.
Hide them with
--hide. Animations and transitions are frozen before each screenshot. - Links only. The crawler follows
<a href>links. Pages reached through forms, JavaScript navigation or only a sitemap need--path. - Chromium only. It doesn't render in Firefox or Safari.
- Compare what you're allowed to. It loads every page it finds on both sites. Run it against your own sites, or ones your client has asked you to check.
Why not BackstopJS, Playwright screenshots or Percy?
BackstopJS and Playwright's
toHaveScreenshot() are built for ongoing visual
regression testing. You list scenarios or write a test for each page, store baseline images, and
compare future runs against them. Hosted services such as Percy and
Chromatic add review dashboards on top of the same model.
amagi-site-diff answers a one-off question: "what's different between these two sites right
now?" You give it two URLs. It finds the pages by crawling both, and writes a markdown file a person
or an AI assistant can read, with text diffs and element names next to the images.
If this saved you time
A star helps other freelancers and agencies find this. It costs nothing and means a lot.
More from AmagiLabs
- amagi-legal-review-skills: Claude Code skills for first-pass NDA/MSA/lease review.
- amagi-watch: turn a video URL into a transcript and key-frame index Claude can read.
- github.com/amagilabs: the rest of the AmagiLabs lab.
License
MIT, see LICENSE. Copyright (c) 2026 AmagiLabs (Amagisolutionsgroup, Inc.).
Metadata
Release files for amagi-site-diff 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| amagi_site_diff-0.1.0.tar.gz | 32.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| amagi_site_diff-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 58.1 kB
Release files / amagi_site_diff-0.1.0.tar.gz
| Download URL | amagi_site_diff-0.1.0.tar.gz |
|---|---|
| Size | 32.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7d224539c2c2cf1df664a8794c9998293441eaa4c99bb6347080d47b61d26e61
|
|
BLAKE2b-256 checksum How to use checksums |
f72df0acd7367cccb2465c5ac623415de4b2db002185ad123553e565913a816c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logRelease files / amagi_site_diff-0.1.0-py3-none-any.whl
| Download URL | amagi_site_diff-0.1.0-py3-none-any.whl |
|---|---|
| Size | 25.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a650f34951fcdd41a763c5cb1181d99a95c1fcac661c1693382afa8ec45322c2
|
|
BLAKE2b-256 checksum How to use checksums |
cdedbfd20b374c5cc7d0cd64ee8a359948dfae4cddb1337ee8e936df710945cd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logSecurity for amagi-site-diff 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for amagi_site_diff-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.