ScreenshotNeo

BlogHow-to

wkhtmltoimage Hindi Text Rendering: Fix Devanagari Characters Showing as Boxes

Diagnose Devanagari boxes in wkhtmltoimage by checking font discovery, character coverage, and script layout in the renderer’s actual runtime.

By the ScreenshotNeo team4 October 20267 min read

When Hindi text appears as empty boxes in a wkhtmltoimage screenshot, first check whether the rendering process can find a font that contains the Devanagari characters on the page. If characters appear but vowel signs, conjuncts, or their placement are wrong, investigate script layout and shaping support as a separate possibility. A font installation may help with missing glyph coverage, but it is not a guaranteed fix for every page or legacy renderer.

The useful distinction is what the output looks like:

Output symptom First area to investigate
Empty squares or replacement boxes Whether the renderer can discover a font with the needed Devanagari characters
Letters appear, but vowel signs or conjuncts are misplaced or broken Whether the rendering stack lays out Devanagari clusters and combining marks correctly
A minimal test works, but a news site fails The site’s CSS, remote fonts, loading behavior, and the exact renderer environment

1. Reproduce the problem with a small local page

Start with literal Unicode text in a local HTML file. Include independent characters, vowel signs, and a conjunct so the test covers more than basic glyph presence. Render it with the same wkhtmltoimage executable, account, container, service, and environment that produce the failing image.

<!doctype html>
<html lang="hi">
<head>
  <meta charset="utf-8">
  <title>Devanagari rendering check</title>
  <style>
    body { font-family: sans-serif; font-size: 32px; }
  </style>
</head>
<body>
  <p>हिन्दी परीक्षण: कि कु के को</p>
  <p>क्ष त्र ज्ञ श्र</p>
</body>
</html>

Save it as devanagari-check.html, then run:

wkhtmltoimage --encoding utf-8 devanagari-check.html devanagari-check.png

Open the PNG and compare it with the same HTML in a current browser. If the local file also shows boxes, focus first on font visibility and coverage. If the characters exist but their combinations differ, investigate layout behavior. If the local file looks correct while the target site does not, compare its CSS, selected web fonts, loading, and remote resources.

This is a diagnostic isolation step, not a confirmed fix from the historical issue report. The archived report describes Devanagari trouble on some Indian newspaper sites but does not establish a universal cause or resolution. See wkhtmltopdf issue #4797.

2. Check fonts from the renderer’s runtime

Checking fonts in your interactive desktop session is not enough if a service, container, scheduled task, or different user runs wkhtmltoimage. Inspect font availability in the context that launches the process, then confirm that an available font covers the code points used by the page.

Qt normally uses fontconfig to access system fonts and FreeType to produce font output. A font can be valid Unicode and still lack particular characters; Qt’s documentation cautions that fonts usually do not contain every Unicode character. These details describe Qt’s font model, but do not prove which Qt version or dependencies a particular wkhtmltoimage package uses. Qt documentation: Fonts for Embedded Linux.

  1. Identify the actual executable and execution context. Record the binary path, operating system, user or service account, container image, and package/build information.
  2. Check which fonts that context can discover through its font configuration. On systems that provide fontconfig tools, inspect the available font list with the tools installed for that environment.
  3. Verify that a candidate font includes the specific Devanagari characters in the input, not merely Latin characters or a generic Unicode label.
  4. Repeat the minimal-page render after changing the environment, using the same executable and launch context as the real job.

If fontconfig is unavailable, Qt documents a fallback font database in an embedded Linux context. Do not assume that fallback behavior applies to a different platform or package; inspect the actual deployment.

3. Distinguish missing glyphs from layout problems

Devanagari rendering involves more than displaying isolated character shapes. Consonant clusters, virama, conjunct forms, and combining vowel signs affect how text is laid out. The W3C’s Devanagari layout document describes these script requirements, but it does not certify that a particular wkhtmltoimage build implements them correctly. W3C: Devanagari Layout Requirements.

  • Boxes or missing characters: check whether the renderer finds a font with the necessary glyph coverage.
  • Present glyphs with incorrect combinations: investigate the renderer’s script layout and shaping behavior.
  • Only one page fails: compare the page’s own font declarations and resources with the local test. A failed image-resource warning does not by itself explain a text-rendering problem.

The W3C document is a Group Draft Note, not an endorsement or a conformance claim about wkhtmltoimage. Use it to understand the script behaviors to inspect.

4. Compare the original page and exact renderer setup

Once the minimal test is understood, compare it with the failing page under controlled conditions. Change one factor at a time where practical, and keep notes so you can tell whether the output changed because of the font environment, the input page, or the rendering build.

  • Use the same input URL and capture options for repeat runs.
  • Record the exact wkhtmltoimage binary and runtime context.
  • Check whether the page depends on remote fonts or other resources, and whether those resources load in the renderer.
  • Compare the page in a current browser and the target renderer, while treating that comparison as evidence about the difference—not proof of a particular cause.
  • Keep a small local regression page with the affected characters so you can recheck changes to the host, fonts, or package.

The historical report includes newspaper pages, resource warnings, and other rendering messages along with its Devanagari symptoms. Those accompanying messages do not establish that font handling caused the entire failure. The project repository was archived in 2023, and the issue does not end with a maintainer-confirmed diagnosis or fix. Issue details and report history.

5. Common problems and fixes to investigate

Problem Likely area What to do
Every Hindi character is a box Font discovery or missing character coverage Check the fonts visible to the actual rendering process, then verify coverage for the text’s characters.
Some characters render, but others are boxes Partial font coverage or a fallback font that lacks some characters Identify the missing characters and check whether the available font set covers them.
Letters show, but vowel signs or conjuncts look wrong Script layout or shaping behavior Compare a controlled sample with a current browser and investigate the rendering stack; adding a font alone may not address layout.
It works in a terminal but fails in a service Different user, environment, container, or font configuration Run the diagnostic under the service’s actual account and runtime.
The local sample works, but a remote site fails Page-specific CSS, web fonts, loading, or resources Compare the site and minimal file, and inspect the page’s dependencies and renderer output together.
Installing a font made no difference The renderer may not see it, coverage may still be incomplete, or the symptom may be layout-related Verify font visibility from the job environment and classify the output symptom again.

6. Reliability, performance, and cost considerations

Keep the minimal render as a regression check whenever the operating system, renderer package, font configuration, or execution context changes. This makes it easier to catch environment differences before they affect production captures.

For performance, isolate the smallest test that reproduces the symptom before repeatedly rendering a complex page. A remote page may involve additional resources and loading behavior, so its result alone can make diagnosis slower. No failure-rate or performance benchmark is established by the cited sources.

For reliability, treat a successful render on one machine as evidence only for that binary and runtime. A service account or container may discover a different font set. The available sources also do not establish a universal wkhtmltoimage Devanagari fix or a cost comparison for self-hosting.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. It returns a PNG, JPEG, WebP, or PDF from one GET request. For this page, request an image capture of the target URL; see the ScreenshotNeo API documentation for options and setup.

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}`);
await Bun.write('shot.webp', res);

ScreenshotNeo accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots. All features are on every plan.

Sign up for 1,000 free screenshots a month, with no card required.

FAQ

Does installing a Devanagari font always fix boxes?

No. It can address missing font discovery or character coverage, but the specific renderer and page still need to be checked. If glyphs appear but combinations are malformed, investigate layout behavior too.

Does the archived wkhtmltoimage issue confirm a solution?

No. It records a report of trouble on some newspaper pages, not a confirmed diagnosis or universal fix.

Can the Qt font documentation prove what my wkhtmltoimage package uses?

No. It describes Qt’s documented font behavior, but the package’s version and dependencies must be identified in the environment where it runs.

Why test both a local page and the original site?

The local page isolates basic text rendering. The original site adds its own CSS, fonts, and resources, which can introduce separate variables.