The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Install fonts-urw-base35. On Debian, it is the package that provides the URW Base 35 font set. Debian’s Bookworm package record lists gsfonts as a transitional dummy package that points to it, and current Debian records also list the package in Trixie.
If characters are still missing in a wkhtmltopdf PDF, installing the package is only one part of the fix. UTF-8 controls how text is decoded; it does not give a font glyphs that the font does not contain. You must also verify CSS font selection, character coverage, and the Fontconfig/FreeType environment visible to the wkhtmltopdf process.
| # | Preview | Product | Price | |
|---|---|---|---|---|
| 1 |
|
Unicode & Character Encoding Guide: Make your software work worldwide by understanding text encoding... | $18.99 | Buy on Amazon |
Install the Debian package that replaces urw-fonts
For the URW/PostScript Base 35 families, run:
sudo apt update
sudo apt install fonts-urw-base35
fc-cache -f -v
The package is named fonts-urw-base35, version 20200910-7 in the Debian Bookworm record. Its description calls it a font set “metric-compatible with the 35 PostScript Level 2 Base Fonts.” It supplies Type 1 outlines and AFM metrics for families including C059, D050000L, Nimbus Mono PS, Nimbus Roman, Nimbus Sans, Nimbus Sans Narrow, P052, Standard Symbols PS, URW Bookman, URW Gothic and Z003. Debian identifies gsfonts as a transitional package pointing to this package.
This is the correct answer when “urw-fonts” means the URW Base 35 set. It is not an all-Unicode font bundle. The package description does not promise glyphs for every script, symbol or punctuation mark.
#1 Best Overall
Verify that Debian installed the files
dpkg -s fonts-urw-base35
fc-list | grep -Ei 'Nimbus|URW|C059|P052|Z003'
dpkg -s should show the package as installed. fc-list checks what Fontconfig can currently see, rather than merely confirming that files exist on disk.
UTF-8 encoding and font glyphs are separate problems
UTF-8 is an encoding. It tells wkhtmltopdf how to interpret bytes as characters; it does not add missing outlines to a selected font. Qt’s font documentation notes that although modern fonts use Unicode encoding, most fonts do not contain every Unicode character.
Declare UTF-8 in the document
Put the declaration early in the document’s <head>:
<meta charset="utf-8">
If the HTML is served over HTTP, send an appropriate content type such as text/html; charset=utf-8. When invoking wkhtmltopdf through a library, its web.defaultEncoding setting is the fallback used when the page does not identify its encoding correctly. Set it to UTF-8 when your input is UTF-8, but do not treat that setting as a font-coverage solution.
Check the font actually selected by CSS
Use an explicit, installed family and a fallback list:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
body {
font-family: "Nimbus Sans", "DejaVu Sans", sans-serif;
}
The family name must resolve in the same host, container or packaged runtime that launches wkhtmltopdf. A font installed on your workstation is irrelevant if production runs in a minimal container without that font or without a usable Fontconfig cache.
Test the exact characters
Create a small HTML fixture containing the problem text: accented Latin, em dashes, currency symbols, CJK, Arabic, Cyrillic or other scripts used by the real document. Render that fixture in the production image or host. This distinguishes decoding errors from absent glyphs and from runtime font visibility.
A reliable diagnostic sequence
- Confirm the bytes and metadata. Check that the source file is saved as UTF-8 and includes
<meta charset="utf-8">, or that the HTTP response declares UTF-8. - Install and refresh fonts. Install
fonts-urw-base35, then runfc-cache -f -v. - Inspect Fontconfig. Run
fc-listinside the exact runtime that executes wkhtmltopdf. Do not inspect only the development host. - Confirm family resolution. Compare the CSS family name with the names reported by
fc-list. Include a fallback family where appropriate. - Check coverage. Determine whether the selected font contains every required character. UTF-8 cannot compensate for a missing glyph.
- Render a minimal sample. Use the same wkhtmltopdf binary, user, container and environment variables as production, then compare the PDF output.
Why wkhtmltopdf can behave differently in production
wkhtmltopdf renders HTML with Qt WebKit and relies on runtime Fontconfig and FreeType. The project’s download documentation warns that even static builds depend on the runtime font configuration and shows setting FONTCONFIG_PATH for a packaged runtime.
For a container or bundled deployment, make sure the font packages and Fontconfig configuration are inside that image or layer. If you maintain a private font directory, expose it through Fontconfig and rebuild the cache. A host-level installation does not automatically appear inside Docker, a serverless layer or another isolated process.
Check the runtime environment
which wkhtmltopdf
wkhtmltopdf --version
fc-match "Nimbus Sans"
echo "$FONTCONFIG_PATH"
fc-cache -v
fc-match reports the font Fontconfig would select for a family. An unexpected fallback is evidence that the requested family is unavailable or that the runtime configuration is incomplete.
When another Debian font package is a better fit
Choose by design, metrics, format and character repertoire—not by the word “UTF-8” in the requirement.
| Package or family | Use case | Important qualification |
|---|---|---|
fonts-urw-base35 |
URW/PostScript Base 35 compatibility | Metric-compatible Type 1 outlines and AFM metrics; no promise of complete Unicode coverage. |
fonts-texgyre |
OpenType remakes in the GUST TeX Gyre collection | Based on URW fonts, but a different font format and design choice. |
fonts-freefont-otf or fonts-freefont-ttf |
Broader script needs, including Cyrillic coverage formerly associated with the obsolete urwcyr fork |
Verify the exact characters required by your document. |
| Debian Liberation packages | Metrics matching familiar Times, Arial and Courier layouts | Use when document geometry depends on those metric-compatible families rather than URW styling. |
No single package is established as best for every language. Compare the actual scripts, punctuation and symbols in your PDFs, and test those characters in the target runtime.
Troubleshooting missing or substituted characters
Boxes, question marks or blank spaces
- Likely cause: the selected font lacks the glyph.
- Fix: choose a family with the needed repertoire, add a CSS fallback, and test the exact text sample.
Accented text is corrupted
- Likely cause: the HTML bytes are not being decoded as UTF-8.
- Fix: save the file as UTF-8, add the meta declaration, send the correct response charset, and set wkhtmltopdf’s
web.defaultEncodingfallback where your integration exposes it.
The package is installed but wkhtmltopdf still substitutes fonts
- Likely cause: wkhtmltopdf runs in a different container, user environment or Fontconfig path.
- Fix: run
fc-listandfc-matchfrom that process environment, refresh the cache there, and configureFONTCONFIG_PATHif the packaged runtime requires it.
It works locally but fails in a container
- Likely cause: the image does not contain the font package or Fontconfig cache.
- Fix: install the package in the image, rebuild caches during image creation, and render a fixture as part of deployment verification.
Only one script fails
- Likely cause: URW Base 35 covers the PostScript families but not that script.
- Fix: select a font package that supports the script, retain a suitable fallback, and verify every character used.
wkhtmltopdf version and maintenance context
The wkhtmltopdf project describes version 0.12.6 as its stable series and dates that release June 11, 2020. Its download page lists Debian 9, 10 and 11 builds; those entries are historical project-page information, not a guarantee of compatibility with every current Debian release. The project status page also notes that the Qt 4 base has been unsupported since 2015 and its WebKit was not updated after 2012. For a new or security-sensitive deployment, assess that maintenance context separately from the font fix.
Or skip the browser setup
If your goal is a clean image or PDF of a web page rather than a local wkhtmltopdf pipeline, ScreenshotNeo provides a website screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each step can be disabled. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result.
One GET request returns PNG, JPEG, WebP or PDF. The API supports full-page captures with lazy images, CSS-selector element captures, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching, signed image links, asynchronous webhooks and bulk capture of up to 100 URLs. An MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.
See the ScreenshotNeo documentation for authentication and 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}`);
The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan. Create a free ScreenshotNeo account.
Recommended Free Tools
Frequently Asked Questions
Which package replaces gsfonts on Debian?
Install fonts-urw-base35; Debian lists gsfonts as a transitional dummy package pointing to it.
Does installing URW Base 35 make every UTF-8 character render?
No. UTF-8 fixes decoding, while glyph availability depends on the selected font and its coverage.
Why does wkhtmltopdf see a font on one machine but not another?
Its Qt WebKit process uses the runtime’s Fontconfig and FreeType setup, which can differ between a host, container or packaged executable.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




