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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Install wkhtmltopdf separately, verify that the same account and process running Python can find it, then either put it on that process’s PATH or pass its absolute path to pdfkit.configuration(). The Python pdfkit package is only a wrapper; it does not contain the wkhtmltopdf executable.

What the error actually means

pdfkit sends HTML and options to an external program named wkhtmltopdf. Installing the Python package does not install that program. The message No wkhtmltopdf executable found therefore means that pdfkit could not discover an executable at the time your application started the conversion.

The failure is usually one of three things:

  • wkhtmltopdf has not been installed on the machine or image;
  • it is installed, but its directory is missing from the PATH seen by the running process; or
  • the executable is present at a non-standard location and pdfkit needs that absolute path explicitly.

The pdfkit README’s troubleshooting guidance is to put wkhtmltopdf in $PATH or set it with a custom configuration. A terminal’s PATH is not necessarily the same PATH seen by an IDE, web server, scheduled task, container, CI job or service account.

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

Fix it in the correct order

  1. Install wkhtmltopdf independently. Choose the package or installer appropriate for the operating system running your Python code.
  2. Check discovery from that environment. Run which wkhtmltopdf on Linux or macOS-like systems, and where wkhtmltopdf on Windows.
  3. Test the same account and runtime. A successful lookup in your interactive shell does not prove that a service, container or IDE can see the binary.
  4. Use an absolute path when discovery is unreliable. Pass it to pdfkit.configuration(wkhtmltopdf=...) and use that configuration in every conversion call.
  5. If discovery succeeds but conversion fails, switch to renderer diagnostics. Enable verbose output, inspect the generated command, and run that command directly.

Install wkhtmltopdf separately

The installation examples documented by pdfkit are platform-specific. Confirm that the command and package are still available for the exact operating-system release you deploy.

Platform Documented installation example What to verify afterward
Debian or Ubuntu sudo apt-get install wkhtmltopdf Run which wkhtmltopdf and note the returned path.
macOS brew install homebrew/cask/wkhtmltopdf Run which wkhtmltopdf from the account that will create PDFs.
Windows Use the wkhtmltopdf project’s binary installer guidance. Run where wkhtmltopdf in the relevant Command Prompt or PowerShell session.
Other systems Use a wkhtmltopdf binary suitable for that operating system and architecture. Confirm that the file exists, is executable, and can be launched by the application account.

Do not assume that pip install pdfkit performs any of these steps. It installs the Python wrapper only.

Check PATH from the process that runs Python

Shell checks

On Unix-like systems:

which wkhtmltopdf
wkhtmltopdf --version

On Windows:

where wkhtmltopdf
wkhtmltopdf --version

If the lookup returns nothing, either install the executable or add its directory to the PATH used by the application. If the lookup works in a terminal but pdfkit still reports the error, test from Python itself:

import os
import shutil

print("PATH:", os.environ.get("PATH"))
print("wkhtmltopdf:", shutil.which("wkhtmltopdf"))

This distinguishes a missing installation from a runtime-environment mismatch. For a service or scheduled task, configure PATH in that service’s environment rather than only in your personal shell profile. For a container, the executable and its directory must be present in the image or mounted runtime, and the process user must be able to execute it.

Free tools Windows power users keep installed

One-click scans. No signup required.

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

Give pdfkit the absolute executable path

An explicit path avoids PATH differences between shells, workers and service managers. Replace the example with the real path in your environment:

import pdfkit

config = pdfkit.configuration(wkhtmltopdf='/opt/bin/wkhtmltopdf')
pdfkit.from_string(
    '<h1>Hello</h1>',
    'out.pdf',
    configuration=config
)

On Windows, use the full path to the installed executable, for example:

import pdfkit

config = pdfkit.configuration(
    wkhtmltopdf=r'C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe'
)
pdfkit.from_url('https://example.com', 'out.pdf', configuration=config)

Keep the configuration object available wherever conversions occur. A common mistake is to create a configured object for one call and then use an unconfigured pdfkit.from_url() or from_string() elsewhere.

A reusable configuration helper

from pathlib import Path
import pdfkit

WKHTMLTOPDF = Path('/opt/bin/wkhtmltopdf')

if not WKHTMLTOPDF.is_file():
    raise FileNotFoundError(f'Not found: {WKHTMLTOPDF}')

config = pdfkit.configuration(wkhtmltopdf=str(WKHTMLTOPDF))

pdfkit.from_string(
    '<!doctype html><html><body><h1>Invoice</h1></body></html>',
    'invoice.pdf',
    configuration=config
)

The file check produces a clearer startup error than waiting for pdfkit to fail during a request. It does not replace an execution-permission check; the account running Python must be able to launch the file.

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

Why a terminal can find it while your application cannot

IDE and notebook sessions

Editors and notebook kernels may have been started before PATH was changed. Restart the IDE or kernel after installation, then run the Python shutil.which() check inside that session.

Web servers and worker processes

Service managers often start processes with a restricted environment and a different user. Set PATH or the absolute path in the service configuration, and verify it by logging the value returned by shutil.which() at application startup.

Containers and CI

Installing pdfkit on the host does not make wkhtmltopdf available inside a container or build runner. Install the executable in the image or runner, check its architecture and permissions, and run the lookup command in the same job that executes the tests or application.

Virtual environments

A Python virtual environment isolates Python packages, not system executables. You can install pdfkit in the virtual environment while wkhtmltopdf remains a separately managed system binary. The binary still has to be accessible to the process using that environment.

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.

When PATH is fixed but PDF generation still fails

An executable-discovery error and a rendering error are different failures. The pdfkit documentation recommends enabling verbose output when wkhtmltopdf is found but cannot process the input:

import pdfkit

config = pdfkit.configuration(wkhtmltopdf='/opt/bin/wkhtmltopdf')
pdfkit.from_url(
    'https://example.com',
    'out.pdf',
    configuration=config,
    verbose=True
)

If the message remains unclear, construct a pdfkit.PDFKit object and inspect the command it builds:

import pdfkit

config = pdfkit.configuration(wkhtmltopdf='/opt/bin/wkhtmltopdf')
job = pdfkit.PDFKit(
    'https://example.com',
    'url',
    configuration=config,
    verbose=True
)
print(job.command())

Run the printed wkhtmltopdf command directly in the same environment. This separates pdfkit’s argument construction from wkhtmltopdf’s own processing. A Command Failed message means the executable was reached but could not complete the conversion; some versions can also terminate with a segmentation fault.

Distribution builds and missing PDF features

Fixing executable discovery does not guarantee that every wkhtmltopdf feature is available. The pdfkit documentation warns that Debian and Ubuntu repository builds may be compiled without wkhtmltopdf’s patched-Qt modifications. It specifically identifies outlines, headers, footers and tables of contents as affected features.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Requirement What to check Practical choice
Basic HTML-to-PDF output The binary launches and can render your pages. Validate with a small representative document.
Outlines or table of contents Whether the selected build includes the required patched-Qt support. Use a static binary from the wkhtmltopdf project when the distribution build lacks it.
Headers or footers Whether those options work in the installed build, not merely in pdfkit’s Python API. Test the exact binary in deployment before relying on the feature.

The static-binary recommendation addresses build capability, not the original “executable found” message. You still need to place that binary where the runtime can execute it or pass its full path.

Troubleshooting by symptom

Symptom Likely cause Fix
No wkhtmltopdf executable found immediately The executable is missing or invisible to Python. Install it, run which/where in the application context, or pass an absolute path.
Lookup works in a shell but not in production Different PATH, user, container or service environment. Log os.environ['PATH'] and shutil.which() from the production process; configure that runtime.
Explicit path still fails Typo, wrong architecture, missing execute permission or inaccessible parent directory. Check the file path as the application user and launch wkhtmltopdf --version directly.
Command Failed after discovery succeeds wkhtmltopdf reached the input but could not render it. Use verbose=True, inspect PDFKit.command(), and run the command directly.
Outlines, headers, footers or TOC do not work Distribution build lacks patched-Qt modifications. Use a compatible static binary and retest the option.
Works once, then fails in a worker Some code paths use a different or unconfigured pdfkit call. Create one configuration object and pass it to every conversion path.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Reliability and maintenance considerations

Make executable validation part of deployment rather than discovering the problem on the first customer request. A startup check should report the resolved path, the effective user and the result of invoking wkhtmltopdf --version. A smoke test that converts a tiny HTML document catches missing libraries, permissions and incompatible binaries earlier than a full production job.

Keep the binary path configurable through deployment settings instead of hard-coding a machine-specific location into source code. Pin and test the exact build used in production, especially when your documents depend on patched-Qt features.

The pdfkit project carries a deprecation warning aligned with wkhtmltopdf’s project status. The wkhtmltopdf GitHub repository was archived on January 2, 2023. That does not prevent an existing deployment from working, but it is relevant when deciding whether to build new long-lived systems around this stack. The available version-history metadata lists pdfkit 1.0.0 as released on November 14, 2021; that date is release metadata, not a guarantee of current platform compatibility.

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

Or skip the browser setup

If your actual requirement is a hosted screenshot or PDF of a URL rather than local control of wkhtmltopdf, ScreenshotNeo provides an HTTP API and an MCP server. It is not a fix for a broken pdfkit installation, but it removes the need to install and operate a browser-rendering executable yourself.

One GET request returns a PNG, JPEG, WebP or PDF. Before capture, ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, 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. An MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.

See the ScreenshotNeo API documentation for authentication and options. The following calls use the documented endpoint:

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()));

ScreenshotNeo includes full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF paper and margin controls, custom CSS and JavaScript, clicks before capture, selector hiding, waits for selectors, delays or network idle, request and resource blocking, custom headers, cookies, user agents and authorization, timezone and geolocation, transparent backgrounds, resizing, configurable caching, signed links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API and an OpenAPI specification. Parameter names used by other screenshot APIs also work for easier migration.

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

Every feature is included on every plan: 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.

Final deployment checklist

  • wkhtmltopdf is installed separately from the pdfkit Python package.
  • The executable resolves with which, where or shutil.which() inside the actual runtime.
  • The application user can execute the file and access its parent directories.
  • Every pdfkit conversion receives the same explicit configuration when PATH cannot be guaranteed.
  • Your selected build supports required outlines, headers, footers and TOC features.
  • Verbose output and the generated command have been captured for any post-discovery rendering failure.
  • A small conversion smoke test runs during deployment.

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.