Short answer: wkhtmltopdf is not a current Chrome or Firefox browser. It renders with an old Qt WebKit engine, and the exact binary, operating-system libraries, fonts, network access and JavaScript timing all change the result. A simple, mostly static page may convert perfectly while a modern, app-like site shows missing content, broken layout or a blank PDF.
Diagnose the executable and environment before rewriting the page or changing tools. If the page depends on web features that this engine cannot implement, no delay flag will make it behave like a modern browser; use a maintained browser renderer instead.
| # | Preview | Product | Price | |
|---|---|---|---|---|
| 1 |
|
99 Formatting Tips for Self-Published Authors: How to Self-Publish a Better Book Using Various Tips... | $5.95 | Buy on Amazon |
What wkhtmltopdf actually renders
The project describes wkhtmltopdf as an open-source, headless command-line tool that renders HTML into PDF (and wkhtmltoimage into image formats) using Qt WebKit. That is materially different from launching a current Chromium or Firefox build.
The project status page says Qt 4, which wkhtmltopdf uses, has been unsupported since 2015 and that its embedded WebKit has not been updated since 2012. Modern sites can therefore rely on CSS, JavaScript and browser APIs that this renderer does not understand or handles differently.
#1 Best Overall
The version number alone is not enough. The project documents that distribution packages may be compiled without wkhtmltopdf’s patched Qt. Two executables both called wkhtmltopdf can consequently differ in capabilities, defaults and dependencies.
Why one site succeeds and another fails
Static markup versus application rendering
A server-rendered article with ordinary CSS, local images and system fonts gives wkhtmltopdf content immediately. A single-page application may initially return an empty shell, then fetch data, construct the DOM and measure the viewport in JavaScript. If the converter captures before those steps finish, the PDF is incomplete.
Newer CSS and layout assumptions
Grid, newer flexbox behavior, sticky positioning, advanced selectors, variable fonts and other current web-platform features may be unsupported or implemented differently. A page can remain readable while columns, spacing, fixed elements or page breaks diverge from a browser screenshot.
Assets that cannot be loaded
CSS, images, scripts and fonts must be reachable from the conversion process. Relative paths can break when the working directory changes; private URLs may require headers or cookies; a container may have no outbound network route; TLS or certificate differences can reject a request. Missing fonts often masquerade as a layout bug because changed metrics alter wrapping and pagination.
Free tools Windows power users keep installed
One-click scans. No signup required.
Screen and print media differ
Websites commonly provide a print stylesheet that hides navigation, changes colors or rearranges content. wkhtmltopdf can select screen or print media, so an apparently “wrong” result may be the intended print rules rather than a failed render.
Build and runtime differences
The official FAQ calls out Linux libraries, libc, OpenSSL, fontconfig, FreeType and installed fonts as sources of variation. A binary that works on one distribution can fail, render differently or refuse to start on another. Record the package origin, operating-system release and runtime libraries when comparing machines.
First diagnostic: identify the exact converter
- Run
wkhtmltopdf --versionand save the complete output. Note the release and whether it sayswith patched qt. - Locate the executable with your operating system’s package tools and record whether it came from a distribution repository, an official package or a custom build.
- Record the operating system and release, container base image, CPU architecture and relevant library versions.
- Run the same command against a local, static test document. If that works but the remote page fails, investigate requests, timing and authentication before blaming pagination.
The downloads page labels 0.12.6 as a stable series released June 11, 2020. Treat that as a dated project statement, not proof that every installed package is identical or current.
A reproducible troubleshooting workflow
1. Preserve the failing case
Save the exact URL, command line, generated file, stderr output and a browser copy of the page. Reduce the page to a minimal HTML/CSS/JavaScript example if possible. The project’s support guidance asks for the version, operating system and a reproducing example; include patched-Qt information, fonts and external resource details as well.
2. Check requests and paths
Confirm that every stylesheet, image, script and font returns successfully from the converter’s network context. Test with a self-contained local copy where practical. Check URL encoding, redirects, authentication, cookies, proxy settings and certificate trust. If a resource is intentionally private, supply the required request metadata rather than assuming a browser session is shared.
3. Make timing explicit
The manual documents JavaScript controls including --javascript-delay, --run-script and --window-status. Use a delay when content appears after a known asynchronous operation; use a status signal when your page can set a predictable completion marker. These options solve capture timing, not missing browser features. An indefinitely waiting page still needs a timeout policy in your wrapper.
4. Choose media deliberately
Test screen and print media intentionally. A print stylesheet may hide elements you expected to see, while screen rules may preserve navigation that wastes pages. Keep the selected mode in the reproducible command so results are comparable.
5. Compare fonts and dimensions
Install the same font files in every environment, refresh fontconfig caches when required by the operating system and set an explicit page size, margins and viewport. Compare a text-only output and a version with external assets to isolate font metrics from network failures.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →6. Decide whether to contain or replace it
If the input is a controlled report template, pinning a known-good binary, fonts and container can be a reasonable containment strategy. If it is arbitrary third-party HTML or a JavaScript-heavy application, migrate to an actively maintained browser renderer. The project status page suggests Puppeteer for dynamic-JavaScript sites and names WeasyPrint or commercial Prince for controlled reports. Evaluate browser fidelity, migration effort, binary and dependency size, concurrency, serverless limits, security maintenance and licensing for your workload.
Command patterns that make failures easier to explain
Keep a baseline command simple, then add one change at a time:
wkhtmltopdf --print-media-type --javascript-delay 2000 https://example.com output.pdf
For a page that signals completion from its own script, use a window-status value agreed with the page:
wkhtmltopdf --window-status ready https://example.com output.pdf
Do not treat either command as a universal fix. Verify that the page actually sets the status and that the delayed content is reachable in the converter process.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Common symptoms, causes and fixes
| Symptom | Likely cause | Useful next action |
|---|---|---|
| Blank or nearly blank PDF | JavaScript shell captured before data arrived; blocked scripts; incompatible feature | Inspect requests, add a bounded delay or status wait, then test a modern renderer |
| Text appears but images do not | Bad relative paths, authentication, certificate or network restrictions | Test each image URL from the same host/container and provide required access |
| Layout changes between servers | Different patched-Qt build, fonts, libraries or viewport | Compare version output, package source, fonts, libraries and dimensions |
| Content is missing only in PDF | Print stylesheet or print-media behavior | Compare explicit screen and print media runs |
| Timeouts or hangs | Never-ending JavaScript, unreachable resource or status condition never met | Set an outer timeout, inspect logs and remove the wait condition incrementally |
| Converter crashes on supplied HTML | Engine bug, resource pressure or hostile input | Reduce the case, cap resources and isolate the worker |
Security is part of the rendering decision
The project warns: “Do not use wkhtmltopdf with any untrusted HTML – be sure to sanitize any user-supplied HTML/JS, otherwise it can lead to complete takeover of the server it is running on!” Treat conversion as a security boundary. Sanitize input, run workers with least privilege, isolate them from sensitive networks and files, apply CPU, memory and time limits, and avoid exposing a converter endpoint directly to untrusted callers.
When replacing wkhtmltopdf is the sensible answer
- Keep it for stable, controlled templates whose output is already accepted and whose environment can be pinned.
- Contain and document it when migration is expensive but inputs can be sanitized and isolated.
- Replace it when current JavaScript, modern CSS, browser-level fidelity, third-party pages or long-term security maintenance are requirements.
Migration is not just a binary swap. Recheck headers, cookies, authentication, page-break rules, footers, print CSS, fonts, concurrency and licensing. Build visual regression cases from your real documents rather than relying on a single successful home page.
Or skip the browser setup
For a website screenshot rather than a locally managed PDF renderer, ScreenshotNeo provides a single HTTP request. It accepts cookie and consent banners as a visitor, then removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers.
cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
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)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo documentation for parameters. It also offers an MCP server with take_screenshot, get_page_info and capture_pdf, so Claude, Cursor and other MCP clients can request captures. Plans include 1,000 screenshots monthly free with no card; paid plans start at $5 for 3,000. Sign up free for ScreenshotNeo.
Frequently Asked Questions
Does adding a longer JavaScript delay make wkhtmltopdf support modern web apps?
No. A delay only gives supported scripts more time to run; it cannot add missing CSS, JavaScript or browser APIs.
Why does the same command differ across Linux servers?
The executable may have different Qt patches, libraries, OpenSSL behavior, font configuration or installed fonts. Compare the complete version output and runtime environment.
Should I use screen or print media?
Use the mode that matches the intended output and test both when diagnosing missing or rearranged elements; websites can define substantially different print CSS.
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.
Recommended Free Tools




