ScreenshotNeo

BlogHow-to

BackstopJS Configuration Example for Testing Multiple URLs

Configure one BackstopJS scenario per URL, share defaults, capture baselines, compare pages, and troubleshoot common multi-page visual test issues.

By the ScreenshotNeo team4 October 20267 min read

To test multiple URLs with BackstopJS, add one object per page or page state to the top-level scenarios array. Give each scenario a unique label and a url. Use scenarioDefaults for settings shared across pages, and add referenceUrl when the baseline should be captured from a different environment.

Save a configuration such as this as backstop.json in your project directory. Replace the example hosts and paths with your own pages. The documented fields are shown here; adapt engine-specific settings to the BackstopJS version installed in your project.

{
  "id": "site-visual-checks",
  "viewports": [
    { "label": "desktop", "width": 1440, "height": 900 },
    { "label": "mobile", "width": 390, "height": 844 }
  ],
  "scenarioDefaults": {
    "selectors": ["document"],
    "misMatchThreshold": 0.1,
    "requireSameDimensions": true
  },
  "scenarios": [
    {
      "label": "home",
      "url": "https://staging.example.com/",
      "referenceUrl": "https://www.example.com/"
    },
    {
      "label": "pricing",
      "url": "https://staging.example.com/pricing",
      "referenceUrl": "https://www.example.com/pricing"
    },
    {
      "label": "contact",
      "url": "https://staging.example.com/contact",
      "referenceUrl": "https://www.example.com/contact"
    }
  ],
  "paths": {
    "bitmaps_reference": "backstop_data/bitmaps_reference",
    "bitmaps_test": "backstop_data/bitmaps_test",
    "engine_scripts": "backstop_data/engine_scripts",
    "html_report": "backstop_data/html_report",
    "ci_report": "backstop_data/ci_report"
  },
  "report": ["browser"]
}

1. Model each URL as a scenario

A BackstopJS scenario describes the endpoint or document to capture and compare. The project README describes url as the endpoint/document to test. Put each distinct URL or page state in its own scenario object rather than trying to combine URLs in a single url value. Each label should be meaningful and unique: labels help identify the case in output and saved screenshot names.

Different states of the same route can also be separate scenarios—for example, a page before and after a user action—provided you configure each scenario’s URL and any state/readiness behavior the page needs. Keep the examples’ home, pricing, and contact labels distinct even if paths are similar.

2. Share settings with scenarioDefaults

Use scenarioDefaults for scenario options that genuinely apply to every entry. A scenario can override a default by specifying the same property itself. This keeps repeated configuration in one place while allowing exceptions for pages with different capture needs.

Setting Purpose Practical guidance
selectors Chooses what is captured, including the special document or viewport selectors. Use document for the whole document or viewport for the visible area. Element selectors can focus a test on specific page regions. A scenario-level selector list replaces the inherited list.
misMatchThreshold Sets the accepted visual mismatch threshold. The example value is not universal. Tune it to the visual noise and change policy of your project.
requireSameDimensions Controls whether dimensions must match for comparison. Keep it consistent for comparable captures; investigate unexpected size changes rather than masking them automatically.
Readiness and delay options Allow a page to reach the intended state before capture. Configure per page where load behavior differs. Confirm exact option names and engine behavior for your installed version.

An explicit empty array such as "selectors": [] is still an override. It means no selectors are configured for that scenario even if the defaults define selectors. If a scenario seems to have lost its default capture target, check for an empty per-scenario array.

3. Choose the reference and test environments

url is used for the test capture. referenceUrl is optional and lets the baseline come from another endpoint, commonly production while the test capture comes from staging. When backstop reference runs, BackstopJS uses referenceUrl when present and otherwise uses url.

Use the same environment for both captures when you want to detect changes within that environment over time. Use separate reference and test URLs when the point is to compare a deployed baseline with a candidate environment. Ensure the two URLs represent the same content and state; otherwise expected content differences can dominate the visual report.

4. Capture baselines and compare

  1. Install and configure BackstopJS using the instructions applicable to your project and locked version. Save the JSON configuration as backstop.json, or use a JavaScript config if you need comments or generated values.
  2. Run backstop reference to capture baseline images. This creates references; it does not compare them.
  3. Run backstop test to capture current images and compare them with those references.
  4. Open and review the report. Use backstop approve only after confirming that the changes are intended. Approval promotes the recent test captures into the reference set.
backstop reference
backstop test
# Review the report before updating accepted baselines.
backstop approve

For larger suites, the documented --filter option can limit a run to scenario labels that match a filter. Verify the exact CLI syntax with the BackstopJS version in your lockfile, especially if a wrapper or older release is involved.

5. Add pages, states, and viewports without losing clarity

  • More pages: add one scenario object per route and give it a descriptive label.
  • More states: represent meaningful state variations as separate scenarios, with distinct labels. Configure the necessary readiness or state behavior for each case.
  • More viewport coverage: add viewport objects with unique labels and dimensions. BackstopJS requires at least one viewport and supports multiple viewport sizes.
  • Page-specific capture: override selectors or other scenario settings only on the scenario that needs different behavior.
  • Alternative configuration: JSON and JavaScript configurations are documented; the CLI also documents selecting another config with --config.
  • Engine settings: the project documentation lists Puppeteer and Playwright engine options. Engine details can vary by installed version, so check the documentation and fixture matching your locked release before adopting them.

Scenario count and viewport count both increase capture work. Start with the pages and viewport sizes that reflect the layouts your team needs to protect, then expand the matrix when the extra coverage justifies the longer run.

6. Troubleshoot common multi-URL issues

Symptom Likely cause Fix
Only one page is captured Several URLs were placed into one scenario value, or the config’s scenarios array contains only one entry. Create a separate scenario object for each URL and check that each object has its own url and unique label.
Baseline shows the wrong site or environment referenceUrl points somewhere unexpected, or the reference command falls back to url. Check the reference and test URL for every scenario. Remember that referenceUrl is used for baseline capture when set.
A page has no screenshot target A scenario-level selectors: [] replaced the default selectors. Remove the empty override or provide the intended selector list for that scenario.
Labels or generated files are hard to distinguish Labels are duplicated or too generic. Give every case a concise name that describes page and state, such as pricing-annual or account-signed-out.
Every run reports noisy diffs Page content or rendering varies, or the mismatch threshold is poorly matched to the project. Stabilize the capture state and readiness behavior, compare like-for-like URLs, then tune the threshold based on reviewed reports. Do not raise it blindly to hide meaningful changes.
Command or engine option is rejected The option may differ in the installed release or wrapper. Check the CLI and engine documentation for the version pinned by the project. Configuration examples from older releases may not describe current behavior.
Approval causes unexpected future diffs Changed captures were promoted without adequate review. Review the report before approving. Restore the intended baseline if an accidental update was made.

7. Performance, reliability, and maintenance

Each scenario and viewport combination adds capture and comparison work. Keep the matrix focused on routes and sizes that matter, use labels that make failures actionable, and use a filtered run while iterating on a subset. For a full regression run, include the complete intended matrix.

Visual comparisons are only useful when the two captures represent equivalent states. Use stable URLs and deliberate readiness settings, and avoid comparing unrelated content or environments. The research sources do not provide universal run-time benchmarks or a universally correct mismatch threshold, so measure suite duration in your own CI and set thresholds based on reviewed project output.

Store the configuration and baseline workflow with the project. Treat baseline approval as a review decision: inspect what changed, establish that it is intended, then promote it. Pin the BackstopJS version and verify version-sensitive engine and CLI settings against that release.

Or skip the browser setup

If you need screenshots of several URLs for documentation, monitoring, or a lightweight capture workflow, ScreenshotNeo provides a website screenshot API and MCP server. Here is the one-call cURL example; repeat it with each target URL as needed. See the API documentation for parameters and response details.

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp

ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. Its MCP server includes take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up free for 1,000 screenshots a month, with no card required.

FAQ

Can I use one scenario for several URLs?

No. Use one scenario object per URL or page state so each capture has its own label and endpoint.

Does BackstopJS compare screenshots when I run reference?

No. backstop reference creates the baseline images. Run backstop test to capture and compare against them.

Can each page use a different selector?

Yes. Set shared selectors in scenarioDefaults and override selectors on scenarios that need a different capture target.

Can I use Playwright?

The project documentation lists Playwright and Puppeteer engine options. Confirm the supported configuration for the version pinned in your project.