How to generate BackstopJS HTML reports in CI
Configure BackstopJS to generate browser-readable HTML reports in CI, retain them as artifacts, and add JUnit output when your pipeline needs it.
To generate a browser-readable HTML report in BackstopJS CI, set report to ["browser"], choose an html_report output path, and run backstop test. Configure your CI provider to retain or publish that output directory as an artifact. If you also need machine-readable results for the build system, add "CI" to the report list; BackstopJS documents that output as JUnit, not HTML.
1. Configure the browser report
In your BackstopJS configuration, add or update the report settings. This example uses JSON syntax; merge these properties into your existing configuration rather than replacing scenario or engine settings.
{
"report": ["browser"],
"paths": {
"html_report": "backstop_data/html_report"
}
}
BackstopJS paths are relative to the current working directory and can be changed in configuration. Run the test command from the project directory so the configured path resolves as expected:
npx backstop test
If BackstopJS is installed globally or your CI job already exposes its executable on PATH, use backstop test instead. The browser report workflow generates the visual report after the test run. In a headless CI environment, the report files can still be retained for later review even when the job cannot open a browser window.
2. Save or publish the report in CI
Generating a report and making it available after a job are separate steps. Configure your CI provider’s artifact or publication mechanism to collect the directory set by paths.html_report—in this example, backstop_data/html_report. The exact artifact syntax depends on the provider; BackstopJS does not prescribe one universal CI artifact recipe.
- Run
backstop testfrom the repository directory. - Collect the configured HTML report directory in the job’s artifact step.
- Set artifact retention according to how long reviewers need access to the report.
- On a failed visual test, inspect the report artifact before changing the baseline or approving differences.
Check the artifact directory after a run. If it is missing, confirm that the job ran in the expected working directory and that its artifact step points to the same path as paths.html_report.
3. HTML report versus CI report
The report setting selects report types. browser is the human-readable visual report; CI is a separate machine-readable report type whose documented default format is JUnit. Enable both when developers need visual inspection and the CI platform needs test-result ingestion.
| Setting | Purpose | Documented output |
|---|---|---|
["browser"] |
Visual review in a browser | HTML report in the configured html_report path |
["CI"] |
Build-system test result integration | JUnit by default; the default file is [backstopjs dir]/test/ci_report/xunit.xml |
["browser", "CI"] |
Both visual review and CI ingestion | Separate browser and CI report outputs |
For example, configure both outputs and customize the CI report directory, filename, and suite name as follows:
{
"report": ["browser", "CI"],
"paths": {
"html_report": "backstop_data/html_report",
"ci_report": "backstop_data/ci_report"
},
"ci": {
"format": "junit",
"testReportFileName": "myproject-xunit",
"testSuiteName": "backstopJS"
}
}
Retain both directories if both audiences need the results. The browser report is not a substitute for JUnit ingestion, and enabling CI alone does not select the browser HTML report.
4. Open the latest report
Use BackstopJS’s report command to reopen the latest test run’s report:
npx backstop openReport
You can also run backstop openReport when the latest run used CI-only reporting or no browser reporting. For report features such as approving scenarios or viewing scenario browser logs, start BackstopJS’s remote HTTP service in another terminal, then open the report:
BACKSTOP_REMOTE_HTTP_PORT=3000 npx backstop remote --config=backstop.json
Replace backstop.json with the configuration file used by your project. In CI, the job may not have an interactive browser; retain the report artifact and open it in an environment where it can be reviewed.
5. Use the test exit code to gate the job
BackstopJS returns exit status 0 when tests succeed and 1 when anything fails. Let the CI job observe that process result so visual regressions can fail the build, while separately retaining the report for diagnosis. Avoid masking the command’s failure status with a shell construct that makes the job succeed regardless of the BackstopJS result.
6. Troubleshoot report generation
| Symptom | Likely cause | What to check |
|---|---|---|
| No HTML report appears | The report list omits browser, or the job looks in the wrong directory. |
Set "report": ["browser"]; confirm the current working directory and paths.html_report. |
| A JUnit file exists, but no HTML report | The configuration enables CI only. |
Add browser to the report list and collect the HTML output path separately. |
| The report exists locally but not after CI finishes | The artifact step does not collect the generated directory, or the job discarded it. | Point artifact collection at the configured html_report path and verify the job’s artifact settings. |
openReport cannot find the expected run |
The command is running from a different working directory or using a different configuration context. | Run it from the project directory and check the report paths and config used by the test run. |
| The CI parser does not show test results | The pipeline expects JUnit but the CI report is not enabled, or the parser watches the wrong file. | Enable "CI", keep the JUnit format, and align the parser path with paths.ci_report and the configured filename. |
| The job fails despite producing a report | BackstopJS found a failed visual comparison; its documented failure exit status is 1. |
Open the report artifact, inspect the differences, and update or approve baselines only when the change is intended. |
7. Reliability, runtime, and storage considerations
BackstopJS’s documented report configuration does not specify a fixed report-generation time or artifact size. These depend on the scenarios and CI environment, so measure them in your own pipeline rather than relying on a general benchmark. Preserve the test command’s exit status, and retain report files even for failing runs so the failure can be inspected.
- Keep outputs together: collect the HTML report and, when enabled, the CI report as separate outputs.
- Make paths explicit: use stable configured paths and run commands from a predictable working directory.
- Limit retention deliberately: report artifacts consume CI storage; choose a retention period that supports review without retaining every report indefinitely.
- Separate review from gating: use the BackstopJS exit status to gate the job and the HTML artifact to explain what failed.
8. Or skip the browser setup
If your task is to capture a website screenshot for a report or review, ScreenshotNeo provides a screenshot API and MCP server. It does not generate BackstopJS regression reports or replace visual baseline testing. For a standalone screenshot, make one GET request:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. Cookie banners, newsletter popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000 screenshots.
Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.
FAQ
Does report: ["CI"] create an HTML report?
No. The documented CI report defaults to JUnit. Include browser for the visual HTML report.
Can I create both reports in one run?
Yes. Set report to ["browser", "CI"] and retain each configured output directory.
What exit code indicates a failed BackstopJS run?
The documented CLI behavior is exit code 1 for failures and 0 for success.
Which BackstopJS version should I use?
Report settings can change between releases. Check the official README for the version installed in your repository: BackstopJS README.


