Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use Python’s pdfkit wrapper to call the separate wkhtmltopdf executable. Install both, verify that Python can find the executable, then choose from_string, from_file, or from_url for your input. The basic pattern is short; the important decisions are which wkhtmltopdf build you have, whether your HTML is trusted, and whether this legacy renderer fits your deployment.
What you need before generating a PDF
pdfkit is not the PDF renderer. It is a Python wrapper that starts wkhtmltopdf, a separate command-line program. Installing the Python package alone is insufficient: the executable must also be installed and discoverable on the system PATH, or its location must be passed explicitly.
- Install the Python package:
python -m pip install pdfkit. - Install a
wkhtmltopdfbinary built for your operating system and architecture. Use the project’s downloads page to identify the available builds. Distribution-specific system libraries, libc, fontconfig, and fonts can affect whether a binary works. - In the same environment that will run your Python application, execute
wkhtmltopdf --version. Confirm the command succeeds and note the reported version. - Run your Python code from an environment whose PATH includes that executable, or configure the binary’s full path in PDFKit.
For Linux servers and containers, check the binary inside the actual runtime image—not just on a developer machine. A successful installation on one distribution does not establish compatibility with another.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Convert an HTML string, file, or URL
PDFKit’s three basic entry points correspond directly to the input type. These examples follow the wrapper’s documented interface; they are illustrative, not reported as independently executed tests.
#1 Best Overall
Generate a PDF from an HTML string
import pdfkit
html = """
<!doctype html>
<html>
<head><meta charset="utf-8"></head>
<body><h1>Hello</h1><p>A PDF generated from HTML.</p></body>
</html>
"""
pdfkit.from_string(html, "out.pdf")
Generate a PDF from a local HTML file
import pdfkit
pdfkit.from_file("report.html", "report.pdf")
Relative images, stylesheets, and other resources referenced by the file may depend on the working directory and the renderer’s resource-access settings. If styling or images are missing, verify resource URLs and permissions as well as the HTML itself.
Generate a PDF from a web page
import pdfkit
pdfkit.from_url("https://example.com", "page.pdf")
This asks wkhtmltopdf to retrieve and render the page. It is most suitable when the rendered content is available to the older rendering stack without relying on modern browser behavior. For pages whose content appears only after substantial client-side JavaScript runs, a JavaScript-capable browser renderer may be a better fit.
Use a specific executable
If the command is not on PATH, or you need to select a particular installed binary, configure its location:
import pdfkit
config = pdfkit.configuration(wkhtmltopdf="/path/to/wkhtmltopdf")
pdfkit.from_string("<h1>Hello</h1>", "out.pdf", configuration=config)
Replace the example path with the executable’s real path for your operating system and deployment. The Python process needs permission to execute it.
Rank #2
Return PDF bytes instead of writing a file
The PDFKit README documents that omitting the output path returns the generated PDF as bytes. That lets an application pass the result to another component instead of saving it directly:
import pdfkit
pdf_bytes = pdfkit.from_string("<h1>Hello</h1>")
For large documents, account for the memory used by the returned byte string and by any downstream copy of it.
Set page size, margins, and rendering options
PDFKit forwards options to wkhtmltopdf. In its Python options dictionary, option names can be written without the leading --. A compact example using common layout controls is:
Free tools Windows power users keep installed
One-click scans. No signup required.
import pdfkit
options = {
"page-size": "Letter",
"orientation": "Portrait",
"margin-top": "12mm",
"margin-right": "12mm",
"margin-bottom": "12mm",
"margin-left": "12mm",
"encoding": "UTF-8",
}
pdfkit.from_file("report.html", "report.pdf", options=options)
Use the page size and units appropriate to the document and its intended locale. wkhtmltopdf’s settings reference covers further controls, including document title, image and JavaScript loading, print media, local-file access, headers and footers, and table-of-contents-related settings: official settings reference. The project’s documentation page and the executable’s command-line help are useful when selecting less common switches.
Some options depend on capabilities in the particular executable build. The PDFKit README warns that Debian/Ubuntu repository builds may omit patched-Qt capabilities such as outlines, headers, footers, and a table of contents. If one of these options appears to have no effect, first check which binary is being invoked and whether that build supports it; changing Python syntax cannot add a capability missing from the executable.
Debug failures and unexpected output
PDFKit runs wkhtmltopdf as a subprocess and is quiet by default. Turn on verbose output to see renderer messages:
import pdfkit
pdfkit.from_file("report.html", "report.pdf", verbose=True)
If the output or an option remains unexplained, reproduce the generated command directly with the same wkhtmltopdf executable. The wrapper README recommends this approach because it separates wrapper configuration issues from renderer and build behavior.
Common symptoms and fixes
| Symptom | Likely cause | What to check |
|---|---|---|
| Executable-not-found error | wkhtmltopdf is not installed, is absent from the running process’s PATH, or the configured path is wrong. |
Run wkhtmltopdf --version in the application environment; configure the verified absolute path if needed. |
| PDF layout or fonts differ across machines | Different binary builds, system libraries, fontconfig, or installed fonts can alter rendering. | Verify the executable version/build, platform compatibility, and required fonts in the target runtime. |
| Images or stylesheets are missing | Resources may not load from their referenced locations, or access/loading settings may prevent retrieval. | Inspect the HTML’s resource paths, network availability for remote assets, and the applicable resource-loading options. |
| Headers, footers, outlines, or table of contents are absent | The selected build may lack the patched-Qt capability the feature requires. | Identify the exact binary and consult the PDFKit README and wkhtmltopdf documentation for build-specific support. |
| Python call succeeds but content is blank or incomplete | The page may depend on scripts, remote resources, or browser behavior that the old renderer does not handle as expected. | Use verbose output, run the equivalent command directly, and check resource loading and JavaScript settings. Consider a browser-based renderer if the content requires modern JavaScript execution. |
| Error messages are hidden | PDFKit’s default quiet behavior suppresses routine renderer output. | Set verbose=True and inspect the generated command and executable’s own output. |
Do not assume a slow or incomplete render is fixed by adding arbitrary delays. First determine whether the executable can retrieve the inputs and resources, whether the build matches the platform, and whether the renderer supports the page’s behavior.
Handle HTML and renderer security carefully
The wkhtmltopdf project warns against using the tool with untrusted HTML and JavaScript: hostile content can compromise a server. This matters especially when a web service converts user-submitted markup or URLs. Sanitizing input is useful, but it should not be mistaken for a complete boundary.
- Prefer controlled templates and constrained input over arbitrary user-provided HTML or scripts.
- Run the renderer with least privilege and use operating-system isolation appropriate to the service.
- Restrict access to files, network resources, and credentials according to the application’s needs.
- Treat disabling local-file access as a risk-reduction setting, not a complete sandbox. The project’s AppArmor guidance notes that an attacker exploiting a vulnerability in a prebuilt binary may bypass that setting; AppArmor can add a further confinement layer.
Do not render sensitive internal pages or pass privileged credentials to content you do not control. An option that blocks one resource path cannot by itself make a vulnerable renderer safe for hostile input.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Know the maintenance and compatibility trade-off
wkhtmltopdf should be treated as a legacy choice rather than assumed to be a current browser engine. The project’s downloads page labels 0.12.6 as its stable series and gives its release date as June 11, 2020. Its status page is a maintainer essay with a status snapshot dated June 10, 2020; it describes Qt 4 and its WebKit as outdated and unsupported in that context, discusses QtWebKit’s retirement, and recommends considering alternatives. The Python PDFKit README also includes a deprecation warning. These dated statements describe the project’s stated status at those dates; they are not a present-day vulnerability assessment or proof of any current release status. Check the project pages and your target platform before adopting or upgrading a deployment.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →For controlled HTML reports, the project status page suggests considering WeasyPrint or commercial Prince. For sites whose output depends on dynamic JavaScript, it suggests Puppeteer or a wrapper around it. These are maintainer recommendations, not a measured performance ranking or a blanket security ranking. Check current versions, platform support, licensing, and suitability for your content before choosing.
Best Value
Or skip the browser setup
If your task is to capture a web page as a PDF rather than render a Python-generated report, ScreenshotNeo provides a screenshot API with PDF output. One GET request can return a PDF, and its API accepts options for paper size, margins, orientation, and page ranges. This avoids installing a local browser-rendering executable for that capture workflow.
Install the Python HTTP client if needed with python -m pip install requests, set your API key, and call the endpoint. See the ScreenshotNeo documentation for the API and response details.
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.pdf", "wb").write(r.content)
ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each of those steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. An MCP server offers take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. This is a page-capture option, not a substitute for converting arbitrary local HTML strings or files.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Sign up free for 1,000 screenshots a month with no card.
Frequently asked questions
Can I install PDFKit and use it without wkhtmltopdf?
No. PDFKit is a wrapper; the separate wkhtmltopdf executable must be installed and reachable by the Python process.
Does wkhtmltopdf run modern JavaScript like a current browser?
It uses an old Qt/WebKit rendering stack, so pages that depend on dynamic browser behavior may be a poor fit. The project status page points readers toward Puppeteer or a wrapper around it for JavaScript-dependent sites.
Can I safely convert HTML submitted by users?
The project warns against using wkhtmltopdf with untrusted HTML and JavaScript. Input controls, least privilege, and OS-level isolation are important; a single renderer option is not a complete security boundary.