Puppeteer Full-Page Screenshot Shows the Indian Rupee Symbol as Boxes: How to Fix It
Missing rupee glyphs usually point to font coverage or loading in Chromium. Check the installed fonts, page font stack, and readiness before changing screenshot settings.
If the Indian rupee symbol (₹) appears as a box in a Puppeteer full-page screenshot, first check whether Chromium has access to a font containing that glyph and whether the page can load or fall back to that font. The fullPage option controls how much of the page is captured; it does not install fonts or supply missing glyphs. The exact fix depends on your operating system, container image, installed fonts, and CSS font stack.
1. Check the font before changing screenshot settings
A box in place of ₹ is a font-rendering symptom to investigate. Start with the affected element and the browser runtime that creates the screenshot:
- Confirm the page content contains the actual rupee character,
₹(Unicode U+20B9), rather than a corrupted or substituted character. - Inspect the element’s computed
font-familyand determine which font Chromium actually uses for the glyph. - Check that the selected font is available in the same environment where Puppeteer runs and contains the rupee glyph.
- If the page uses a web font, verify that its request succeeds and that the font is usable before capture.
- Capture a small test containing ₹ in the same runtime, CSS, browser, and output format as the failing screenshot.
A CSS font-family name is a preference, not proof that the font exists in a Linux container or on a server. A fallback helps only if that fallback is installed and covers the glyph. The right font package varies by distribution; there is no single package or CSS family that can be prescribed for every deployment.
2. Wait for page fonts, then capture
For web fonts, wait for the browser’s font-loading work before taking the screenshot. This helps avoid capturing before a requested font finishes loading, but it cannot install a missing font or guarantee the preferred font is present.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle0' });
// Wait for font-loading work to finish. This does not install fonts.
await page.evaluate(() => document.fonts.ready);
await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
await browser.close();
}
})();
Replace the example URL with the page you capture. If the site never reaches network idle because it keeps connections open, use a more appropriate navigation condition for that site and separately wait for the content and fonts you need. Font readiness is one check, not proof of correct glyph coverage.
3. Verify fonts in the deployed runtime
Local development and deployment can use different operating systems, base images, font inventories, and browser dependencies. A screenshot that looks correct locally but shows boxes in production points toward a difference in that rendering environment or its page inputs.
- Inspect installed font files or the font inventory using tools appropriate to your operating system and container distribution.
- Use a font that includes U+20B9 and make sure the page’s font stack can select it.
- If installing fonts into an image, rebuild or restart the runtime so Chromium sees the updated inventory.
- Check the web-font request and computed style in the deployed browser, not only in your local browser.
Puppeteer’s troubleshooting guide includes environment-specific setup examples. Those examples are not a universal prescription for rupee glyph coverage; select a suitable font for your target system. Puppeteer troubleshooting documentation.
4. Compare viewport and full-page captures
Puppeteer describes fullPage as taking a screenshot of the full page. It changes capture scope, not the font inventory or glyph support. Compare a viewport capture and a full-page capture of the same content:
await page.screenshot({ path: 'viewport.png' });
await page.screenshot({ path: 'full-page.png', fullPage: true });
If ₹ is boxed in both images, focus on the page’s text, font selection, font loading, and runtime. If it differs between captures, investigate whether the affected content or styling changes as the page is resized or scrolled; the full-page setting itself is not a font installation setting. Puppeteer documents the option in its ScreenshotOptions API.
5. Troubleshooting common causes
| Symptom or check | Likely cause | What to do |
|---|---|---|
| ₹ is a box locally and in deployment | The chosen font may lack the glyph, or the page content may not contain the intended character. | Confirm U+20B9 is present, inspect computed font family, and test with an available font that covers it. |
| It works locally but fails in a Linux container | The deployed runtime may have a different or smaller font inventory. | Inspect the target image’s installed fonts and add an appropriate font for that distribution; rebuild or restart after changing it. |
| The page uses a web font but renders boxes | The font request may have failed, or the loaded font may not contain ₹. | Check the request result and font coverage. Await document.fonts.ready, then verify the rendered result. |
document.fonts.ready resolves, but boxes remain |
Readiness does not mean the preferred font is installed or that it supports the character. | Check the actual available font and fallback chain; install or select a font with the glyph. |
| Viewport works but full-page capture fails | The page may change layout, content, or styles during full-page capture. | Compare the same glyph and computed styles in both modes and inspect page behavior at the relevant dimensions. |
| Changing CSS font-family has no effect | The named font may not be available to Chromium, or another rule may override the style. | Inspect computed styles and the runtime font inventory; ensure the intended font is actually selectable. |
6. Performance, reliability, and cost considerations
Waiting for fonts adds a readiness step to capture time, and waiting for network idle can take longer or fail to settle on pages with persistent network activity. Prefer waits that match the page’s actual dependencies, and make sure a font-ready check is followed by visual validation. For repeatable production results, use a known runtime image and font setup, then validate screenshots after changes to that image or the page’s font assets.
The cited Puppeteer documentation does not establish a universal timing, reliability benchmark, or monetary cost for this fix. Operational cost depends on your browser runtime, infrastructure, and capture volume.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its API returns an image or PDF from one GET request; see the API documentation for options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
- Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; each step can be turned off.
- Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are never billed. Responses identify the page verdict and billing status in headers.
- An 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 on every plan.
Sign up for 1,000 free screenshots a month, with no card.
FAQ
Does fullPage: true fix missing characters?
No. It requests a full-page capture. It does not provide fonts or glyphs.
Will waiting for document.fonts.ready always fix the box?
No. It waits for font-loading work to settle; it cannot install a font or add missing glyph coverage.
Why does the screenshot differ from my desktop browser?
The deployed browser may have a different font inventory or page font-loading behavior. Check both in the runtime that produces the screenshot.
Which Linux font package should I install?
That depends on the distribution and the font coverage you need. Inspect the target image and choose a font containing U+20B9; the available evidence does not support one universal package recommendation.
Sources
- Puppeteer ScreenshotOptions: documents the full-page option.
- Puppeteer troubleshooting: environment-specific runtime setup guidance.
- Puppeteer Page API: page screenshot API reference.
- Puppeteer screenshots guide: supplementary guidance on font readiness and installed fonts.


