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.

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.

  1. Install the Python package: python -m pip install pdfkit.
  2. Install a wkhtmltopdf binary 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.
  3. In the same environment that will run your Python application, execute wkhtmltopdf --version. Confirm the command succeeds and note the reported version.
  4. 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.

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

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.

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:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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.

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

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.Support on Ko-Fi

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.

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

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.

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.

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

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.

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

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.