How to Test Visual Changes on a Hindi Website with BackstopJS
Build repeatable BackstopJS screenshot checks for Hindi pages: configure scenarios and viewports, control rendering noise, review diffs, and update baselines safely.
Use BackstopJS to capture Hindi pages at fixed URLs and viewport sizes, compare each run with an approved reference screenshot, and review the visual report before accepting changes. For reliable results, keep browser conditions, locale, font availability, page state, and capture timing consistent. BackstopJS does not provide a Hindi-specific test mode: it compares rendered screenshots, so differences in Devanagari text or shaping need to be investigated in the page and its loaded fonts.
1. Install and initialize BackstopJS
BackstopJS is screenshot-based visual regression software. Its documented workflow is to create a project configuration, capture reference images, capture test images, compare them in a report, and promote reviewed changes to the reference set. See the BackstopJS project README for its documented configuration and commands.
npm install --global backstopjs
backstop init
Run these commands in or near the project where you want to keep the generated configuration and screenshot artifacts. For repeatability, pin BackstopJS in the project’s dependency setup and keep the Node.js runtime consistent across local and CI runs. Check the README and package information for the version you choose rather than assuming a global installation will remain unchanged.
2. Define Hindi pages as scenarios
A scenario identifies a page or visual state to capture. Use stable labels and the actual Hindi-language route and content state. Add separate scenarios for important states such as an expanded navigation menu, form validation, or a page after a user interaction.
BackstopJS requires at least one scenario with a label and URL and at least one viewport. The following is an illustrative configuration shape; adapt the URLs, dimensions, and readiness selector to your application and the configuration format generated by your installed version.
module.exports = {
id: "hindi-site",
viewports: [
{ label: "desktop", width: 1366, height: 900 },
{ label: "mobile", width: 390, height: 844 }
],
scenarios: [
{
label: "Hindi home page",
url: "https://example.com/hi/",
readySelector: "main",
readyTimeout: 10000,
selectors: ["document"],
misMatchThreshold: 0.1,
requireSameDimensions: true
},
{
label: "Hindi article page",
url: "https://example.com/hi/articles/example",
readySelector: "article",
readyTimeout: 10000,
selectors: ["document"]
}
],
paths: {
bitmaps_reference: "backstop_data/bitmaps_reference",
bitmaps_test: "backstop_data/bitmaps_test",
html_report: "backstop_data/html_report",
ci_report: "backstop_data/ci_report"
},
report: ["browser", "CI"],
engine: "puppeteer",
asyncCaptureLimit: 5,
asyncCompareLimit: 50,
debug: false,
debugWindow: false
};
BackstopJS configuration fields and supported options can vary by version. Start from the configuration created by backstop init and merge in the scenario and capture settings you need, checking their names against the README for your pinned version. In particular, the sample threshold is a starting point, not a recommendation for every site.
Make Hindi rendering repeatable
- Use the same browser engine and version, viewport dimensions, locale, and relevant browser settings for references and test runs.
- Wait for the page’s important content and fonts to be ready before capture. A selector or readiness event is preferable to an arbitrary long delay when it expresses the real condition.
- Keep data and page state stable. Timestamps, rotating banners, personalized content, and asynchronously loaded assets can create diffs unrelated to a code change.
- If a difference appears in Hindi text, check the rendered page, font loading, and browser conditions as well as the screenshot. The supplied documentation does not establish a universal Devanagari font choice or a Hindi-specific mismatch threshold.
3. Choose viewports and capture scope
Choose viewport dimensions that match supported layouts and the breakpoints that matter to your users. The example’s desktop and mobile dimensions are illustrative; the project documentation does not prescribe a universal mobile resolution. Include additional sizes when your layout changes at other breakpoints.
Choose what each scenario captures based on the behavior under test:
documentcaptures the full page, useful for page-wide layout and content changes.viewportcaptures the visible viewport, useful when the initial screen is the focus.- A CSS selector targets a component or region, useful for focused checks when unrelated page areas change frequently.
Full-page capture can expose changes below the fold, while a targeted selector can make a component’s diff easier to review. Targeting too narrowly can miss surrounding layout effects, so use page-level scenarios for changes that can affect the whole layout.
4. Capture the baseline and compare changes
A reference is an intentionally approved visual state. Create it once the page, test data, and capture settings are ready. Then run tests after changes and inspect the report before approving a new baseline.
backstop reference
backstop test
# Open and inspect the generated report.
# Approve only after confirming the differences are intended.
backstop approve
backstop reference creates reference captures. backstop test creates new captures and compares them against those references. backstop approve replaces the reference images with the latest test images, so it is a baseline-management action, not a way to make a failing check pass. Review the reference, test, and diff views first; a passing command or Hindi page is not by itself a reason to approve a change.
Use referenceUrl when references should be captured from one environment and test images from another. This can help compare a stable reference environment with a build under review, but the environments still need compatible content and rendering conditions for meaningful diffs.
5. Reduce noisy differences and set sensitivity
Use readiness conditions, interactions, and selector controls to make captures reflect the intended page state. The BackstopJS README documents options including readySelector, readyEvent, readyTimeout, delay, interaction scripts, and selectors to hide or remove. Use a delay when the page has a genuine timing requirement that cannot be expressed by a readiness condition.
When a dynamic element is irrelevant to the test, hide or remove only that region using the documented selector options. Do not mask text, spacing, or components whose layout is under test. If possible, make the underlying data deterministic instead.
misMatchThreshold sets tolerance for image differences; requireSameDimensions controls whether dimensions must match. A higher threshold may overlook small regressions, while a zero threshold may flag harmless rendering noise. Calibrate these settings by reviewing real diffs in your project and documenting why the chosen values fit the pages being tested.
6. Use reports in local review and CI
The project README describes browser reports and CI reporting, including JUnit format. A practical workflow is to run reference and comparison commands locally while building scenarios, then run visual checks in the build process or before deployment. Keep the generated report available to reviewers so a failure can be judged from the images rather than only from a command status.
Be deliberate about coverage: each extra route, state, and viewport adds captures and review work. Start with high-value Hindi routes and the layouts most likely to change, then extend coverage as you learn which failures are useful.
Common errors and fixes
| Symptom | Likely cause | What to do |
|---|---|---|
| No usable captures or configuration error | Missing scenario fields or no viewport. | Confirm there is at least one scenario with a label and URL and at least one viewport. Compare field names with the README for the installed version. |
| Page captured before Hindi content appears | The capture began before client-rendered content or fonts were ready. | Wait for a meaningful content selector or readiness event; use a delay only if needed. Check that the same condition is met in both runs. |
| Large diffs on every run | Unstable data, rotating content, timestamps, asynchronous resources, or changed rendering conditions. | Stabilize the page state and environment. Hide or remove only genuinely irrelevant regions, then rerun and inspect the report. |
| Devanagari text looks different in screenshots | Different font availability or loading state, browser environment, viewport, or actual content/layout change. | Inspect the page itself and confirm the intended fonts are loaded consistently. Keep browser, locale, viewport, and timing stable; do not assume the diff is harmless. |
| Dimension mismatch | The captured page or viewport dimensions changed, or the scenario is configured to require matching dimensions. | Check viewport settings and page layout, then decide whether dimension equality is part of the requirement. Change requireSameDimensions only deliberately. |
| Too many small failures or missed subtle changes | The mismatch threshold is poorly calibrated for this page or rendering noise. | Review representative diffs and adjust misMatchThreshold with a documented rationale. Do not use a high tolerance simply to silence repeated failures. |
| A baseline changed unexpectedly | backstop approve was run before visual review. |
Restore the intended reference set from version control or a known-good artifact, then review the new diffs before approving. |
Performance, reliability, and cost considerations
BackstopJS work grows with the number of scenarios and viewports because each combination needs a capture and comparison. Keep scenario coverage focused on meaningful routes and states. The configuration includes capture and comparison concurrency controls; choose settings that fit your environment and avoid treating a particular concurrency value as a universal performance target.
Reliability depends on deterministic content, consistent browser conditions, appropriate readiness checks, and reviewable reports. A screenshot comparison can tell you that rendered pixels changed; it does not explain whether a change is correct or test text semantics. Pair visual diffs with the checks appropriate to your application.
The provided research does not establish BackstopJS hosting costs or CI-provider pricing. Account for the compute and storage used by your own build environment, and decide how long to retain screenshots and reports based on your review workflow.
Or skip the browser setup
For a one-off capture or a screenshot workflow you do not want to run in your own browser setup, ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. Its API accepts a URL and returns a PNG, JPEG, WebP, or PDF. It is a separate capture service, so BackstopJS remains the workflow for maintaining reference images and reviewing visual regressions.
One-call cURL example (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://example.com/hi/ -o shot.webp
Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com/hi/"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com/hi/'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are not billed. Its MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. These are capture features, not BackstopJS reference comparison or approval features.
Sign up free for 1,000 screenshots a month, with no card required.
FAQ
Does BackstopJS understand Hindi?
It compares screenshots of rendered pages. It does not perform a Hindi-language semantic or typography-specific check.
Should every Hindi page use the same mismatch threshold?
Not necessarily. Choose and document a threshold based on reviewed diffs for the pages and rendering conditions in your project.
Can I test an interactive Hindi page?
Yes. Model the relevant state as a scenario and use the documented interaction and readiness settings so the capture occurs after the state is reached.
When should I approve a new reference?
After reviewing the report and deciding that the changed appearance is intentional and should become the new baseline.


