ScreenshotNeo

BlogHow-to

How to Compare Website Screenshots for an Indian Regional-Language Website

Build reliable visual regression checks for Indian-language pages with stable Playwright baselines, script-specific reviews, and practical troubleshooting.

By the ScreenshotNeo team4 October 20268 min read

To compare screenshots of an Indian regional-language website, capture the same route, language, page state, viewport, browser, and operating system each time. Save an approved capture as the baseline, then compare later captures against it. Review every language and script variant directly: a pixel diff can flag changed pixels, but it cannot tell whether a translation change was intentional or whether a glyph, line break, or layout is broken.

This guide uses Playwright Test for local visual regression checks. It focuses on repeatable captures, deliberate baseline updates, script-specific review, and separating real defects from rendering noise.

1. Define what each screenshot test covers

Start with a small matrix of important routes and states. A test name should make the route, locale, and viewport clear, so reviewers can identify which language and layout a baseline represents.

Dimension Examples to record
Route and state Homepage, navigation open, search results, form validation, checkout or application submission
Language and script Each supported language and actual script variant; include mixed-script pages where users see them
Viewport Widths that represent supported mobile, tablet, and desktop layouts
Environment Browser project, browser build, operating system, and any relevant device scale factor
Content Fixed test records, approved representative strings, and a known page state

Prioritize shared components and high-value journeys first: navigation, search, forms, and payment or application flows where applicable. Add combinations when they represent a real supported experience; testing every route-language-width permutation immediately can create a large baseline set that is expensive to review.

2. Create a repeatable Playwright screenshot test

Playwright Test creates a reference screenshot on its first run and compares later runs with that baseline. Screenshot assertions wait until two consecutive screenshots match before comparison. Browser rendering can vary with the host operating system, version, settings, hardware, power source, and headless mode, so create and compare baselines in a consistent environment. See the [Playwright visual comparisons guide](https://playwright.dev/docs/test-snapshots) and [screenshot assertion options](https://playwright.dev/docs/api/class-pageassertions).

Install and configure

npm init -y
npm install --save-dev @playwright/test
npx playwright install chromium

Add a script to package.json:

{
  "scripts": {
    "test:visual": "playwright test"
  }
}

Create playwright.config.ts to pin the project and make the viewport explicit:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  use: {
    browserName: 'chromium',
    headless: true,
    viewport: { width: 1280, height: 900 },
    deviceScaleFactor: 1,
    locale: 'hi-IN',
    timezoneId: 'Asia/Kolkata'
  },
  expect: {
    toHaveScreenshot: {
      animations: 'disabled',
      caret: 'hide',
      scale: 'css'
    }
  }
});

Use the locale appropriate to your page; an Indian language locale is not interchangeable with another language or script variant. Set the project locale deliberately, and make the URL or application state select the intended translation too.

Runnable example with explicit language and state

Save this as tests/regional-homepage.spec.ts. Replace the example domain, route, and selectors with your application. The test fixes browser context, viewport, locale, time zone, and a stable application state before capturing.

import { test, expect } from '@playwright/test';

test('Hindi homepage desktop visual baseline', async ({ page }) => {
  await page.setViewportSize({ width: 1280, height: 900 });
  await page.goto('https://example.com/hi/', { waitUntil: 'networkidle' });

  // Wait for the page's real ready signal and load web fonts before capture.
  await expect(page.locator('main')).toBeVisible();
  await page.evaluate(() => document.fonts.ready);

  // Stabilize data-dependent content using your app's own test controls/API.
  await expect(page.getByRole('heading', { level: 1 })).toBeVisible();

  await expect(page).toHaveScreenshot('homepage-hi-desktop.png', {
    fullPage: true,
    animations: 'disabled',
    caret: 'hide',
    scale: 'css'
  });
});

Run it with npm run test:visual. The first run writes the expected screenshot into the test’s snapshot directory. Review that image and commit it as the approved baseline. Later runs compare against it. Do not treat first-run generation as approval by itself.

For more variants, use separate named tests or parameterized cases, with the language, route, and viewport reflected in each snapshot name. A Tamil mobile baseline and a Hindi desktop baseline should not overwrite or ambiguously share one reference image.

3. Review each Indian-language rendering directly

Use real production or approved representative strings in the capture. Latin placeholder text will not expose missing glyphs, fallback-font changes, or the way translated copy fits into controls.

  • Check for missing glyphs, tofu boxes, and unexpected fallback fonts.
  • Look for clipped, overlapping, or unexpectedly wrapped text in headings, cards, buttons, navigation, forms, and dialogs.
  • Check alignment and spacing after longer translations change component dimensions.
  • Inspect punctuation, mixed-script content, numerals, and text direction where the page uses them.
  • Compare actual labels and calls to action; ensure they remain visible and usable at each supported width.
  • Review text regions in the diff manually. A visual comparison tool does not determine whether a translation is linguistically correct.

These are practical review checks, not a claim that every Indian script has the same rendering risks. Font coverage and layout behavior depend on the page, fonts, browser, and environment.

4. Control noise without hiding defects

First rerun a suspicious diff in the same browser and operating system used to create the baseline. Check fonts, browser build, OS rendering, dynamic data, animation, and image loading before deciding the application regressed.

Playwright’s screenshot assertion options include full-page and clipped captures, masks for selected locators, CSS stylesheets applied during capture, animation controls, CSS-pixel or device-pixel scaling, color-difference threshold, and maximum differing pixel count or ratio. Keep text and glyph areas visible. Use masks or capture styles only for genuinely irrelevant dynamic regions such as a changing timestamp; masking a language block can conceal the exact regression this suite should catch.

Keep comparison tolerances conservative and explicit. A larger allowed pixel difference can suppress noise, but it can also allow real small defects to pass. If the output changes only because of a dynamic region, stabilize that data or narrowly mask the region instead of relaxing the whole image comparison.

5. Update baselines through review

  1. Run the test and open the actual, expected, and diff images produced by the failure.
  2. Confirm that the capture used the intended route, locale, content, viewport, and environment.
  3. Decide whether the difference is a defect, rendering noise, or an intentional translation/design change.
  4. Fix defects and rerun. For an intentional update, review the new screenshot and update the baseline deliberately.
  5. Include the changed baseline in code review so another reviewer can verify the language and layout.

To regenerate snapshots intentionally, Playwright Test supports npx playwright test --update-snapshots. Review the resulting images before committing; avoid using the flag as an automatic cleanup for unexplained failures.

6. Choose local or hosted coverage based on the risk

Local Playwright comparison works well when you can keep the baseline and comparison environment controlled and want the review in your test and code review workflow. Add browser projects or environments when browser-specific font and form-control differences matter to your supported audience.

A hosted visual testing service such as Percy can provide centralized review and browser coverage through its Playwright integration. Treat each required browser and responsive width as a coverage and usage decision: BrowserStack’s Percy documentation says each responsive width counts as a separate screenshot, and its visual testing documentation describes browser-specific review. Check current service plan terms before estimating cost; do not assume the billing model or allowance stays fixed.

Keep accessibility review separate from screenshot review. A matching screenshot cannot prove keyboard access, semantic structure, screen-reader behavior, or sufficient contrast. W3C WAI describes its [Easy Checks](https://www.w3.org/WAI/test-evaluate/easy-checks/) as a first review; it says normal-size text should have at least a 4.5:1 contrast ratio. Use appropriate accessibility tests and manual checks alongside visual regression.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its one-request API can capture a page as an image or PDF. This is useful when you need a repeatable capture without maintaining browser setup; it does not replace approved-baseline review or language-specific inspection. See the ScreenshotNeo API documentation.

cURL

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,
)
r.raise_for_status()
with open("shot.webp", "wb") as image_file:
    image_file.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}`);
await import('node:fs/promises').then(({ writeFile }) =>
  writeFile('shot.webp', Buffer.from(await res.arrayBuffer()))
);

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. For visual regression, capture the same URL and state consistently and retain your own approved references and review process.

Start with 1,000 free screenshots a month, no card required.

Troubleshooting

Symptom Likely cause Fix
Diff changes between identical runs Dynamic content, animation, unstable data, or different rendering environment Fix test data and page state, disable suitable animations, and run in the baseline browser/OS environment.
Regional text appears as boxes or wrong shapes Missing glyph coverage or a fallback font Check loaded fonts and font coverage in the target environment; keep the real script in the fixture and baseline.
Only one language fails at a narrow width Translated text changes wrapping or component dimensions Inspect the actual target-language strings and responsive layout; adjust the layout or approved content as appropriate.
Screenshot is blank or incomplete Capture happened before the application was ready, or content is delayed Wait for a meaningful page locator and required data; wait for fonts before capture. Avoid relying only on an arbitrary sleep.
Baseline differs on a developer machine but not CI OS, browser version, headless mode, or rendering settings differ Compare within a consistent environment and pin the browser/runtime used for visual tests.
Many failures after translation copy changed The change may be intentional, but the baseline has not been reviewed Review every affected language and viewport. Update only expected images after approving the new rendering.
A tolerance hides small text defects Diff threshold or pixel allowance is too permissive Reduce the tolerance and stabilize or narrowly mask irrelevant regions. Keep text and glyph areas unmasked.

Performance, reliability, and cost

  • Keep the suite focused: begin with high-value routes, shared layouts, representative strings, and supported viewport widths; add combinations when they cover a real user risk.
  • Stabilize instead of sleeping: wait for application readiness and fonts. Screenshot assertions perform consecutive-capture settling, but that does not replace controlling asynchronous data or external content.
  • Control image size: CSS-pixel scaling produces smaller captures than device-pixel scaling on high-density displays. Use device scale when high-density rendering itself is under test.
  • Budget review effort: each language, state, viewport, and browser can add another baseline to maintain. Hosted responsive and browser coverage may also add service usage; verify current plan rules.
  • Keep accessibility and visual checks complementary: screenshots catch appearance changes, while semantic, keyboard, assistive-technology, and contrast checks cover different requirements.

FAQ

Should each language have its own screenshot baseline?

Yes. Keep a distinct, clearly named reference for each supported language or script variant whose rendered content differs.

Can a pixel diff tell me whether a translation is correct?

No. It identifies image changes. A person who can review the language must decide whether the text is correct and whether a change is intended.

Should I mask translated text to reduce flaky diffs?

No. That removes the most important region from review. Stabilize the content and rendering environment instead.

Does a passing screenshot test establish accessibility?

No. Add accessibility checks for semantics, keyboard use, assistive technology, and contrast.