A Hosted BackstopJS Alternative — No Config File to Maintain
BackstopJS is the open-source default for visual regression testing: you describe your pages in a backstop.json file, run backstop test, and get an HTML report of what changed. It is free, it is MIT licensed, and for a developer who is comfortable in a terminal it works well.
Diffy answers the same question — did this page change? — as a hosted service with a browser UI instead of a config file. This page is an honest account of what you gain and what you give up moving between them.
What each one costs
BackstopJS is free. There is no licence fee and no per-screenshot cost, at any volume. What it costs instead is indirect: somewhere to run the tests, somewhere to keep reference images and HTML reports so the team can see them, and the engineering time to keep the configuration current as the site changes.
Diffy is priced per screenshot per month, counting each page at each breakpoint. A 20-page site at three breakpoints, run daily, is roughly 1,800 screenshots a month.
| Screenshots per month | Billed annually | Month-to-month |
|---|---|---|
| 2,000 | $67/mo | $80/mo |
| 8,000 | $125/mo | $150/mo |
| 30,000 | $250/mo | $300/mo |
There is also a free plan — 500 screenshots a month, two environments, one month of history — which is enough to test the idea on a real site before paying anything.
The honest framing: if your team already runs Node tooling in CI and someone owns the config, BackstopJS is hard to beat on price. If the person who wants visual testing is a designer, a site owner or an agency PM, the maintenance you avoid is the thing you are actually buying.
Setup: a config file vs a browser tab
BackstopJS is configured in backstop.json — or in a backstop.js module if you want comments — checked into your repository. You define viewports and scenarios, then drive it from the CLI:
backstop init # scaffold the config
backstop reference # capture the baseline
backstop test # capture and compare
backstop approve # promote the test result to the new baseline
That file is a real advantage: it lives in version control, it reviews like code, and it gives you per-scenario granularity. Each scenario can have its own delay, its own hideSelectors, its own readySelector. It is also the thing someone has to maintain, and the reason a non-developer cannot add a page.
Diffy’s equivalent is a browser tab. You paste the URL list into the project, pick breakpoints, and press a button. The URLs, the waits, the elements to mask, the login credentials and the schedule are all fields in the UI, editable by whoever needs to change them.
Diffy settings do export to YAML and import back, and Diffy keeps a revision history of settings changes — so you can version a project’s configuration if you want to, without that being the only way to edit it.
One genuine trade: Diffy applies most settings per project, where BackstopJS applies them per scenario. If one page on your site needs a four-second delay and the rest need none, BackstopJS models that more precisely.
Where the screenshots are taken
BackstopJS runs on your machine or your CI runner. Nothing leaves your network, which matters if you are testing something that cannot be reached from the public internet or cannot be sent to a third party. It ships a Docker image (backstop test --docker) specifically so rendering is consistent across developer machines and CI.
Diffy runs on its own infrastructure by default, and also offers a local worker — a Docker container that captures screenshots on your machine and uploads them for comparison. There are documented setups for DDEV, Lando, Docksal, plain Docker and ngrok.

For sites behind a firewall or a strict CDN, Diffy can also route all traffic through a single IP address so it can be allowlisted, and there is an on-premises option.
How a long page gets captured
The two tools take genuinely different approaches to pages taller than one screen, and each approach has a characteristic failure.
BackstopJS captures the viewport in sections and stitches them together. The failure mode is floating elements: a sticky header that follows the scroll can end up repeated, or land somewhere unexpected in the stitched image.
Diffy opens the page in a very tall browser window and captures it in one pass. The failure mode is relative heights: a hero section set to 100vh will stretch to the full height of that tall window. Diffy overrides those styles behind the scenes to prevent it.
Neither is universally correct. If your site is full of sticky and scroll-triggered elements, the tall-viewport approach usually produces fewer surprises. If your site leans heavily on viewport-relative sizing, the stitching approach avoids a class of problem Diffy has to work around.
Comparison that understands vertical shifts
This is the difference that changes day-to-day review, and it is worth being precise about.
BackstopJS compares images pixel by pixel, with misMatchThreshold to set how much difference is tolerated. That is the correct default behaviour — but it has a well-known consequence. Add one line to your header, and every pixel below it moves down. Every one of those pixels genuinely differs, so the whole page lights up red, on every page that shares the header.
Diffy runs a custom algorithm alongside pixel-perfect comparison that recognises vertical shifts. The same change highlights the header and leaves the 4,000 pixels that merely moved alone. You can switch to strict pixel-perfect comparison per comparison, or set it as the project default, and you can tune sensitivity.

Keeping real pages quiet
Most of the work in visual regression testing is not capturing screenshots, it is stopping them from reporting changes you do not care about. Both tools solve this; they differ in where the solution lives.
| BackstopJS | Diffy | |
|---|---|---|
| Hide an element | hideSelectors — sets visibility: hidden | Mask — paints a visible rectangle, so reviewers can see what was hidden |
| Remove an element | removeSelectors — sets display: none | Removes the node from the DOM |
| Wait before capture | delay, readyEvent, readySelector | Delay setting, plus scroll-to-bottom |
| Dynamic text | Use static content stubs | Mock content — replace selector contents with placeholder text |
| Log in first | Custom script plus saved cookies | Presets for Drupal, WordPress and Netlify, plus custom |
| Custom CSS / JS | onBeforeScript, onReadyScript files | Fields in project settings |
| Cookies, headers, User-Agent | cookiePath, engine options | Fields in project settings |
| Retina, dark mode | Custom script | Checkboxes |
Two of those deserve more than a table row.
Mocking dynamic content. BackstopJS’s own guidance is to test against static content stubs, which is sound advice and often impossible on a live CMS site where editors publish between runs. Diffy takes a list of selectors and replaces their contents with placeholder text, so a news listing stops reporting a change every time an article is published.

Logging in. In BackstopJS this is a scripting job — there are community write-ups covering the combination of a custom script and saved cookie data. In Diffy it is a radio button and two fields.

Reviewing and sharing the results
BackstopJS produces a local HTML report with an approval UI, and backstop remote serves it over HTTP. The practical friction is distribution: the report is a folder of files on whichever machine ran the test, so getting it in front of a client or a colleague means hosting it somewhere and keeping the history yourself.
Diffy keeps every screenshot and comparison in the cloud, so history and sharing come for free:
- Thumbnail view, with approval directly from thumbnails
- The same change grouped across every screenshot it appears in, so you approve it once
- Approve an individual change, a whole screenshot, or a page across all breakpoints
- Before/after slider and keyboard shortcuts for moving through a large set
- HTML source and the JavaScript console captured with the screenshot, for debugging
- Shareable links that work for people without a Diffy account
- Six months of history on paid plans; one month on the free plan

Environments and scheduled monitoring
BackstopJS works with a reference set and a test set. referenceUrl lets you point a scenario’s baseline at a completely different URL — so https://example.com/about-us can be compared against https://staging.example.com/new-about-us-page. That is flexible in a way Diffy is not.
Diffy models environments instead: production, staging and development are first-class, plus custom ones. Pages are matched by path against a base URL, so /about-us on production is compared with /about-us on staging. You lose the arbitrary URL mapping; you gain a model where “does staging still match production?” is the default question rather than something you configure.
That model also enables scheduled monitoring: Diffy can run daily or weekly and compare an environment against itself over time, which catches changes on a live site that nobody deployed — an expired plugin, a third-party script, a CDN change. BackstopJS can be put on a cron job, but you supply the scheduler, the storage and the alerting.
Notifications go out by email, Slack or webhook, with configurable thresholds.
Speed
BackstopJS is fast. Running dozens of pages across several breakpoints locally completes in a few minutes.
Diffy is slower per screenshot — plan for roughly 30–60 seconds each, depending on page weight and how many concurrent workers you allow. The reason is partly that Diffy is doing more per capture, and partly deliberate: hammering a production server with parallel requests is a good way to get rate-limited by a CDN or to distort the very page you are measuring. You can raise the worker count when the target can take it.

CI/CD and integrations
BackstopJS integrates by being a Node package: install it, run backstop test --docker in your pipeline, and handle the exit code. The one persistent chore is the report — you have to publish it somewhere the team can reach after the job ends.
Diffy provides:
- A CLI for CI/CD, with worked examples for Pantheon, Tugboat, Platform.sh, CircleCI, GitLab and GitHub Actions
- A GitHub Action that posts results back to the pull request
- Zapier, so a diff can open a ticket in your tracker
- Figma — compare a built page against the design export
- Screenshot upload from Playwright or any other functional testing framework, using Diffy purely as the comparison and review layer
- Bulk operations for triggering comparisons across many projects at once
Because the report lives in the cloud, the CI step only has to post a link.
Driving Diffy from Claude
Diffy publishes a Claude plugin that runs visual testing from a conversation rather than a dashboard or a CI config. It installs in two lines:
/plugin marketplace add diffywebsite/diffy-skills
/plugin install diffy@diffy
That gives you skills under the /diffy: namespace covering project setup, capture (locally through the screenshot-worker container, or remotely on Diffy’s servers), comparison, and end-to-end runs that return a percentage changed, a per-page table and a JUnit report. The plugin is MIT licensed and developed in the open at github.com/DiffyWebsite/diffy-skills.
Where BackstopJS is the better fit
We would rather you picked the right tool than the one that emails you.
- You need zero cost at high volume. BackstopJS has no per-screenshot price. If you are testing thousands of pages and have somewhere to run it, that is decisive.
- Nothing may leave your infrastructure. BackstopJS runs entirely on your own machines. Diffy’s local worker keeps capture local but still sends images to Diffy for comparison.
- You are testing interactions, not page loads.
clickSelectors,hoverSelectors,keyPressSelectorsandpostInteractionWaitlet you screenshot a menu open, a tooltip showing, a form in an error state. Diffy can reach some of this with custom JavaScript, but BackstopJS models it directly. - You want element-level screenshots.
selectorsandselectorExpansioncapture individual components rather than whole pages. Diffy works at the page level. - You need Firefox. BackstopJS can run Chromium, Firefox or WebKit through its Playwright engine option. Diffy gives you Chrome and WebKit.
- You need per-page configuration. Different delays and selectors per scenario is a real capability, and Diffy’s project-level settings do not replicate it exactly.
- Your baselines are arbitrary URL pairs.
referenceUrlhas no direct Diffy equivalent.
Project status, as of this writing
BackstopJS is MIT licensed and installable today. Its most recent release on npm is 6.3.25, published in September 2024. It requires Node 16 or above and ships both Puppeteer (the default engine) and Playwright. The README states that the project “was created and is maintained by Garris Shipon with help from these amazing engineers”, linking to the contributor list.
We are not going to tell you the project is dead — it is widely deployed, it works, and it has a real contributor history. We would say only that a tool sitting at the centre of your QA process is worth checking the repository for before you commit to it for the next three years, and that a project with one named maintainer carries a different risk profile than one with a company behind it — in both directions.
BackstopJS version, release date, licence and dependency facts verified against the npm registry and the project README in August 2026. Diffy prices as published on our pricing page in August 2026.Frequently asked questions
Is BackstopJS still maintained?
BackstopJS is MIT licensed and still installable. Its most recent release on npm is 6.3.25, published in September 2024, and the package is published under a single maintainer account. Check the GitHub repository for the current state before you commit to it for a long-lived project.
Is Diffy a drop-in replacement for BackstopJS?
No. There is no automatic converter for a backstop.json file. You recreate the project in Diffy by pasting your URL list, choosing breakpoints, and moving your hide and remove selectors into the project settings. For a typical scenario file this takes a few minutes — but scripted interactions written as onBeforeScript or onReadyScript files need to be rewritten as custom JavaScript in Diffy.
Can I use BackstopJS for free?
Yes. BackstopJS is open source under the MIT license and there is no licence fee at any volume. The costs are indirect: somewhere to run it, somewhere to keep reference images and reports, and the engineering time to maintain the configuration.
Can Diffy take screenshots of a local development site?
Yes. Diffy provides a local worker that runs as a Docker container, takes screenshots on your machine and uploads them for comparison. There are documented setups for DDEV, Lando, Docksal, plain Docker and ngrok.
Why does BackstopJS highlight a whole page when only the header changed?
Pixel-perfect comparison flags every pixel that differs. Add a line to a header and everything below it moves down, so every pixel below the header genuinely differs and the diff lights up. Diffy runs a custom algorithm alongside pixel-perfect comparison that recognises vertical shifts and highlights only the element that actually changed.
Try it
Create an account, paste your URLs, and run your first comparison — the free plan covers 500 screenshots a month and there is nothing to uninstall if it is not for you.
If you are comparing more than one option, our Percy comparison covers the other end of the market, and what visual regression testing is covers the basics.