ScreenshotNeo

BlogHow-to

How to Render a Marathi Webpage as a PNG Without Broken Fonts

Render Marathi text cleanly by using a Devanagari-capable font, waiting for it to load, and capturing in the same browser environment.

By the ScreenshotNeo team4 October 20266 min read

To render a Marathi webpage as a PNG without broken fonts, make sure the browser can load a font with Devanagari coverage, wait until the page’s fonts are ready, then capture the page in the same browser environment where you verified the text. A screenshot can preserve a fallback font just as readily as the intended font, so capture timing and runtime font availability matter as much as the CSS.

Marathi uses Devanagari. Use a script-capable font such as Noto Sans Devanagari, provide deliberate fallbacks, and inspect the actual output for missing glyphs or malformed clusters. Noto recommends choosing fonts for the writing systems in use and placing the most important script’s family first in the stack. [Noto Fonts]

1. Set up a Devanagari font stack

For a page you control, load a Devanagari family and name it first for Marathi text. Add a general Noto family and then a generic sans-serif fallback. Browsers try later families when an earlier one lacks characters, but fallback can change the page’s appearance, so verify it visually. [Noto Fonts]

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Devanagari:wght@400;500;700&display=swap" rel="stylesheet">
<style>
  body {
    font-family: "Noto Sans Devanagari", "Noto Sans", sans-serif;
  }
</style>

If the page is rendered in an offline container or a restricted network, load the font from an asset you control or install it in the runtime. Do not assume a font installed on your laptop is available to a hosted browser. Browser environments have their own font resources; for example, Cloudflare Browser Run documents that screenshots use fonts available in that environment and supports custom font injection. [Cloudflare Browser Run]

2. Wait for fonts, then capture with Playwright

Playwright can capture PNGs from a browser page, including the viewport or full page, and supports element screenshots and scale choices. [Playwright screenshots] The following runnable Node.js example navigates to a page, waits for document fonts, and saves a full-page PNG.

import { chromium } from 'playwright';

const url = process.argv[2] ?? 'https://example.com';
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } });

try {
  await page.goto(url, { waitUntil: 'networkidle', timeout: 60000 });
  await page.evaluate(() => document.fonts.ready);
  await page.screenshot({ path: 'marathi.png', fullPage: true, type: 'png' });
} finally {
  await browser.close();
}

Save this as capture.mjs, install Playwright with npm install playwright, install its browser with npx playwright install chromium, then run node capture.mjs https://your-site.example. Replace the sample URL. For a page with ongoing network activity, networkidle may never occur; use domcontentloaded or load and wait for the specific content and fonts instead.

Choose the capture scope and scale

  • fullPage: true captures the full document height. Omit it for the current viewport.
  • For just one region, locate it and call locator.screenshot({ path: 'section.png' }).
  • Use scale: 'css' for output dimensions matching CSS pixels or scale: 'device' for device-pixel dimensions. Confirm the target application’s needs before choosing; higher pixel dimensions increase file size. [Playwright screenshot API]

3. Diagnose the font failure

What you see Likely cause What to check
Empty boxes or missing marks The chosen font lacks glyph coverage, or the font request failed. Inspect the browser network panel for failed font requests and confirm a Devanagari-capable font is available in the capture runtime. [Noto Fonts]
Letters display but clusters look separated or malformed The selected font or browser combination may not apply the shaping features needed for complex script text. Try a suitable Devanagari font and validate the same content in the target browser. Unicode describes how Devanagari sequences map to glyphs and notes fallback behavior when a complete conjunct is unavailable. [Unicode Core Specification, Chapter 12]
Browser looks right, PNG looks wrong The capture may have happened before the font loaded, or the screenshot browser has different font resources. Wait for document.fonts.ready, compare browser and capture environments, and load or install the needed font in the capture runtime. This diagnosis follows from documented web-font loading and runtime differences. [Google Fonts knowledge] [Cloudflare Browser Run]

4. Check the result in its target environment

  1. Open the page in the same browser build or hosted runtime that produces the PNG.
  2. Inspect representative Marathi text, including conjuncts and punctuation used by the page.
  3. Confirm the intended font request succeeded and the page completed loading before capture.
  4. Compare the PNG against the browser rendering at the intended viewport and scale.

Browser builds and operating systems can differ in available fonts and features, so a result that looks correct locally may differ in a container. Playwright also notes that availability of some browser features can vary by operating system. [Playwright browsers]

5. Capture the same page with cURL, Python, or Node.js

For a direct API capture, ScreenshotNeo accepts a URL and returns an image or PDF. Its screenshot API and options are documented at ScreenshotNeo documentation. These examples save the response bytes; use a page whose font is already configured and publicly reachable by the capture service.

cURL

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

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://your-site.example"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://your-site.example'
});
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(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server from ScreenshotNeo. One GET request captures a URL. Configure the page itself with a Devanagari-capable font, then use the API call below; see the API documentation for options.

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

Cookie banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An 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. Sign up for 1,000 free screenshots a month, with no card.

Performance, reliability, and cost

For self-hosted captures, font downloads and page readiness add to capture time; cache or host fonts close to the rendering environment where appropriate. Waiting for all network activity can delay or block captures on pages with polling or long-lived requests, so prefer a page-specific readiness condition when network idle is unreliable. The exact delay depends on the page and runtime; no single timing guarantees font readiness across environments.

With ScreenshotNeo, only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Responses include X-Page-Verdict and X-Billed headers indicating the outcome. Pricing is Free for 1,000 shots/month, Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000; yearly billing gives two months free. Every feature is included on every plan.

FAQ

Will adding a font family fix every Marathi rendering issue?

No. The runtime must load that font, and the browser and font combination must shape the text correctly. Check the actual output in the target environment.

Should I use a full-page screenshot?

Use one when the whole document is needed. For a particular component, capture its locator to keep the image focused and smaller.

Why use PNG instead of another image format?

PNG is the requested lossless capture format and is supported by Playwright. If storage or transfer size matters, choose a format supported by your downstream workflow.