ScreenshotNeo

BlogHow-to

How to Set Hindi Fonts for wkhtmltoimage on Ubuntu

Install a Devanagari font where wkhtmltoimage runs, set it in CSS, and verify glyphs and shaping with the exact Ubuntu build you deploy.

By the ScreenshotNeo team4 October 20268 min read

Direct answer: install a Devanagari-capable font in the same Ubuntu environment that runs wkhtmltoimage, declare its family in the HTML or a user stylesheet, and render representative Hindi text with the exact binary and build you deploy. There is no Hindi-specific font switch in wkhtmltoimage: font selection comes from page CSS, while the renderer must be able to discover the installed font.

Hindi is the language; Devanagari is the script. A font needs the required Devanagari glyphs, and the renderer must shape combinations such as consonants, vowel marks, and conjuncts correctly. Installing a font can solve missing glyphs, but it does not guarantee correct shaping in every wkhtmltoimage build.

1. Check the renderer and Ubuntu runtime

First confirm which executable will render the page and where it runs. Fonts installed on a developer laptop do not automatically exist in a container, worker, or serverless runtime.

wkhtmltoimage --version
command -v wkhtmltoimage
cat /etc/os-release

Keep the version output and package or image details with your deployment notes. The wkhtmltopdf project identifies 0.12.6 as its stable series, released June 11, 2020, but builds and distribution packaging can differ. Ubuntu Noble’s manpage lists package version 0.12.6-2build2; check your own release and binary rather than assuming it matches.

2. Install a Devanagari font in the rendering environment

Noto Sans Devanagari and Lohit Devanagari are candidate families. The package name and availability depend on the Ubuntu release, so inspect the package metadata for the release used by your image before copying an apt command. The runtime font setup also depends on fontconfig and FreeType.

After identifying a package that provides the family you want, install it in the image or machine that launches wkhtmltoimage. For a Debian or Ubuntu container, the general pattern is:

# Replace <verified-package-name> with the package available for your Ubuntu release.
apt-get update
apt-get install -y <verified-package-name>
fc-cache -f -v

Check the actual family name visible to fontconfig rather than guessing from the package name:

fc-list : family | sort -u | grep -i -E 'noto.*devanagari|lohit.*devanagari'

If this produces no result, verify that the package installed successfully, that fontconfig is present, and that the command is running in the same container or runtime as wkhtmltoimage. If you build an image in stages, ensure the font files and required font configuration are present in the final stage.

3. Declare the font in HTML or a stylesheet

Set the installed family explicitly and provide fallbacks. This complete example saves a small HTML file and renders it to PNG:

cat > /tmp/hindi-sample.html <<'HTML'
<!doctype html>
<html lang="hi">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body {
      font-family: "Noto Sans Devanagari", "Lohit Devanagari", sans-serif;
      font-size: 24px;
      line-height: 1.6;
    }
  </style>
</head>
<body>
  <p>हिन्दी पाठ: नमस्ते, कृपया इस वाक्य को जाँचें।</p>
  <p>मात्राएँ, संयुक्ताक्षर और विराम चिह्न भी देखें।</p>
</body>
</html>
HTML

wkhtmltoimage --encoding utf-8 /tmp/hindi-sample.html /tmp/hindi-sample.png

The family names in CSS must match families available to the renderer. Replace or reorder the CSS candidates to match what fc-list reports. Use UTF-8 input; the --encoding option is documented by wkhtmltoimage, and the HTML declares its character encoding as well.

You can keep styles in the HTML, or supply a user stylesheet with --user-style-sheet:

wkhtmltoimage --encoding utf-8 \
  --user-style-sheet /path/to/hindi-fonts.css \
  /path/to/page.html /path/to/page.png
/* hindi-fonts.css */
html, body {
  font-family: "Noto Sans Devanagari", "Lohit Devanagari", sans-serif;
}

4. Verify glyph coverage and shaping

Do not decide from a Latin-only sample or from how the same page looks in your desktop browser. Render text representative of the page and inspect the output. Include independent vowels, consonant-vowel combinations, conjuncts, matras, punctuation, and any Hindi names or symbols your content uses.

  1. Confirm fontconfig can list the intended family in the renderer’s runtime.
  2. Render a minimal HTML sample with UTF-8 declared and an explicit CSS family.
  3. Inspect the image at full resolution for missing boxes, misplaced marks, or broken conjuncts.
  4. Compare against a known-correct rendering, such as a current browser rendering of the same sample.
  5. Repeat after changing the Ubuntu image, font package, or wkhtmltoimage binary.

Missing characters or tofu boxes usually point to font coverage or font discovery. If the individual glyphs appear but vowel marks or conjuncts are malformed, investigate shaping behavior in the exact renderer build as well. This distinction is a diagnostic guide, not a guarantee about a particular font or build.

5. Relevant wkhtmltoimage options

The font itself is selected by CSS. These options can still matter to a reproducible Hindi capture:

Option or input Use Notes
--encoding utf-8 Specify the input encoding. Also declare <meta charset="utf-8"> in the HTML.
--user-style-sheet FILE Apply font CSS without editing the source HTML. Use a family name actually available in the runtime.
CSS font-family Select the preferred font and fallback chain. There is no Hindi-only wkhtmltoimage font flag.
Input URL or HTML file Choose the page to render. For remote pages, ensure the HTML and its styles load before drawing conclusions about fonts.
Output file Choose the resulting image path and format by extension. Inspect the produced file and process exit status as part of deployment checks.

Use wkhtmltoimage --extended-help on the deployed binary to inspect the options that build supports. The official manual documents controls such as input encoding and user stylesheets, but it does not provide a Hindi font selector.

6. Troubleshooting

Symptom Likely cause What to do
Hindi characters show as empty boxes or question marks The selected font lacks glyphs, the font is not installed in the renderer runtime, or input encoding is wrong. Check fc-list in the runtime, use a Devanagari-capable family in CSS, and set UTF-8 in the HTML and command.
Text looks correct in a browser but not in the generated image The browser and wkhtmltoimage may use different fonts or rendering engines. Verify fonts inside the same environment as the binary and compare a minimal sample with the exact deployed build.
Glyphs appear, but short-i marks or conjuncts are misplaced This may be a shaping issue specific to a renderer/build and text combination. Record Ubuntu version and wkhtmltoimage --version, minimize the Hindi sample, and compare the exact output with a current browser rendering. Test another available family and build before choosing a workaround.
Font is installed but not listed by fc-list Fontconfig cache or installation visibility problem. Check the package contents and fontconfig installation, refresh the cache with fc-cache -f -v, then rerun the query in the final runtime.
CSS fallback appears to be ignored The family spelling may not match the installed family, or the stylesheet may not be applied. Inspect the rendered HTML and stylesheet path, query exact family names, and try a minimal inline-style sample.
Works on a VM but fails in a container or worker The deployed image does not include the font or its runtime configuration. Install the verified font package in the final image and run font discovery and a sample render there.
Remote page uses a web font that never appears The remote font request may not complete or be accessible to the renderer. For a controlled test, use an installed system font and CSS family. Check network access and page readiness separately from font shaping.

A wkhtmltopdf project issue filed in 2021 described a short-i shaping problem with Noto Sans Devanagari on wkhtmltopdf 0.12.6 with patched Qt on Windows 10. That report is evidence to test the exact build and string; it does not establish that every Ubuntu build has the same defect.

7. Performance, reliability, and cost considerations

For a local render, the relevant operational cost is maintaining the renderer and its dependencies in the runtime image. Installing fonts during image construction avoids per-request setup work. Keep the selected font and binary version consistent across workers so text does not change between captures.

For reliable output, treat the generated image as a deployment artifact to inspect when changing the base image, font package, fontconfig, or wkhtmltoimage build. Capture exit status and check that the output file exists and is non-empty; a successful command alone does not prove the Hindi shaping is visually correct.

Rendering a local HTML file avoids network delays while diagnosing fonts. For remote pages, page load and remote asset timing can affect capture time independently of font availability. No universal speed or cost figure applies across different Ubuntu images, page sizes, and renderer builds.

8. When wkhtmltoimage is the wrong fit

If you specifically need wkhtmltoimage, the CSS-and-runtime-font method above is the relevant path. If your goal is simply to obtain a website screenshot without managing a browser-rendering runtime, ScreenshotNeo is a website screenshot API and MCP server. Its API accepts one GET request for an image or PDF, and its parameter names are compatible with those used by other screenshot APIs.

Or skip the browser setup

Send a URL to the ScreenshotNeo API; the full API reference is in the ScreenshotNeo documentation.

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 banners are accepted like a visitor and removed before the shot, along with 60+ known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off.
  • Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Response headers identify the page verdict and whether the request was billed.
  • An MCP server gives AI agents tools for screenshots, page info, and PDF capture.
  • 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000 shots. Every feature is available on every plan.

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

FAQ

Does wkhtmltoimage have a Hindi font option?

No Hindi-specific selector is documented. Install a Devanagari font where the renderer runs and choose it in CSS.

Will Noto Sans Devanagari always fix Hindi output?

No. It is a candidate font, but glyph availability and shaping must be checked with your exact runtime and representative text.

Should I use Hindi or Devanagari in the CSS family name?

Use the actual installed font family name, such as Noto Sans Devanagari, rather than a language label.

Why does output change after a deployment rebuild?

The rebuilt image may have a different font package, font configuration, or wkhtmltoimage build. Repeat the font discovery and sample-render checks in the final runtime.

Sources