ScreenshotNeo

BlogHow-to

How to Capture Hindi Web Pages with Playwright Screenshots

Capture Hindi pages with legible Devanagari text using Playwright. Set up fonts, wait for content, choose screenshot options, and troubleshoot common issues.

By the ScreenshotNeo team4 October 20267 min read

To capture a Hindi web page with Playwright, navigate to it, wait for the page content and any web fonts it uses, then call page.screenshot(). Use fullPage: true for the entire scrollable document. For legible Devanagari, make sure the page has a font with Devanagari coverage and shaping support, and keep the browser environment consistent when comparing screenshots.

This guide uses Playwright’s JavaScript API. The same workflow applies whether the page is a Hindi news site, a localized application, or a page with Hindi mixed with other scripts.

1. Install Playwright and capture a Hindi page

Start with a small Node.js project and install Playwright:

mkdir hindi-capture
cd hindi-capture
npm init -y
npm install playwright
npx playwright install chromium

Save this as capture.js. Set TARGET_URL to the page you are allowed to access and capture.

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

(async () => {
  const url = process.env.TARGET_URL || 'https://example.com';
  const browser = await chromium.launch({ headless: true });
  const page = await browser.newPage({
    viewport: { width: 1365, height: 900 },
    deviceScaleFactor: 1,
  });

  try {
    await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30_000 });
    await page.locator('body').waitFor({ state: 'visible', timeout: 15_000 });

    // This resolves when fonts known to the document have finished loading.
    // It is a deliberate readiness step; do not assume screenshot() itself
    // universally waits for every custom web font.
    await page.evaluate(() => document.fonts.ready);

    await page.screenshot({ path: 'hindi-page.png', fullPage: true });
  } finally {
    await browser.close();
  }
})().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

Run it with TARGET_URL=https://your-site.example node capture.js. The example waits for the document and visible body, then waits for font readiness. For a single-page application, replace the body check with a locator or app-specific condition that indicates the Hindi content has actually rendered. A generic body being visible does not mean asynchronous page data is ready.

2. Make Devanagari font rendering predictable

A screenshot records what the browser rendered. Playwright cannot turn a font without the required glyphs into a Devanagari font. If characters appear as boxes, marks are missing, or text looks different from another machine, check the page’s computed font family, whether its web font loaded, and which fallback font is available.

For a sans-serif Hindi interface, Noto Sans Devanagari is one script-specific option. Include a fallback and a generic family at the end of the stack:

body {
  font-family: "Noto Sans Devanagari", "Noto Sans", sans-serif;
}

The site must actually load or have access to those font files; listing a family in CSS alone does not install it. Google Fonts recommends listing a fallback web-safe font, and Noto’s guidance explains that browsers fall back through the family list when a face lacks characters. Devanagari also needs software support for complex text layout. See the Noto Sans Devanagari UI family notes, Google Fonts guidance, and Noto usage documentation.

If you control the page, verify that the intended font is loaded and that the computed family is correct before capture. If you do not control it, wait for document.fonts.ready and inspect the rendered result; fallback may still be used when the requested face is unavailable.

3. Choose the screenshot area and output

Playwright’s page screenshot API supports several controls. Choose the smallest capture that answers your use case: full-page images can become very tall, while a viewport or clip can keep output manageable.

Goal Option What it does
Visible viewport page.screenshot({ path: 'page.png' }) Captures the current visible page area.
Entire scrollable page fullPage: true Captures the full scrollable document as a tall image.
One region clip: { x, y, width, height } Captures the specified rectangle.
Image encoding type: 'png', 'jpeg', or 'webp' Selects the output format. Use a format supported by the API and your downstream workflow.
Pixel scale scale: 'css' or 'device' CSS scale uses one output pixel per CSS pixel; device scale follows device pixels.
Transparent background omitBackground: true Omits the default background for formats that support transparency; it does not apply to JPEG.
Hide caret caret: 'hide' Hides the text caret; this is the documented default.
Mask or style content mask and style Can cover or alter selected content. Use intentionally because this changes the image.

For example, capture a smaller region at CSS-pixel scale:

await page.screenshot({
  path: 'hindi-section.png',
  type: 'png',
  scale: 'css',
  clip: { x: 0, y: 0, width: 900, height: 650 },
});

Use fullPage when you need the entire document and a clip or viewport capture when you only need a section. Full-page capture can produce a large image; choose dimensions and scale based on where the file will be viewed or stored. Playwright documents screenshot styling and visual assertion options in its visual comparisons guide.

4. Wait for the right page state

There is no single readiness signal that fits every site. Navigation completion can happen before a client-rendered page has populated its content, and an arbitrary sleep can be either too short or wasteful. Prefer a meaningful locator or app-specific readiness condition.

await page.goto(url, { waitUntil: 'domcontentloaded' });
await page.locator('main article').waitFor({ state: 'visible' });
await page.evaluate(() => document.fonts.ready);
await page.screenshot({ path: 'article.png', fullPage: true });

If images are lazy-loaded further down the page, a full-page screenshot may not by itself guarantee that every image has loaded. For a page you control, use the site’s own readiness signal or deliberately scroll through relevant sections and wait for the assets your capture requires. Keep these waits bounded with timeouts so a failed request does not hang a job indefinitely.

5. Keep visual comparisons reproducible

For visual regression, capture the baseline and later screenshots with the same host OS, browser version, settings, hardware, power conditions, and headless mode. Playwright notes that these can affect browser rendering. A web font can also render differently if it is missing, not loaded, or substituted by a fallback.

Playwright Test’s expect(page).toHaveScreenshot() is intended for screenshot comparisons and waits for consecutive matching screenshots. That behavior is distinct from calling page.screenshot() directly. Stabilize content such as timestamps, rotating banners, and personalized text only when doing so matches the purpose of the visual test; masking or stylesheet overrides change what the screenshot represents.

6. Troubleshoot common Hindi screenshot problems

Symptom Likely cause What to check or change
Devanagari appears as boxes or missing characters The selected face or available fallbacks lack the needed glyphs, or shaping support is unavailable. Inspect computed fonts and loaded font resources. Use a Devanagari-capable face such as Noto Sans Devanagari and retain a fallback stack.
Text looks different from the interactive browser The web font may not have loaded before capture, or the capture environment differs. Wait for document.fonts.ready, verify the loaded face, and keep browser and host environment consistent.
Screenshot shows a blank or incomplete application The capture began after navigation but before the app populated its content, or a required request failed. Wait for a meaningful page locator or application readiness signal; inspect failed requests and console errors.
Lower content is missing The screenshot captured only the viewport. Set fullPage: true, or use a clip around the region you need.
Full-page output is unexpectedly huge The document is very tall or the chosen scale creates a large raster. Capture a viewport or clip, or reduce output scale where appropriate.
Images below the fold are absent They may be lazy-loaded and not yet requested or decoded. Use a site-specific loading signal or scroll through relevant content and wait for the required images.
Screenshots differ between runs Environment or dynamic page content changed. Pin browser and execution environment, stabilize only the dynamic elements relevant to the test, and consider Playwright’s screenshot assertion.
Navigation or readiness wait times out The page is slow, inaccessible, or waiting for a condition that never occurs. Use a meaningful locator, set an explicit timeout, and inspect network and page errors rather than extending arbitrary sleeps without diagnosis.

7. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its one-request API can return a screenshot or PDF; see the ScreenshotNeo API documentation for options. For a Hindi page, send the target URL and save the returned image:

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

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const fs = require('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. These API captures are useful when you want to avoid maintaining a browser setup; use Playwright directly when you need its browser automation and test controls.

Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.

FAQ

How do I take a full-page screenshot in Playwright?

Call await page.screenshot({ path: 'page.png', fullPage: true }) after the page is ready.

Why does Hindi text look different or show boxes in my Playwright screenshot?

Check Devanagari glyph coverage, shaping support, font loading, and fallback fonts. Also compare captures in the same browser and host environment.

How do I wait for web fonts before taking a Playwright screenshot?

Run await page.evaluate(() => document.fonts.ready) after navigation and before capture. Treat it as an explicit workflow step rather than relying on screenshot capture to wait for all custom fonts.

Which format should I use?

Playwright supports PNG, JPEG, and WebP screenshots. Pick based on the quality, transparency, and file-handling needs of your destination; the reviewed sources do not establish a universal best format for Hindi text.

Sources