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 monthBilled annuallyMonth-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.

Logos of DDEV, Lando, Docksal and Docker, the local development environments Diffy's screenshot worker supports.
Testing a site that only exists on your laptop, without making it publicly reachable.

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.

Diffy's comparison algorithm switcher, offering Custom highlight and Pixel perfect, with an option to set the choice as the default algorithm for the project.
Switch algorithms per comparison, or set a default for the project.

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.

BackstopJSDiffy
Hide an elementhideSelectors — sets visibility: hiddenMask — paints a visible rectangle, so reviewers can see what was hidden
Remove an elementremoveSelectors — sets display: noneRemoves the node from the DOM
Wait before capturedelay, readyEvent, readySelectorDelay setting, plus scroll-to-bottom
Dynamic textUse static content stubsMock content — replace selector contents with placeholder text
Log in firstCustom script plus saved cookiesPresets for Drupal, WordPress and Netlify, plus custom
Custom CSS / JSonBeforeScript, onReadyScript filesFields in project settings
Cookies, headers, User-AgentcookiePath, engine optionsFields in project settings
Retina, dark modeCustom scriptCheckboxes

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.

Diffy's Mock Content Before Taking A Screenshot settings, showing a CSS selector field next to a content type dropdown, and the available mock types: title, paragraph, large paragraph, phone number and number.
Mocking dynamic content: a CSS selector and the type of placeholder to substitute.

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.

Diffy project settings showing the Authenticate User Before Screenshot options, with presets for Custom, Drupal, WordPress and Netlify, and username and password fields.
Login presets for Drupal, WordPress and Netlify, plus a custom option.

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
Diffy's review dashboard comparing Prod 8 May against Stage 8 May, with tabs for changed pages, unreviewed and with bugs, and page thumbnails each carrying an Approve button.
Reviewing a production-versus-staging run from thumbnails.

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.

Diffy CLI commands for triggering screenshot and comparison jobs from a CI pipeline.
Diffy’s CLI covers the same automation ground as the BackstopJS binary, without owning the storage.

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, keyPressSelectors and postInteractionWait let 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. selectors and selectorExpansion capture 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. referenceUrl has 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.