BackstopJS vs Percy for Visual Regression Testing
Compare BackstopJS’s self-managed screenshot workflow with Percy’s hosted review service, including setup, browser coverage, approvals, CI, cost, and maintenance.
Short answer: Choose BackstopJS if you want to run screenshot capture, comparison, reports, and reference-image updates within infrastructure your team manages. Choose Percy if you want a hosted build and review workflow with managed browser rendering and approvals. The right choice depends on who operates the rendering environment, which browsers and operating systems you must cover, and how your team reviews and accepts visual changes.
Neither is a universal winner. BackstopJS’s README currently says the project needs a new maintainer or owner. That is a project-status signal to include in adoption planning; by itself, it does not establish that the software is unusable or abandoned. Check current release and issue activity before making a long-term dependency decision.
1. What BackstopJS and Percy do
BackstopJS: project-owned capture and reference images
BackstopJS automates visual regression checks by comparing screenshots over time. Its basic workflow is to initialize a project, configure scenarios and viewports, capture test screenshots, inspect a visual report, then approve the intended changes into the reference set. The team owns the configuration and reference-image handling as part of its project workflow. BackstopJS documents Puppeteer and Playwright engine choices, browser and CLI reports, JUnit output for CI, and an optional Docker rendering path.
backstop initcreates a starting project configuration.backstop testcaptures pages and compares them with current references.- Review the report and decide which differences are expected.
backstop approvepromotes the latest captures into the reference set.
Percy: hosted builds, comparisons, and review
Percy integrates with a test run that produces a build containing snapshots. Percy processes snapshots, renders and compares them with a baseline, and presents changes for review and approval. Its hosted browser option manages rendering infrastructure. You can also configure BrowserStack Automate when you need more control over the browser and operating-system combinations used for testing.
Percy provides build and snapshot review, approval states, and source-control status integrations. Approved snapshots can carry forward across builds for a branch. Check your project’s current integration and plan details before relying on a specific behavior.
2. Side-by-side comparison
| Question | BackstopJS | Percy |
|---|---|---|
| Where does capture and comparison run? | In your project workflow, locally or in CI; Docker is an optional rendering route. | Snapshots are uploaded to Percy for hosted processing and comparison. |
| Who owns the references? | Your team manages the project’s reference screenshots and approves updates with the CLI. | Percy manages baselines through its build and snapshot workflow. |
| How are changes reviewed? | Open the generated report, inspect diffs, and approve captures with the CLI. | Review builds and snapshots in Percy; approve snapshots, groups, or builds. |
| What browser control is documented? | Engine options include Puppeteer and Playwright, with browser configuration; Docker can reduce environment differences. | Percy-managed browsers offer managed rendering. Automate configuration supports chosen browser and OS combinations. |
| CI integration | Includes documented JUnit output; reports can support a CI workflow. | Builds are generated by visual test runs and can surface review and source-control status. Verify current integration and blocking behavior for your setup. |
| Usage and history | Runs and image storage are part of the infrastructure and workflow you operate. | Each selected browser rendering counts as a separate screenshot toward monthly usage. Build-history terms depend on the plan and may change. |
| Maintenance signal | The README says the project needs a new maintainer or owner; evaluate current activity and your ability to own the workflow. | Hosted operations reduce the rendering infrastructure you operate, while the service and its current plan terms remain vendor dependencies. |
3. Choose based on ownership and rendering needs
Prefer BackstopJS when
- You want configuration, capture, reports, and baseline files integrated into your own project workflow.
- Your team can maintain the runtime, browser dependencies, reference storage, and CI execution.
- You want to select a documented Puppeteer or Playwright engine and can make the rendering environment consistent.
- Your CI process benefits from the documented JUnit output and browser report.
Prefer Percy when
- You want a hosted build and review workflow rather than operating screenshot rendering and comparison infrastructure yourself.
- Reviewers need a shared place to inspect and approve visual changes.
- You need managed cross-browser rendering, or want to configure Automate for specific OS and browser combinations.
- You want visual approvals associated with source-control checks, after verifying the behavior of your project integration.
Decide explicitly about browser and operating-system coverage
Browser differences can create real regressions and expected rendering diffs. Fonts, native form controls, and scrollbars can vary with the operating system. Percy’s managed browser mode uses its managed environments; BrowserStack says to configure Automate when you need specified OS and browser combinations. BackstopJS documents Puppeteer and Playwright engine options and Docker rendering to reduce environment differences. Confirm the specific versions and environments currently supported before adopting either workflow.
BrowserStack recommends Percy for testing on newer browsers and Automate when a team needs a range of desktop, mobile, and browser combinations. This is the vendor’s guidance, not an independent benchmark. Its Percy documentation also says every selected browser rendering counts separately toward screenshot usage.
4. Getting started with BackstopJS
The commands below follow the documented CLI workflow. Run initialization in a project directory and inspect the generated configuration before adding scenarios. The init command can overwrite existing files, so use a clean directory or back up existing configuration first.
mkdir visual-regression
cd visual-regression
npm install --save-dev backstopjs
npx backstop init
npx backstop test
# Review the generated visual report before promoting changes.
npx backstop approve
BackstopJS normally looks for backstop.json in the project root. You can pass --config=<path> to use another config file. It also supports a JavaScript configuration module when you need comments or computed configuration. Configure scenarios, URLs, cookies, viewports, selectors, and interactions to match the states your users actually see.
# Run only scenarios whose labels match a regular expression
npx backstop test --filter="checkout|homepage"
# Render using the Docker option to reduce environment differences
npx backstop test --docker
# Approve only matching capture filenames after review
npx backstop approve --filter="homepage_desktop"
# Use the same non-default config path for both commands
npx backstop test --config=tests/backstop.json
npx backstop approve --config=tests/backstop.json
The README documents command options and configuration fields in the BackstopJS repository documentation. Confirm exact scenario properties and engine configuration there for the version you install rather than copying an unverified config from a different release.
5. Getting started with Percy
Percy setup depends on your test framework and whether you choose Percy’s SDK or BrowserStack SDK. The reliable high-level path is:
- Create a Percy project and choose the relevant project type.
- Choose an integration compatible with your test framework. The Percy SDK can add visual snapshots to existing scripts; the BrowserStack SDK combines functional and visual test configuration.
- Configure the project and credentials as directed by the current integration guide. Keep secret keys in CI secrets rather than source control.
- Run the visual test job. Inspect the resulting Percy build and snapshots.
- Review changes and approve the intended updates. If visual approval should gate merging, verify and configure the source-control check for your repository.
There is no single framework-independent Percy code sample that is runnable for every project: the snapshot call and setup differ by SDK and test runner. Use the official Percy integration options to select the matching setup, and its visual testing guide for builds and review. Verify framework support and project-specific blocking behavior at setup time.
6. Baselines, approvals, and pull-request policy
A visual test is useful only when baseline changes have clear ownership. With BackstopJS, run tests against known references, review the report, and approve only changes you intend to establish as the new reference. The approve command updates reference files from the most recent test batch; use its filter option when only selected captures are ready.
With Percy, approval is part of the hosted build workflow. Percy documents approval of individual snapshots, groups, or builds. A snapshot can include screenshots across browser and width combinations, so approval applies at snapshot level rather than to an individual browser-width image. When connected to source control, approving a complete build can update the associated check status. Percy also documents default auto-approval behavior on the main branch; review branch settings before making approvals a merge gate.
- Decide who may approve baseline changes.
- Keep intentional design updates reviewable in the same change as the UI code.
- Run comparisons against stable test data and predictable application state.
- Do not automatically approve every changed screenshot; that can turn a regression into the new baseline.
- Check how your selected tool handles branches, retries, and parallel test jobs before treating a status as a definitive pass.
7. CI, performance, and reliability
CI design
For BackstopJS, install a consistent Node and browser environment in the job, run backstop test, and publish the report and any JUnit output your CI system consumes. Make the reference set available to the job and define how reference updates are reviewed and committed. Docker rendering is an option when differences between developer and CI environments cause noise.
For Percy, the test job captures and uploads snapshot assets; Percy then processes and renders the build. BrowserStack describes Percy rendering and diffing as server-side, so that portion does not run in the CI worker. CI still depends on the test run completing, snapshot assets reaching Percy, and the build processing. Percy documents failed builds when assets are not uploaded correctly, no screenshots are received, or rendering times out.
Performance considerations
- More scenarios, page states, viewport sizes, and browser selections mean more captures and review surface.
- Percy’s cross-browser selection creates a separate screenshot count for each selected browser. Choose a coverage matrix that reflects supported user environments.
- BackstopJS runs capture work in the environment you provision. Browser startup, page readiness, application data setup, and CI resources influence job duration.
- Use stable test data and wait for the page state you need before capture. Avoid broad test suites for every small local iteration; BackstopJS supports filtering scenarios for targeted reruns.
Reliability and maintenance
Reproducible visual comparisons require stable content, fonts, browser versions, viewport sizes, and timing. Dynamic timestamps, personalized content, animations, and asynchronous loading can cause noisy diffs. Control those sources of change in the test environment or capture only after the intended state is ready.
BackstopJS gives the team direct ownership of its execution and reference workflow, which also means owning environment upkeep and monitoring the repository’s maintenance status. Percy transfers hosted rendering operations to the service, while adding dependence on service availability, account configuration, integrations, and plan terms. Neither choice removes the need to review baselines and keep test scenarios maintained.
Cost and usage
Compare total operating cost, not just a tool’s listed price. For BackstopJS, account for CI compute, browser and container maintenance, artifact or reference storage, and engineering time spent keeping the workflow reliable. The research dossier did not establish a comparable BackstopJS license or hosting price.
For Percy, check the current plan, monthly screenshot allowance, cross-browser counting, and history retention before budgeting. BrowserStack’s current documentation says each selected browser rendering counts separately. Its visual testing overview says free-plan builds expire after 30 days and other plans include one year of history; these are plan terms and should be verified before publication or procurement.
8. Troubleshooting common visual-test failures
| Symptom | Likely cause | What to do |
|---|---|---|
| BackstopJS reports widespread diffs on a machine or CI change | Different browser, OS, fonts, or rendering environment. | Standardize the environment; consider the documented Docker option and regenerate references only after review. |
| BackstopJS cannot find the intended config | Command runs from another directory or uses a non-default config path. | Run from the project root or pass the same --config path to test and approve. |
| BackstopJS test appears to miss a scenario | A filter does not match its label or capture filename. | Inspect labels and report filenames; adjust the regular expression and rerun. |
| BackstopJS references changed unexpectedly | backstop approve promotes captures from the latest test batch. |
Review the report first; use --filter to limit promotions and confirm the config path. |
| Percy build remains in Receiving or Processing | Assets are still uploading or Percy is rendering snapshots. | Check job completion and build details; confirm assets were uploaded and allow processing to finish. |
| Percy build fails or contains no snapshots | Assets failed to upload, no screenshots arrived, or browser rendering timed out. | Check the test-run logs, integration configuration, and build details; retry after correcting the reported failure. |
| Cross-browser differences look noisy | Browsers or operating systems render fonts, controls, or scrollbars differently. | Decide whether the difference represents supported user behavior; configure the needed OS/browser matrix and review each environment. |
| Screenshot usage grows faster than expected in Percy | Each enabled browser rendering counts separately. | Review selected browsers and snapshot volume, then verify current allowance and plan terms. |
| A Percy check does not block a pull request | Repository status checks or project integration may not be configured as required. | Verify the repository connection, check settings, and approval behavior for the selected integration. |
9. ScreenshotNeo: an alternative to try first
ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. It is an alternative for developers who need clean website captures in an application, script, or AI-agent workflow; it is not a replacement for the baseline comparison and approval workflows described above. One GET request returns a PNG, JPEG, WebP, or PDF. Its parameter names used by other screenshot APIs also work, which can make switching easier.
Or skip the browser setup and make a capture with one API request. See the ScreenshotNeo API documentation for options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
- Cookie banners are accepted and removed before capture, along with known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off.
- Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Response headers report the page verdict and whether it was billed.
- An MCP server provides
take_screenshot,get_page_info, andcapture_pdftools for Claude, Cursor, and other MCP clients. - The free plan includes 1,000 shots a month with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan.
Sign up for ScreenshotNeo and get 1,000 screenshots a month free, with no card.
10. Frequently asked questions
Can BackstopJS and Percy run in the same project?
They can serve different needs, but running both duplicates capture and review work. Add a second system only when its distinct browser, ownership, or approval capability is needed.
Does approving a visual change mean the UI is correct?
No. Approval records that a reviewer accepts the new baseline. It does not establish accessibility, functional correctness, or that the change was intended.
Should I compare every browser on every pull request?
Choose coverage based on the browsers your product supports and the cost of missing a browser-specific regression. A smaller routine matrix plus broader scheduled coverage can be a practical policy, provided the risk is acceptable.
Where should I check current product details?
Use the official BackstopJS repository and BrowserStack Percy documentation. Browser support, integrations, maintenance signals, usage counting, and plan retention can change.
