ScreenshotNeo

BlogHow-to

How to Capture a Playwright Screenshot of a Marathi Website with Correct Text Rendering

Wait for Marathi content and web fonts, verify the rendered glyphs, then capture a reproducible Playwright screenshot. Troubleshoot missing or incorrect text step by step.

By the ScreenshotNeo team4 October 20269 min read

To capture a Marathi website with correct text rendering in Playwright, first wait for the target Marathi content to appear, then wait for the document’s fonts to settle, verify that the intended font and Devanagari glyphs actually rendered, and only then take the screenshot. document.fonts.ready is a synchronization point, not proof that a particular font loaded or supports Marathi. If the image looks wrong, inspect the page text and font state separately before changing screenshot options.

This guide uses JavaScript with Playwright. The same browser-side font checks work with Playwright’s Python API. Standardize the browser and operating system when comparing screenshots; font availability, browser versions, settings, and headless mode can all change pixels. See Playwright’s visual comparison guidance.

1. Install Playwright and prepare a capture

For a small standalone script, install Playwright and its Chromium browser:

npm init -y
npm install playwright
npx playwright install chromium

Save the following as capture-marathi.js. Set TARGET_URL to the page you are authorized to capture. Replace the example content selector with a stable locator for the Marathi content on your page. The selector wait prevents taking a screenshot before the relevant page section exists.

const { chromium } = require('playwright');

const url = process.env.TARGET_URL;
const contentSelector = process.env.CONTENT_SELECTOR || 'body';

if (!url) throw new Error('Set TARGET_URL to the page URL');

(async () => {
  const browser = await chromium.launch({ headless: true });
  const page = await browser.newPage({
    viewport: { width: 1440, height: 1000 },
    deviceScaleFactor: 1,
  });

  try {
    await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
    await page.locator(contentSelector).waitFor({ state: 'visible', timeout: 15000 });

    // Useful synchronization point; it does not prove a specific face loaded.
    await page.evaluate(() => document.fonts.ready);

    const diagnostics = await page.evaluate((selector) => {
      const el = document.querySelector(selector);
      const text = el?.innerText || '';
      const style = el ? getComputedStyle(el) : null;
      return {
        textSample: text.slice(0, 240),
        fontFamily: style?.fontFamily || null,
        fontStatus: document.fonts.status,
        declaredFonts: [...document.fonts].map(font => ({
          family: font.family,
          status: font.status,
          weight: font.weight,
          style: font.style,
        })),
      };
    }, contentSelector);
    console.log(JSON.stringify(diagnostics, null, 2));

    await page.screenshot({ path: 'marathi-page.png', fullPage: true });
  } finally {
    await browser.close();
  }
})();

Run it with the target route and selector:

TARGET_URL='https://example.com/mr/page' CONTENT_SELECTOR='main article' node capture-marathi.js

The example logs text, computed font-family, the font set’s status, and the faces known to the document. It does not automatically determine whether each character has a glyph in the selected font. Inspect the screenshot and browser font-loading evidence as well.

2. Wait for the content and the relevant fonts

Use a readiness condition tied to the page’s actual state. domcontentloaded means the initial document was parsed; it does not guarantee that a client-rendered article, translated content, or lazy section has appeared. Wait for a meaningful selector, and if necessary wait for a known Marathi phrase or application-specific ready marker.

await page.goto(url, { waitUntil: 'domcontentloaded' });
await page.getByText('मराठीतील अपेक्षित मजकूर', { exact: false }).waitFor();
await page.evaluate(() => document.fonts.ready);
await page.screenshot({ path: 'marathi.png', fullPage: true });

If the target text or font loads only after scrolling, scrolling, opening a menu, or dismissing an interstitial, perform that action first. Then wait for the target content and fonts again. A site may load different font files for different sections or scripts.

MDN describes document.fonts as the document’s font set and document.fonts.ready as a promise that resolves when font loading and related layout operations complete. Optional fonts may not load in time, so the used fonts can differ from the declared ones. Read MDN’s Document.fonts reference.

Check a specific face when you know its family

You can ask the browser whether a face matching a CSS font shorthand is available for sample text:

const fontCheck = await page.evaluate(() => ({
  ready: document.fonts.status,
  hasFaceForSample: document.fonts.check('16px "Site Marathi Font"', 'मराठी मजकूर'),
}));
console.log(fontCheck);

Use the actual family declared by the site. A positive check is not a visual inspection and should not be treated as a universal guarantee of correct shaping or appearance. Check the rendered page in the same browser runtime used for the screenshot. Chrome explains that a system fallback can display while a web font is not ready, and swapping from a temporary face to a custom face can change layout; see Chrome’s font-display guidance.

3. Capture viewport or full page

Choose the capture extent deliberately. A viewport screenshot captures the current visible area; fullPage: true captures the page’s full scrollable height. Full-page capture can expose content below the fold, but some sites only load that content after scrolling. Trigger the site’s lazy-loading behavior before capture when those sections matter.

// Current viewport
await page.screenshot({ path: 'marathi-viewport.png' });

// Entire scrollable page
await page.screenshot({ path: 'marathi-full.png', fullPage: true });

Playwright’s screenshots documentation covers screenshot capture and related options. For a visual regression test, toHaveScreenshot() waits for two consecutive screenshots to match before saving or comparing. That stabilization helps with visual output; it does not establish that the intended font face supports the text. See Playwright visual comparisons.

4. Diagnose boxes, fallback glyphs, and unexpected text

Separate content problems from rendering problems. First confirm the Marathi string exists in the DOM or accessibility representation. Then inspect computed styles and font loading, and finally inspect the pixels. A screenshot is visual evidence; it cannot tell you by itself whether text is absent from the page structure or merely rendered incorrectly. Playwright describes screenshots as visual verification and accessibility snapshots as a way to inspect structure in its screenshots and PDF guidance.

  1. Confirm the text exists. Read innerText or locate the expected Marathi phrase. If it is absent, investigate navigation, application rendering, localization, or data loading before font settings.
  2. Check the computed font-family. This is the requested CSS stack, not necessarily proof of the exact face used for every glyph.
  3. Check font loading. Review document.fonts.status, individual face statuses, and browser network/console errors for failed font requests.
  4. Inspect the actual capture runtime. Confirm Marathi is visible in the same browser engine, version, OS image, and headless configuration that produced the screenshot.
  5. Compare after fonts settle. If the initial appearance differs from the settled appearance, layout or glyph shape changed during font swap; capture only after the relevant state is stable.

Do not add an arbitrary font-family or locale setting on the assumption that one choice guarantees every Marathi page. The available evidence does not establish a universal font stack or browser configuration for Marathi. Verify the site’s intended face and the rendered output.

5. Make screenshots reproducible

For visual comparisons, keep the environment consistent: browser engine and version, operating-system image and installed fonts, headless/headed mode, viewport and device scale factor, and relevant capture options. Playwright warns that rendering can vary across host OS, version, settings, hardware, power source, headless mode, and other factors. A baseline made on a developer laptop may therefore differ from CI even when the page code has not changed.

When a difference appears, record the Playwright version, browser version, operating system, headless setting, viewport, target selector, font status, and whether the capture was viewport or full page. Compare the same route with the same inputs before concluding the Marathi text itself caused the change.

6. Troubleshooting

Symptom Likely cause What to do
Marathi characters appear as boxes or replacement symbols The active font may not contain the required glyphs, a font request failed, or the intended face was not used. Check the computed font stack, font network responses, and loaded face statuses. Inspect the same route in the capture browser and verify the installed fallback fonts. Do not assume that waiting alone adds missing glyph coverage.
Text is visible but its shapes or spacing differ from the browser window The screenshot may use a different browser, OS font set, browser version, headless mode, or a font that loaded after the initial render. Standardize the capture environment and wait for the relevant font state. Compare computed styles and inspect the settled screenshot.
Screenshot is blank or the text is missing The route may not have finished rendering, the selector may target the wrong element, or content may require client-side data, scrolling, or interaction. Wait for a meaningful visible selector or exact text, check page errors and response state, and trigger the required interaction or lazy loading.
document.fonts.ready resolves, but the wrong font remains The promise indicates the font set and related layout operations settled; optional fonts can be omitted, a request may have failed, or the requested face may lack the needed glyphs. Inspect actual font requests and face statuses, verify the family name and glyph coverage, and visually confirm the result. Use a suitable installed or site-provided font only after confirming the cause.
Font wait hangs or times out A page/font-loading issue or browser-specific behavior may be involved. Capture the Playwright version, browser engine and version, OS, and font-loading state. A report describes a timeout on one Linux WebKit/Playwright 1.63.0 setup with a 1.60.0 control passing in that reproduction; it is a specific issue report, not evidence of a general Marathi problem. See Playwright issue 42986.
Full-page capture omits lower Marathi sections The page may lazy-load sections or font resources only after scrolling. Scroll through the relevant content to trigger loading, wait for its content and fonts, then capture full page.
Visual test fails intermittently Animations, content changes, asynchronous rendering, or differing environments can change pixels. Wait for the application’s stable state, use Playwright screenshot assertions where appropriate, and pin the browser/OS/font environment used for baselines.

7. Performance, reliability, and cost

For a one-off capture, a selector wait plus a font-ready wait is usually a small addition compared with launching a browser and loading the page. Avoid a fixed long sleep as the only synchronization method: it can waste time on fast pages and still be too short on slow ones. Prefer explicit conditions tied to the content and font state you need, with timeouts that let failures surface clearly.

Browser screenshots are only as reliable as the page state and runtime you control. Reuse a browser process for batches of captures where appropriate, while creating a fresh page or context when isolation matters. Keep the browser version and operating environment aligned for regression work. Cost depends on where and how you run the browser; this workflow has no per-screenshot API charge, but you operate the browser environment and its compute.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF. For a page that needs Marathi text, the API can capture the rendered site without you installing and managing Playwright locally; still inspect the returned image when exact font rendering matters. 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/mr/page \
  -o marathi-page.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com/mr/page"},
    timeout=90,
)
r.raise_for_status()
open("marathi-page.webp", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://example.com/mr/page',
});
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('marathi-page.webp', bytes));
  • 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, and failed loads are never billed, and response headers report the page verdict and billing status.
  • An MCP server lets AI agents, including Claude and Cursor, take screenshots with the take_screenshot tool.
  • 1,000 screenshots a month are free with no card; paid plans start at $5 for 3,000 screenshots.

Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.

FAQ

Does waiting for fonts guarantee correct Marathi glyphs?

No. It coordinates with font loading, but does not prove the intended face loaded or includes every required glyph. Check the face, requests, and rendered result.

Should I set a special browser locale for Marathi?

Only if the site’s behavior depends on locale. The available sources do not prescribe a locale that guarantees correct Marathi font rendering.

Why does the same screenshot differ between my machine and CI?

Browser version, operating system and installed fonts, settings, headless mode, and other environment details can change rendering. Keep them consistent for comparisons.

Can a screenshot tell whether the Marathi text is in the page?

No. Inspect the DOM or accessibility structure alongside the pixels to distinguish missing content from incorrect rendering.