How to Show the Correct Hindi Font in Puppeteer Website Screenshots
Fix missing or incorrect Hindi characters in Puppeteer screenshots by checking fonts, CSS fallbacks, and the exact Linux or container runtime.
To show Hindi correctly in a Puppeteer screenshot, make sure a Devanagari-capable font is installed in the same operating system or container that runs Chromium, set a suitable CSS font stack, and capture only after the page’s fonts have loaded. Puppeteer automates the browser; it does not supply Hindi fonts. A font installed on your laptop is not automatically available inside a deployment container.
For a useful starting stack, use "Noto Sans Devanagari", "Noto Sans", sans-serif. If you prefer serif text, use "Noto Serif Devanagari", serif. The exact font files and package names depend on your Linux distribution and base image, so verify the setup in the environment that produces the screenshot. ScreenshotNeo’s API documentation describes an alternative when you do not want to manage browser setup yourself.
1. Confirm where Chromium gets its fonts
Chromium uses fonts available to the operating environment in which it runs. If Puppeteer runs in Docker, check the container, not just your workstation. A missing Devanagari font can lead to fallback to a different face, visibly inconsistent text, or missing-glyph boxes.
Do not assume Chromium’s generic font mapping is identical across versions or Linux distributions. A Chromium change dated March 4, 2026 added Linux default mappings for Devanagari: Noto Sans Devanagari for standard and sans-serif, and Noto Serif Devanagari for serif. This does not mean every older Chromium build or distribution includes the font files. Verify both the browser build and the installed fonts in your runtime. Chromium source change
2. Set a Devanagari-aware CSS font stack
Choose a family with Devanagari glyph coverage, then provide sensible fallbacks. Noto’s guidance uses script-specific families followed by general fallbacks. Noto font guide
/* Apply this to the Hindi text or its containing element. */
.hindi {
font-family: "Noto Sans Devanagari", "Noto Sans", sans-serif;
}
/* For a serif design, use this instead. */
.hindi-serif {
font-family: "Noto Serif Devanagari", serif;
}
A CSS font name does not install a font. If the requested family is unavailable, the browser selects a fallback. For consistent output across machines, make the font available in the deployed runtime and keep an appropriate CSS fallback for other environments.
3. Install and verify the font in the screenshot runtime
- Identify the exact container image or host where Puppeteer launches Chromium. Record the Linux distribution, Puppeteer version, and browser build.
- Use that distribution’s package documentation to find a package that supplies a Devanagari font such as Noto Sans Devanagari. Package names vary, so do not copy a package name from another distribution without checking it.
- Build the font into the image, or otherwise make the font files available to the Chromium process. Installing it only on the developer machine will not fix screenshots made in a separate container.
- Check the runtime’s font listing or family lookup to confirm the expected family is visible. Follow your distribution’s instructions for refreshing its font cache if needed.
- Capture a page containing representative Hindi text from the same image and browser build used in production.
This deployment-specific verification matters because Chromium’s defaults and available font files can differ. Puppeteer’s troubleshooting guide also covers Linux browser dependencies; it is useful when Chromium itself will not launch. Puppeteer troubleshooting
4. Capture after the page has loaded its fonts
If the font is available but the screenshot still shows a fallback face, the page may be captured before its web fonts finish loading. The following Node.js example waits for the document’s font set before taking a screenshot. It assumes the page can be reached and Puppeteer’s browser dependencies are installed.
import puppeteer from 'puppeteer';
const url = 'https://example.com';
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2', timeout: 60_000 });
// Wait for document fonts, including web fonts, before capture.
await page.evaluate(async () => {
await document.fonts.ready;
});
await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
await browser.close();
}
Replace https://example.com with the page you need to capture. If the site keeps network connections open, networkidle2 may take too long or never be reached; use a navigation condition appropriate to that page, then still wait for the fonts before capture. This snippet uses the document font set to wait for fonts the page has requested; it cannot make an unavailable font appear.
5. Diagnose the result
| What you see | Likely cause | What to check |
|---|---|---|
| Boxes or missing Hindi glyphs | No usable font covers the characters, or the font is unavailable to Chromium. | Check installed Devanagari font files and the CSS family in the actual runtime. |
| Hindi appears, but the style differs from the page design | The named CSS family was not resolved and Chromium chose a fallback. | Verify the family is available and the font stack names it correctly. |
| The first capture looks wrong, but a later one looks right | The screenshot may have happened before a web font finished loading. | Wait for document.fonts.ready before capture. |
| Chromium fails to launch | This may be a missing shared library or another browser runtime problem rather than a font problem. | Follow Puppeteer’s Linux troubleshooting steps. Its guide suggests checking missing libraries with ldd chrome | grep not. |
6. Common errors and fixes
“It works locally but not in Docker”
The local machine has a font that the container does not. Add a suitable Devanagari font to the container image using instructions for its Linux distribution, then rebuild and verify inside the container.
“I set Noto Sans Devanagari in CSS, but the screenshot still looks wrong”
The CSS family name only requests a font; it does not provide the font file. Confirm the family is visible to the browser in the runtime. Also check that the CSS rule applies to the element containing the Hindi text and is not overridden.
“Some words look correct, but other characters do not”
Check the exact characters and the font’s coverage, including any marks or conjuncts present in the text. Try a representative sample from the page and verify that the selected face can render it. If a particular font lacks coverage, choose an installed face that covers the needed text and keep a fallback.
“The browser never reaches network idle”
Some pages keep requests active. Choose a navigation wait condition that fits the page, and separately wait for the document’s fonts before the screenshot. A navigation timeout and a missing-font problem are distinct issues.
“Puppeteer cannot start Chromium”
Do not treat every failed screenshot as a font issue. Check Puppeteer’s runtime dependency guidance and inspect missing shared libraries in the Chromium binary environment. A browser launch failure happens before page font rendering can be diagnosed.
7. Reliability, performance, and deployment notes
- Pin and record the runtime: Log the container image, Puppeteer version, and browser build used for captures. Font mapping can change between browser builds.
- Keep fonts in the image: A reproducible image makes it easier to ensure the same font files are available after redeployments.
- Wait for the needed condition: Waiting for fonts avoids capturing an early fallback, while waiting indefinitely for network idle can make capture unreliable on pages with persistent requests.
- Separate failures: Missing glyphs point toward font availability or fallback; launch errors call for browser dependency checks; navigation timeouts call for page-loading diagnosis.
- Account for font loading in capture time: Font installation itself is a deployment concern, while remote web fonts can add page-load work. Avoid unnecessary waits that are unrelated to the page’s readiness.
There is no universal Linux package command in the available guidance: package names and font cache steps depend on the base distribution. Check its current documentation instead of relying on an old Docker snippet.
8. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. One GET request returns a PNG, JPEG, WebP, or PDF. For a basic screenshot:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for the request options. ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture.
The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is available on every plan. Sign up for 1,000 free screenshots a month, with no card.
FAQ
Does Puppeteer include a Hindi font?
No. Puppeteer automates a browser; the operating environment must provide fonts that Chromium can use.
Should I use Noto Sans Devanagari or Noto Serif Devanagari?
Choose the style that matches the design: Noto Sans Devanagari for sans-serif text and Noto Serif Devanagari for serif text. In either case, verify the font is available in the screenshot runtime.
Will a newer Chromium automatically fix a missing Hindi font?
No. A newer Linux mapping may select a Devanagari family by default, but the font files still need to be available, and behavior depends on the Chromium build and distribution.
Do I need to wait for fonts when the site uses only system fonts?
Waiting for the document font set is a useful capture safeguard. It does not install fonts or correct a CSS family that cannot be resolved.


