October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
PDF

How to Troubleshoot wkhtmltopdf Failures With Python pdfkit

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Most pdfkit failures are caused by one of three separate layers: the Python wrapper cannot find wkhtmltopdf, the renderer fails on the HTML or its resources, or the operating system blocks a dependency or network request. Diagnose those layers in that order. Confirm the executable from the same runtime that fails, enable verbose output, print and run the generated command directly, then investigate the exact URL, binary, platform and security policy involved.

Understand what is actually failing

Python pdfkit is a wrapper. It locates and invokes the separate wkhtmltopdf executable; installing the Python package does not install that binary. A successful import of pdfkit therefore proves very little about whether PDF generation can run.

The useful boundary is:

  • Wrapper setup: Python cannot discover the executable, options are malformed, or the output destination is wrong.
  • Renderer/input: wkhtmltopdf starts but rejects, crashes on, or cannot render the supplied URL, file or HTML string.
  • Runtime: missing shared libraries or fonts, incompatible architecture, blocked network access, or a confinement policy such as AppArmor prevents required work.

Keep the original error, full stderr, command, versions and runtime details. A generic “Command Failed” message is only a symptom.

1. Fix “No wkhtmltopdf executable found”

Check the failing runtime, not just your shell

Run these checks inside the virtual environment, web worker, container, scheduled task or service that generates the PDF:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
python -c "import shutil; print(shutil.which('wkhtmltopdf'))"
which wkhtmltopdf
wkhtmltopdf --version
python -c "import pdfkit; print(pdfkit.__file__)"

On Windows, use where wkhtmltopdf and run the executable with its full path. A shell may have a different PATH from a systemd service, WSGI worker or container. If discovery returns nothing, install a compatible wkhtmltopdf package for your operating system and architecture, or configure the real path explicitly:

import pdfkit

config = pdfkit.configuration(wkhtmltopdf='/usr/local/bin/wkhtmltopdf')
pdfkit.from_url('https://example.com', 'out.pdf', configuration=config)

Use the Windows executable path as a raw string, for example r'C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe'. Do not assume a path from a developer laptop exists in production.

2. Make wkhtmltopdf show its own error

Enable verbose output and print the command

pdfkit normally suppresses much of the renderer output. Reproduce the request with a PDFKit object and verbose=True:

import pdfkit

html = '<html><body><h1>Diagnostic PDF</h1></body></html>'
kit = pdfkit.PDFKit(html, 'string', verbose=True)
command = kit.command()
print(' '.join(command))
pdf_bytes = kit.to_pdf()
with open('diagnostic.pdf', 'wb') as output:
    output.write(pdf_bytes)

Copy the printed command and execute it unchanged in the same environment. This separates pdfkit from wkhtmltopdf: if the direct command fails, inspect its stderr and runtime; if it succeeds, compare the Python input, options, encoding and output handling.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Capture a complete failure record

  • Python and pdfkit versions.
  • The absolute wkhtmltopdf path and the output of wkhtmltopdf --version.
  • Operating-system distribution, release and CPU architecture.
  • Whether the input is a URL, local file or HTML string.
  • The exact command, full stderr and exit code.
  • Whether the copied command succeeds outside Python.

The pdfkit documentation notes that some underlying versions can crash; a wrapper-level exception does not identify the renderer fault by itself.

3. Separate input and rendering problems

Test a minimal local document

First remove network and application complexity:

from pathlib import Path
import pdfkit

Path('/tmp/minimal.html').write_text(
    '<!doctype html><html><body>OK</body></html>',
    encoding='utf-8'
)
pdfkit.from_file('/tmp/minimal.html', '/tmp/minimal.pdf', verbose=True)

If this works, the executable and basic libraries are usable. Add your real CSS, images, scripts and fonts incrementally. If it fails, focus on the binary, shared libraries, permissions and architecture before changing HTML.

Check URLs and resource access

For every missing image, stylesheet, script or remote page, record the exact URL and test it from the renderer’s environment. A browser on your workstation may have credentials, DNS, proxy settings or a network route that the service lacks. Check redirects, authentication, certificate validation, robots or firewall behavior and HTTP status codes. A reported wkhtmltopdf issue included an HTTPS request that returned HTTP 403 and then a network error; that is evidence about that particular request, not proof that SSL is always the cause. See issue #4897 for the example.

For local assets, use correct absolute paths or a documented file-access configuration, and verify that the service user can read them. For JavaScript-heavy pages, remember that wkhtmltopdf is an older Qt/WebKit renderer: scripts may require a deliberate delay, may use unsupported browser APIs, or may never finish because they expect an interactive browser.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

4. Investigate network and sandbox restrictions

AppArmor and other confinement

If the direct command reports connection failures despite a working URL, determine whether the process is confined. The official wkhtmltopdf AppArmor guidance explains that network connections can be denied when the profile lacks the required rule. Inspect audit logs and profile rules for the service, then grant the narrow connection permission it needs. Do not disable AppArmor or weaken TLS simply because the error mentions a network problem.

Proxy, DNS and outbound policy

Compare DNS resolution and HTTPS requests under the service account. Check environment variables such as HTTP_PROXY and HTTPS_PROXY, egress firewall rules, private DNS zones and certificate stores. A 403 means the server refused that request; a timeout usually indicates reachability, routing or policy; a certificate error points to trust or hostname validation. Preserve the exact stderr instead of collapsing all three into “SSL issue.”

5. Verify binary, platform and dependencies

The official downloads page lists 0.12.6 as the stable series, released June 11, 2020. That is dated project information, not a guarantee that every current distribution supports every package. Match the downloaded binary to the deployed distribution and architecture. Verify:

  • CPU architecture (for example, x86_64 versus ARM).
  • Distribution and release, including whether it uses musl or glibc.
  • Required shared libraries with your platform’s dependency checker.
  • Installed fonts and fontconfig configuration.
  • Write permission for the output directory and temporary directory.

The downloads page describes distribution-specific support and dependencies and calls out Alpine as problematic in its deployment discussion. Do not copy a binary built for another Linux family and assume it is interchangeable. A container image should install the binary and libraries in the same image, then run the version check during deployment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

6. Handle options, encoding and output correctly

Use explicit configuration and input encoding

import pdfkit

options = {
    'encoding': 'UTF-8',
    'quiet': ''
}
config = pdfkit.configuration(wkhtmltopdf='/usr/bin/wkhtmltopdf')
pdfkit.from_string(
    '<meta charset="utf-8"><h1>Résumé — 你好</h1>',
    'report.pdf',
    options=options,
    configuration=config
)

Pass option values in the form pdfkit expects and avoid mixing shell quoting into Python dictionaries. Ensure the destination directory exists and is writable. When returning bytes from to_pdf(), write binary data ('wb'), not text mode.

Reduce the failing document

Remove custom JavaScript, external fonts and third-party widgets, then add them back one at a time. A page that depends on a login session may need cookies or headers supplied explicitly; a page that depends on a client-side API may not be renderable by this engine without a server-rendered or precomputed version.

7. Choose a deployment approach deliberately

Approach What to verify Typical failure
System package Repository version, libraries, fonts, architecture Older or patched binary behaves differently
Vendor binary Distribution compatibility and shared libraries Loader or missing-library error
Container image Binary and dependencies installed together; outbound policy Works locally, fails in production network
Explicit path in pdfkit Path exists for the service user “Executable not found” despite local success

Pin the binary and image version, run a minimal PDF smoke test after deployment, and log the command and renderer version without exposing secrets.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Security boundary for HTML and JavaScript

The wkhtmltopdf 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 arbitrary HTML as code that can trigger network access and interact with the renderer’s privileges. Sanitize input, isolate the process, restrict outbound access and filesystem permissions, and never render attacker-controlled content in a highly privileged service.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Or skip the browser setup

If your actual goal is a clean image or PDF of a public web page rather than control of a local wkhtmltopdf process, ScreenshotNeo provides a single HTTP request and an MCP server for AI agents. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; bot checks, blank pages, failed loads and cache hits are not billed, with the result identified by 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)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

See the ScreenshotNeo documentation for options including full-page lazy-image capture, CSS-selector elements, device and retina settings, PDFs, custom CSS or JavaScript, waits, request blocking, headers, cookies, geolocation, caching, signed links, asynchronous webhooks and bulk capture. Its MCP tools are take_screenshot, get_page_info and capture_pdf, usable by Claude, Cursor and other MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Troubleshooting checklist

  1. Run which/where and wkhtmltopdf --version inside the failing runtime.
  2. Set pdfkit.configuration(wkhtmltopdf=...) when PATH discovery is unreliable.
  3. Enable verbose=True, print PDFKit.command() and run it directly.
  4. Test a minimal local HTML file before debugging remote assets.
  5. Inspect each resource URL, status, redirect, proxy and DNS result.
  6. Check AppArmor, container egress and service-user permissions.
  7. Match binary, libraries, fonts, distribution and architecture.
  8. Sanitize untrusted HTML and isolate the renderer.

Frequently Asked Questions

Why does pdfkit work in a terminal but fail in my web application?

The application may have a different PATH, service account, working directory, environment variables, filesystem permissions or network policy. Run discovery and the printed command from the application runtime.

What does exit code 1 prove?

Only that wkhtmltopdf reported failure. The actionable cause is in verbose stderr, the exact input and the direct command’s behavior.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should I change SSL options first?

No. Confirm the URL’s status, certificate result, proxy and confinement policy first. A documented 403 example is request-specific and does not establish a universal SSL defect.

Is wkhtmltopdf safe for user-submitted HTML?

Not by default. The project warns that unsanitized user HTML and JavaScript can lead to complete server takeover. Sanitize and isolate before rendering.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.