How to Test a Website’s Devanagari Fonts with Screenshot Comparisons
Build repeatable screenshot checks for Devanagari text, verify which font actually rendered, and catch shaping, loading, and fallback problems.
A screenshot comparison can show that Devanagari text changed, but it cannot tell you by itself whether the font is broken. For a useful test, hold the browser environment and capture timing steady, include the Devanagari combinations your site actually uses, and verify the typeface the browser rendered.
This guide sets up a repeatable Playwright Test check, shows how to inspect font fallback in Chrome DevTools, and explains how to separate settled-font checks from font-loading checks.
1. Choose what the test should prove
Decide whether you are checking for a visual regression in one supported environment, or checking that the site behaves across different browsers and platforms. These are related but different jobs:
- Regression check: compare a new capture with a baseline made under the same browser, operating system, settings, viewport, device scale, and capture mode.
- Compatibility check: run separate captures for each browser and platform combination you support, then inspect those results for differences.
- Font-loading check: capture the settled web font and, if relevant, the initial loading state as separate test cases.
- Font-source check: verify the locally installed font path and the network-served web font path independently.
Playwright warns that rendering can vary with the host operating system, browser version, settings, hardware, power source, and headless mode. Keep the environment consistent for baseline creation and comparison. A pixel change is evidence that pixels changed; inspect the rendered face, loading state, and test conditions before calling it a font regression. Playwright’s visual comparisons guide explains the screenshot comparison model and environment caveats.
2. Build representative Devanagari test content
Use a small fixture that renders the actual words, labels, headings, and mixed-script strings used in your interface. Include combinations and marks in context: Devanagari shaping depends on how glyphs combine and position, so a row of isolated characters is not enough to assess the page. If the real design mixes Latin and Devanagari, include that too and look at baseline alignment.
There is no universal test string prescribed here. Choose content that covers your product’s real vocabulary and the combinations most likely to expose clipping, misplaced marks, incorrect conjunct shaping, spacing changes, or fallback.
<!doctype html>
<html lang="hi">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Devanagari font fixture</title>
<style>
@font-face {
font-family: "SiteDevanagari";
src: url("/fonts/site-devanagari.woff2") format("woff2");
font-style: normal;
font-weight: 400;
font-display: swap;
}
body {
margin: 0;
padding: 32px;
font-family: "SiteDevanagari", sans-serif;
font-size: 28px;
line-height: 1.7;
}
.sample { margin-block: 0 24px; }
.mixed { font-size: 24px; }
</style>
</head>
<body>
<main>
<p class="sample">Replace this sentence with a real Devanagari heading from your product.</p>
<p class="sample">Add interface labels and words containing the combinations and marks you need to review.</p>
<p class="mixed">Add a real mixed-script label: Latin product name followed by Devanagari text.</p>
</main>
</body>
</html>
Replace the placeholder English strings with actual Devanagari text from your site before using the fixture. Keep the content stable between runs; changes to the test string make screenshot comparisons harder to interpret.
3. Add a repeatable Playwright screenshot assertion
Use Playwright Test’s toHaveScreenshot() assertion to create and compare a reference screenshot. The first run can write the baseline; later runs compare the new rendering against it. Review a changed image before updating the baseline.
Install Playwright Test in your project and add a test such as this. Adjust the fixture URL and selector to match your app:
import { test, expect } from '@playwright/test';
test('Devanagari font fixture matches its visual baseline', async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 900 });
await page.goto('http://127.0.0.1:4173/devanagari-font-fixture', {
waitUntil: 'networkidle',
});
// Wait for web fonts to settle before capturing the settled-font case.
await page.evaluate(() => document.fonts.ready);
await expect(page.locator('main')).toHaveScreenshot('devanagari-fixture.png', {
animations: 'disabled',
caret: 'hide',
maxDiffPixels: 0,
});
});
Start the app or fixture server before running the test, then run your Playwright Test command. On the initial run, inspect the generated reference. On later runs, inspect the diff and actual image when the assertion fails. Only update the baseline after confirming the change is intended.
The example uses maxDiffPixels: 0 to make any differing pixel fail. Playwright supports configurable pixel-difference thresholds; a nonzero threshold can reduce noise, but choose it carefully. A threshold must not mask changed glyph forms, missing marks, spacing shifts, clipping, or a fallback face.
4. Verify which font actually rendered
A CSS declaration such as font-family: "SiteDevanagari", sans-serif states the preferred stack. It does not prove that the named face supplied the glyphs. The font may not have loaded, may lack a needed glyph, or may have fallen through to another face.
- Open the page in Chrome and inspect the specific text element in DevTools.
- Open the rendered-font information for that element and check the actual typeface used, including fallback faces.
- Compare the reported face with the font file and stack you expected for that text.
- If the page uses
local()in its@font-facesource, open DevTools’ Rendering panel, enable disabling local font sources, and reload. This helps test whether the web-served font is being used rather than a matching font installed on your machine. - Check the browser’s network panel for failed font requests and inspect the response and font URL if the served font does not appear.
Chrome’s guide, “DevTools answers – What font is that?”, describes checking rendered typefaces and font-stack fall-through. The DevTools Rendering panel documentation describes effects including disabling local font sources.
5. Test font-loading states separately
Choose whether your baseline represents text after the web font has loaded or the page during its initial load. Do not compare a settled-font capture with a capture taken while the font is still loading.
In the settled case, wait for the browser’s font set to be ready before capturing, as in the Playwright example. If the initial loading appearance matters to users, make a separate test for that state and control when the screenshot is taken. Avoid relying on an arbitrary delay unless the delay itself is the behavior you intend to test.
Browser behavior during web-font loading can differ: Google Fonts documents that Chrome and Safari may show blank space for text using a web font until it loads, while Firefox initially uses a default font and then rerenders. Treat those stages as distinct conditions. See Google Fonts’ technical considerations.
6. Record and control the capture environment
For a meaningful regression check, record the environment used to make the baseline and keep it fixed for later comparisons. At minimum, track:
- Browser and version.
- Operating system and version.
- Headless or headed mode.
- Viewport dimensions and device scale factor.
- Font-loading condition: settled web font or initial loading state.
- Whether local font sources are enabled.
- The fixture URL, test content, and any relevant page state.
These controls make it easier to distinguish an intended font change from a different rendering environment. If your support promise covers multiple browser and operating-system combinations, keep separate baselines or test projects for those targets. Playwright notes that browser and platform differences, including font rendering, can change screenshots.
7. Review differences with a font-specific checklist
When a screenshot assertion reports a difference, compare the rendered image and diff, then check:
- Do the same Devanagari words and combinations appear in both captures?
- Are conjunct forms and marks shaped and positioned as expected in context?
- Are any marks clipped, missing, or shifted?
- Did line breaks, letter spacing, line height, or element dimensions change?
- Does DevTools report the same rendered typeface and fallback behavior?
- Was the web font settled in both captures?
- Were browser, OS, browser mode, viewport, and device scale held constant?
- Could local font availability explain why one machine used a different face?
The W3C’s Devanagari Script Resources is a draft resource for web and ebook layout and presentation. It points to relevant areas such as shaping combinations, glyph positioning, and baseline alignment; it is guidance, not a browser conformance test or final normative standard. The Devanagari Gap Analysis discusses browser coverage and gaps, and notes the difficulty of determining appropriate font rendering without examining rendered behavior. Neither source establishes that every font, browser version, and operating system behaves correctly.
8. Troubleshooting common failures
| Symptom | Likely cause | What to check or fix |
|---|---|---|
| Screenshot differs on another machine | Browser, OS, settings, hardware, or headless mode changed. | Run baseline and comparison in the same controlled environment. Keep separate baselines for supported target environments. |
| The CSS names the expected font, but glyph shapes look different | The requested face may not have rendered, or the browser may have used a fallback face. | Inspect the element’s rendered fonts in Chrome DevTools. Check font requests and font coverage for the text. |
| Local test looks correct, deployed page does not | A local font source may satisfy the stack while the web font path is missing or failing. | Disable local font sources in DevTools and reload. Verify the web font request and its response. |
| Text is blank in one capture and visible in another | The captures were taken at different web-font loading stages; browser behavior also differs. | Wait for document.fonts.ready for the settled case. If initial loading matters, create a separate controlled loading-state case. |
| A small pixel threshold passes but a glyph looks wrong | The threshold may be hiding a meaningful local change. | Inspect the diff visually. Tighten the threshold or use a stricter assertion for this fixture; focus on glyph forms, marks, spacing, and clipping. |
| Screenshot fails after changing the fixture text | The captured content no longer matches the baseline. | Confirm the new content is intended, review the new capture, then update the baseline deliberately. |
| Only mixed-script lines look misaligned | The Latin and Devanagari glyphs may have different baseline or line-box behavior. | Include the real mixed-script UI string and inspect baseline alignment and line height in the target environment. |
9. Keep the check fast and dependable
- Keep the fixture small. A focused page makes a diff easier to interpret and limits unrelated layout changes.
- Use stable content and page state. Remove unrelated animation or changing content from the fixture, and use Playwright’s screenshot options to disable animations where appropriate.
- Wait for the state you intend to capture. Font readiness improves settled-font repeatability; use a distinct test for loading behavior.
- Run comparisons in a consistent environment. This reduces false alarms from rendering differences unrelated to a font change.
- Use thresholds as noise controls, not as proof of correctness. Pixel thresholds can permit variation, but a reviewer still needs to check whether critical glyph details changed.
- Update baselines intentionally. A baseline is a reviewed reference image, not an automatic approval of every visual change.
The cost of this workflow is mainly the maintenance of the fixture, controlled browser environment, and review of changed images. Keep the number of target environments aligned with the browsers and platforms you actually support; use separate projects when cross-environment behavior is part of the requirement.
10. Or skip the browser setup
If you want a screenshot without maintaining your own browser capture setup, ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. One GET request can return a PNG, JPEG, WebP, or PDF. For this font-check workflow, capture the same fixture URL consistently and compare the returned images in your visual review process. The API also supports viewport and device settings, custom CSS and JavaScript, wait conditions, and other capture controls. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com/devanagari-font-fixture \
-o devanagari-shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={
"access_key": "YOUR_API_KEY",
"url": "https://example.com/devanagari-font-fixture",
},
timeout=90,
)
r.raise_for_status()
open("devanagari-shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com/devanagari-font-fixture',
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('devanagari-shot.webp', image));
- Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
- Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed; response headers report the page verdict and billing status.
- An MCP server lets AI agents use
take_screenshot,get_page_info, andcapture_pdf. - The free plan includes 1,000 screenshots a month with no card. Paid plans start at $5 for 3,000 screenshots.
Sign up free for 1,000 screenshots a month, no card required.
Frequently asked questions
Does a passing screenshot prove the font is correct?
No. It shows that the captured pixels match the baseline within the assertion’s threshold. Confirm the rendered typeface and inspect the relevant Devanagari shapes and marks.
Should I use one baseline for every browser?
No, if you intend to test multiple browsers or platforms. Keep a separate baseline for each target environment you support.
Is the W3C Devanagari resource a conformance test?
No. It is a draft layout and presentation resource that points to relevant shaping and positioning concerns.
Should I include mixed Latin and Devanagari text?
Include it when your interface uses mixed-script text. It helps expose baseline and line-layout issues that a Devanagari-only fixture may miss.


