Choosing a tool
There are more visual regression tools than any team needs, and most of them are fine. The choice comes down to four questions about your situation, not about the tools.
1. What do you screenshot?
- Components in isolation (a design system, a Storybook): tools that render stories are the natural fit. Loki, Lost Pixel and the hosted services all take a Storybook build; Vitest browser mode and Playwright component tests screenshot components without Storybook.
- Pages and flows in a real browser: the screenshot assertion of your end-to-end runner (Playwright's
toHaveScreenshot, a Cypress plugin), or a standalone crawler like BackstopJS that works from a list of URLs. - Native screens: a per-platform tool (Roborazzi or Paparazzi on Android, swift-snapshot-testing on iOS, Flutter's golden tests, Maestro across both).
Most teams end up with two: a component-level suite for the design system and a page-level suite for the key flows.
2. Where should comparison and review happen?
Local tools compare on the machine that ran the tests and leave images on disk. You own everything, pay nothing, and build (or borrow) the review step yourself. They suit teams that already have a CI with artifacts and want the state in git.
Hosted services take screenshots or DOM snapshots and compare, store and show them on their side. You get a review UI, PR integration, baseline history and cross-browser rendering on day one, and in exchange you pay per screenshot, depend on the service for every run, and your baselines live outside the repository. They suit teams who want the workflow without building it, and teams with many contributors on different machines.
Self-hosted services (reg-suit on your own S3 bucket) sit in between: the service model without the vendor.
3. How much noise can you remove at the source?
If you can run comparisons in a pinned renderer, a local tool with repository baselines is stable and cheap. If you cannot (many contributors on many OSes, no Docker in CI), a service that renders on its side removes the problem by taking rendering away from you.
4. What do you need to read back?
This is the question nobody asks and everyone regrets. Once the run is over, something has to tell the reviewer what failed and where the images are, and something has to approve. Tools that leave only image folders force you to walk directories; tools that write a machine-readable result (a JSON report, CTRF, the manifest) let you build the PR comment, the approval job or the dashboard once and keep it when you switch tools. Hosted services keep the results inside their app, which is convenient until you want them elsewhere. The comparison has a column for this.
Reasonable defaults
- Playwright users: start with
toHaveScreenshot, a pinned Docker image and baselines in the repository. Add a review step (PR comment or viewer) from the JSON reporter output, which converts to a manifest. - Cypress users: a plugin that compares in the runner and shows the diff in the Cypress UI; pixsame writes the manifest natively, cypress-image-snapshot and cypress-visual-regression have converters.
- Storybook users: Lost Pixel or Loki locally, Chromatic if you want the hosted review and can pay per snapshot.
- No end-to-end suite yet: BackstopJS, which needs only a list of URLs, or a hosted service with a static upload.
- Mobile: the per-platform tool your framework recommends; Roborazzi writes a JSON summary, which makes it the easiest to integrate into review tooling.
Keep the exit open
Whatever you choose, keep two things in your control: the baselines (export them, or keep them in git) and the results format (a file you can read without the vendor). A tool that writes or converts to the manifest can be swapped for another one without changing the review step, which is the whole point of having a common format.
Now go read the comparison, filter by your category, and pick something. The best tool is the one your team will actually review failures from.