The error usually means Django cannot launch the separate wkhtmltopdf executable—not that your Python code is necessarily wrong. Install a distribution-compatible binary inside the same server, container, or function that runs Django, verify it as the service user, and point django-wkhtmltopdf at its real absolute path with WKHTMLTOPDF_CMD. If the message names a shared library such as libfontconfig.so.1, the executable was found but its runtime dependencies are incomplete.
What the error means
django-wkhtmltopdf is a Python wrapper. It does not include the wkhtmltopdf program, so installing the wrapper from PyPI is not enough. The wrapper searches for a command named wkhtmltopdf on the process PATH unless you configure another location. See the wrapper documentation for the binary requirement and settings.
“No such file or directory” can describe two different failures:
- Executable lookup failure: the path Django tries does not exist in the application runtime.
- Loader or dependency failure: the executable exists, but the operating system cannot start it because an interpreter or shared library is missing. An error naming
libfontconfig.so.1is an example of the second case (wkhtmltopdf issue example).
Diagnose those cases separately before changing Django code.
#1 Best Overall
Diagnose from the environment that runs Django
-
Enter the actual runtime
Check the machine, virtual machine, container image, or serverless runtime that launches the Django process. A binary installed on your laptop or on a Docker host is invisible to a container unless it is installed or mounted inside that container.
-
Resolve the command
Run these commands as the same user and in the same environment as the web worker or job:
command -v wkhtmltopdf which wkhtmltopdf wkhtmltopdf --versionIf neither lookup command returns a path, the executable is absent from
PATH. Python also recommends resolving an unqualified command withshutil.which(), and using a fully qualified path when reliable launching matters (Python subprocess documentation):python -c "import shutil; print(shutil.which('wkhtmltopdf'))" -
Test the exact path
When a path is returned, run it directly:
/absolute/path/to/wkhtmltopdf --version /absolute/path/to/wkhtmltopdf --helpA successful version or help response proves that this user can start the binary. A permission error points to file ownership or mode; a missing
.soname points to runtime compatibility.Crashes, 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 minutePC 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 & 11Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy. -
Inspect what Django actually sees
Web servers often have a smaller
PATHthan an interactive shell. Temporarily logos.environ.get("PATH")and the configured command from the running service, or execute a one-off management command under that service account. Do not assume your login shell configuration is inherited by Gunicorn, uWSGI, Celery, systemd, or a container entrypoint.
Configure django-wkhtmltopdf with the real executable
Set an absolute path discovered inside the application runtime:
# settings.py
WKHTMLTOPDF_CMD = '/usr/local/bin/wkhtmltopdf'
Replace the illustrative value with the path printed by command -v or shutil.which(). The wrapper also permits an environment variable named WKHTMLTOPDF_CMD; use whichever configuration method your deployment standardizes. An absolute path avoids dependence on a service-specific PATH. Restart the Django workers after changing settings or environment variables.
WKHTMLTOPDF_CMD_OPTIONS can define default command-line options, but options cannot create a missing executable or supply missing system libraries. Keep executable configuration and rendering options as separate troubleshooting concerns.
Free tools Windows power users keep installed
One-click scans. No signup required.
Install a compatible wkhtmltopdf package
Obtain the package from the official downloads page or your operating-system repository, matching all of these properties:
- Operating-system and distribution release
- CPU architecture
- libc implementation (for example, glibc versus musl)
- Libraries and fonts available in the image or server
The downloads page lists the 0.12.6 stable series and dates that release June 11, 2020. Treat that as the page’s listed series and package matrix, not as evidence of a recent release; recheck the page for current package availability.
Linux distribution and library checks
The project’s FAQ explains that builds statically link Qt but still require system packages and font-related configuration (official FAQ and downloads). Therefore a file can exist and still fail at process startup. If the error names a library, use your distribution’s package manager to install the corresponding compatible runtime package, then rerun wkhtmltopdf --version as the Django user.
Do not treat a generic Linux download as universally portable. The FAQ specifically notes that earlier generic Linux builds did not work on Alpine because Alpine uses musl rather than glibc. On Alpine, prefer an Alpine-compatible build or change to a supported glibc-based image rather than copying an arbitrary binary.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Containers
Install both the executable and its runtime libraries in the image that executes Django. A typical verification sequence in a running container is:
docker exec -it your-container sh
command -v wkhtmltopdf
wkhtmltopdf --version
python -c "import shutil; print(shutil.which('wkhtmltopdf'))"
Build the image from a package appropriate to its distribution and architecture, then run the same checks in CI. Ensure the service account has execute permission on the file and traverse permission on every parent directory. If you use a multi-stage build, copy required shared libraries and font configuration along with the executable, not only the one file.
AWS Lambda and other serverless runtimes
The official FAQ describes bundling a distribution-specific package, libraries, and fonts for Lambda. Its example tests the extracted bundle in an Amazon Linux 2 container with LD_LIBRARY_PATH and FONTCONFIG_PATH. Adapt those paths to the runtime version selected for your function and test the bundle there; a package built for another distribution may not load.
Separate path errors from dependency errors
When the executable is missing
shutil.which('wkhtmltopdf')returnsNone.command -vprints nothing.- The wrapper reports that the command cannot be found.
Install the binary in the runtime or set WKHTMLTOPDF_CMD to an existing absolute path.
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 →When a loader or library is missing
- The configured file exists and has execute permission.
- Running it directly reports a named
.so, interpreter, or loader problem. - The failure may appear to Django as “No such file or directory” even though the file itself is present.
Install the matching library package, fonts, and font configuration, or replace the binary with one built for the target OS and architecture. The wrapper documentation calls out libfontconfig as a requirement; the issue tracker shows how a missing libfontconfig.so.1 surfaces in practice.
Common fixes that do not work
- Installing only the Python package: the wrapper and executable are separate components.
- Using a guessed path:
/usr/bin,/usr/local/bin, and virtual-environment directories differ by image and installation method. Use the path resolved in the running environment. - Installing on the host: containers and isolated functions need their own binary and libraries.
- Changing command-line options: options affect rendering, not executable discovery or dynamic linking.
- Assuming “static” means dependency-free: Qt may be static while font and other system requirements remain.
- Copying a generic binary to Alpine: musl/glibc incompatibility can prevent startup.
Make the deployment reliable
Check at startup or in health checks
Fail early with a diagnostic that reports the configured path and version, rather than discovering the problem during a customer PDF request:
import os
import shutil
import subprocess
cmd = os.environ.get("WKHTMLTOPDF_CMD", "wkhtmltopdf")
resolved = cmd if os.path.isabs(cmd) else shutil.which(cmd)
if not resolved:
raise RuntimeError(f"wkhtmltopdf not found: {cmd!r}")
subprocess.run([resolved, "--version"], check=True, text=True)
Run this check in the same image, account, and process supervisor used for production. Keep the version output in deployment logs so an image change that replaces the binary is visible.
Compare deployment options
| Deployment | What must match | Extra checks |
|---|---|---|
| Traditional VM or bare metal | OS release, architecture, libraries, fonts | Service-user PATH and permissions |
| Docker or another container | Image distribution, libc, architecture, bundled files | Verify inside the running container, not the host |
| Alpine-based image | musl-compatible package or a different base image | Do not assume generic Linux builds load |
| AWS Lambda | Function runtime and Amazon Linux-compatible bundle | LD_LIBRARY_PATH, FONTCONFIG_PATH, libraries, and fonts |
Or skip the browser setup
If your requirement is a clean web-page capture rather than a server-side HTML-to-PDF workflow, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF, without installing Chromium or wkhtmltopdf in your Django runtime.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Best Value
Using 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}`);
Read the parameter reference at ScreenshotNeo documentation. Before capture it accepts consent banners 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, with the result identified by X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
FAQ
Does installing wkhtmltopdf inside a virtualenv fix the error?
Only if the executable is actually installed there and the Django process can execute it. A Python virtual environment does not automatically contain operating-system binaries.
Why does the path work in my shell but not under Gunicorn?
Gunicorn or its service manager may receive a different PATH. Configure an absolute WKHTMLTOPDF_CMD path and verify it as the service user.
Is wkhtmltopdf still actively maintained?
The upstream GitHub repository is archived and read-only as of January 2, 2023 (repository). That status is a maintenance consideration, not the immediate explanation for a missing executable or library.
Recommended Free Tools
Frequently Asked Questions
Can I use a relative value for WKHTMLTOPDF_CMD?
Use an absolute path whenever possible. Relative paths depend on the worker’s current directory and can change between supervisors, containers, and jobs.
What should I collect before asking for deployment help?
Record the runtime image or OS, CPU architecture, output of shutil.which(), the exact configured command, wkhtmltopdf –version output, the service user, and the complete loader error including any named library.
The Bottom Line
Locate and test wkhtmltopdf inside the same runtime and user context as Django, configure that verified absolute path, and then resolve any separately reported library or font dependency. Distribution and libc compatibility matter as much as the file path.
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.




