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.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Fix it in the correct order
- Install wkhtmltopdf independently. Choose the package or installer appropriate for the operating system running your Python code.
- Check discovery from that environment. Run
which wkhtmltopdfon Linux or macOS-like systems, andwhere wkhtmltopdfon Windows. - 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.
- Use an absolute path when discovery is unreliable. Pass it to
pdfkit.configuration(wkhtmltopdf=...)and use that configuration in every conversion call. - 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.
#1 Best Overall
| 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.
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.
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.
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.
| 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. |
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.
Rank #4
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.
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.
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.
Quick Recap
Final deployment checklist
- wkhtmltopdf is installed separately from the pdfkit Python package.
- The executable resolves with
which,whereorshutil.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.

