Fix wkhtmltopdf encoding problems by checking the entire conversion path in order: the source file, .NET string, HTML bytes, HTTP Content-Type charset, in-document declaration, wkhtmltopdf fallback settings, and finally font glyph coverage. --encoding utf-8 only supplies a converter default; it cannot repair bytes that were emitted in another encoding or a document whose declarations contradict those bytes.
What the error usually means
ASP.NET handles application strings as Unicode, but several separate encodings can still disagree. Microsoft describes this distinction directly: “Internally, the code behind ASP.NET Web pages handles all string data as Unicode.” The physical encoding of a .cshtml or other source file, the encoding used to write an HTTP response, and the encoding wkhtmltopdf uses to decode that response are different layers.
- Garbled characters such as
éusually indicate a byte/declaration mismatch. - Empty boxes or missing characters often indicate that the renderer lacks a font containing the required glyph.
- Correct direct-file output but broken MVC output points toward the response bytes, headers, or wrapper configuration.
The wkhtmltopdf documentation describes --encoding as the default input text encoding and web.defaultEncoding as the encoding to guess when content does not specify one properly. These are fallback controls, not proof that your application emitted valid UTF-8. See the libwkhtmltox settings documentation and command-line usage documentation.
1. Capture a reproducible test case first
Record the exact wkhtmltopdf version and build, server operating-system version, MVC rendering path, wrapper library and complete command or API options. The project’s support guidance asks for version, OS details and a detailed reproducer because behavior can vary between builds.
#1 Best Overall
Create a minimal HTML file containing representative failures from your application, for example Turkish ğ İ ş, Polish ł ą, accented Latin text, Cyrillic, and the affected Asian script. Include an explicit declaration:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>body { font-family: "DejaVu Sans", sans-serif; }</style>
</head>
<body>Turkish: ğ İ ş — Chinese: 中文 — emoji: ✓</body>
</html>
Convert this file directly, then convert the same content through the MVC response. If the direct file works and MVC does not, stop changing fonts and investigate the response path.
2. Verify the MVC source and .NET string
Source-file encoding
Ensure the physical view and source files are saved as UTF-8 (preferably UTF-8 without a legacy code-page conversion). A literal character can already be damaged before it reaches the controller if an editor saved the file in a different code page. Test with a runtime value as well as a literal, so you can distinguish source corruption from response corruption.
Inspect the final rendered HTML
Do not inspect only the C# string before it is written. Save or fetch the exact HTML returned by the MVC action and look at the bytes around a failing character. A browser’s page display is not sufficient evidence; browser sniffing can conceal a wrong declaration.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #2
Set response encoding deliberately
For an MVC action that returns HTML, set the response content type and charset explicitly, while keeping the view text Unicode:
public ActionResult Invoice(int id)
{
var model = repository.GetInvoice(id);
Response.ContentType = "text/html";
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.Headers["Content-Type"] = "text/html; charset=utf-8";
return View(model);
}
Use the mechanism appropriate to your MVC 4 application and wrapper; do not blindly copy Web Forms-only settings. Microsoft’s legacy guidance distinguishes responseEncoding, which controls the response buffer encoding and charset, from fileEncoding, which concerns source files such as .aspx, .asmx and .asax. See Microsoft’s ASP.NET page-encoding documentation and its globalization guidance.
3. Make the HTTP header, bytes and HTML declaration agree
For UTF-8 output, all three must describe the same thing:
- The response bytes must actually be UTF-8.
- The HTTP header should say
Content-Type: text/html; charset=utf-8. - The HTML should contain
<meta charset="utf-8">near the start of<head>(or an equivalent HTML 4 declaration).
If a proxy, wrapper or file-writing step changes one layer, wkhtmltopdf may decode the stream incorrectly. Fetch the endpoint with a raw HTTP client, record the headers, and inspect bytes rather than relying on a browser’s rendered result.
A historical report for wkhtmltopdf 0.12.5 on Debian/Linux says that adding an explicit UTF-8 meta declaration fixed a case where locale and --encoding did not. Treat that report as a reproduction clue, not a universal remedy: see issue #5006.
4. Use wkhtmltopdf encoding options as diagnostics
Command line
wkhtmltopdf --encoding utf-8 https://example.com/invoice/123 invoice.pdf
Use the option when the input has no reliable declaration. It cannot transform incorrectly encoded bytes into correct Unicode. If the document declares ISO-8859-1 while the bytes are UTF-8, changing the default may have no effect because the explicit declaration wins or because the bytes are already damaged.
Library settings
When using a wrapper around the C API, map the equivalent setting to web.defaultEncoding (usually utf-8). Confirm that the wrapper actually passes it to the page settings and that it is applied before loading the page. Log the complete settings object for a failing conversion.
URL versus local HTML
A URL conversion involves HTTP headers, redirects, authentication and network timing; a local temporary file bypasses most of those. Write the exact HTML to a UTF-8 file and run:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteRank #4
wkhtmltopdf --encoding utf-8 file:///C:/temp/test.html test.pdf
On Linux, use a correctly escaped absolute file:// URL. A difference between URL and file results narrows the fault to transport or response metadata.
5. Distinguish encoding from missing fonts
Encoding errors change characters consistently. Font failures usually leave a square, blank area or missing glyph while nearby Latin text remains correct. Check the fonts installed on the machine that runs wkhtmltopdf, not just on your development workstation. Verify the selected CSS font family resolves to an installed font and that the process account can read it.
An issue discussion records missing Chinese font coverage in one Ubuntu 14.04 environment and mentions fonts-wqy-zenhei; that is a historical, platform-specific report rather than a current universal package recommendation. See issue #3233. Install an appropriate font for your distribution, refresh its font cache when required, restart the conversion service, and retest the minimal file.
CSS and fallback stacks
body {
font-family: "Noto Sans", "DejaVu Sans", sans-serif;
}
.cjk {
font-family: "Noto Sans CJK SC", "WenQuanYi Zen Hei", sans-serif;
}
Do not diagnose every box as a charset problem. Test one known glyph from the affected script in a standalone document using the same CSS and server account.
Recommended Free Tools
Best Value
6. MVC-specific conversion checks
- Use the final absolute URL that wkhtmltopdf can reach from the server; localhost and development host names often resolve differently.
- Ensure authentication cookies, custom headers and redirects are passed by the wrapper. An error page or login page can look like a rendering failure.
- Wait until the view has produced its dynamic text before capture. If JavaScript inserts the text, configure an appropriate delay or readiness condition in the wrapper.
- Write a byte-for-byte copy of the response to disk and compare it with the HTML sent to wkhtmltopdf.
- Keep a known-good PDF generated from the minimal fixture so changes to OS images, fonts or wkhtmltopdf builds can be detected.
7. Troubleshooting by symptom
| Symptom | Likely cause | Next check |
|---|---|---|
é becomes é |
UTF-8 bytes decoded as a legacy encoding, or contradictory declaration | Inspect raw bytes, HTTP charset and meta declaration together |
| Only MVC URL fails; local file works | Response header, proxy, redirect or wrapper behavior | Capture the final response and compare headers and bytes |
| Chinese characters are boxes | Font lacks glyphs or is unavailable to the service account | Install/verify a font covering the script and retest |
--encoding utf-8 changes nothing |
Bytes are already wrong or an explicit declaration overrides the default | Correct the producer and declarations before changing defaults |
| Some pages fail after deployment | Different wkhtmltopdf build, OS fonts, locale or wrapper settings | Record versions and reproduce with the minimal fixture |
Or skip the browser setup
If your goal is a clean image or PDF of a page rather than debugging this legacy rendering pipeline, ScreenshotNeo provides a website screenshot API. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and each response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.
One request is enough:
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 options such as full-page capture, CSS selectors, device and retina settings, custom CSS/JavaScript, waiting rules, headers, cookies, geolocation, PDF layout and signed webhooks. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
FAQ
Does adding <meta charset="utf-8"> always fix wkhtmltopdf?
No. It can resolve an undeclared-document case, but it cannot repair bytes that were encoded incorrectly before conversion.
Should I change fileEncoding to UTF-8?
Only when you are addressing the physical encoding of applicable ASP.NET source files. It does not substitute for verifying the MVC response bytes and charset.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Why does a browser show the text correctly while the PDF does not?
Browsers may sniff encodings, substitute fonts or apply different fallback behavior. The PDF converter still needs consistent bytes, declarations and installed glyphs.
Frequently Asked Questions
Does adding <meta charset="utf-8"> always fix wkhtmltopdf?
No. It can resolve an undeclared-document case, but it cannot repair bytes that were encoded incorrectly before conversion.
Should I change fileEncoding to UTF-8?
Only when you are addressing the physical encoding of applicable ASP.NET source files. It does not substitute for verifying the MVC response bytes and charset.
Why does a browser show the text correctly while the PDF does not?
Browsers may sniff encodings, substitute fonts or apply different fallback behavior. The PDF converter still needs consistent bytes, declarations and installed glyphs.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsQuick 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.




