---
title: "HTML to PDF in Python: Convert HTML using wkhtmltopdf and pdfkit"
canonical_url: "https://www.nutrient.io/blog/how-to-convert-html-to-pdf-using-wkhtmltopdf-and-python/"
md_url: "https://www.nutrient.io/blog/how-to-convert-html-to-pdf-using-wkhtmltopdf-and-python.md"
last_updated: "2026-06-15T08:43:43.843Z"
description: "Learn how to convert HTML to PDF in Python using wkhtmltopdf and pdfkit. Covers URLs, HTML strings, and files, and when a cloud API is a better fit."
---

**TL;DR**

Install `pdfkit` and the `wkhtmltopdf` binary. Then convert HTML to PDF in three lines:

```python

import pdfkit

pdfkit.from_url('https://example.com', 'out.pdf')   # from a URL

pdfkit.from_file('index.html', 'out.pdf')           # from a file

pdfkit.from_string('<h1>Hello</h1>', 'out.pdf')     # from a string

```

If you’re looking for a way to convert HTML to PDF using Python, this post will show you how to do it efficiently using [`wkhtmltopdf`](https://wkhtmltopdf.org/).

**wkhtmltopdf was [archived on 2 January 2023](https://github.com/wkhtmltopdf/wkhtmltopdf/issues/5160)** and is now read-only. The library still works, but receives no security patches, browser-engine updates, or bug fixes. For new projects, consider maintained alternatives — [WeasyPrint](https://weasyprint.org/) (BSD, pure Python), [Puppeteer](https://pptr.dev/) or [Playwright](https://playwright.dev/) (Node.js, Chromium-based), or [Nutrient’s HTML-to-PDF API](https://www.nutrient.io/api/html-to-pdf-api/) for a managed cloud option. This guide remains for teams maintaining existing wkhtmltopdf integrations.

If you’re looking for a way to convert HTML to PDF using Python, this post will show you how to do it using [`wkhtmltopdf`](https://wkhtmltopdf.org/) and [python-pdfkit](https://github.com/JazzCore/python-pdfkit) — a Python wrapper around the `wkhtmltopdf` binary. Common use cases include generating invoices, shipping labels, resumes, and reports.

## How to pick a Python HTML-to-PDF library

| Library                                         | Best for                                       | Active?                           | License    |
| ----------------------------------------------- | ---------------------------------------------- | --------------------------------- | ---------- |
| **wkhtmltopdf + python-pdfkit**                 | Simple static HTML, invoices, reports          | ⚠️ Deprecated (last release 2022) | LGPL / MIT |
| **WeasyPrint**                                  | Print-quality typography, paged media CSS      | ✅ Active                          | BSD-3      |
| **Playwright/Pyppeteer**                        | Modern JavaScript-heavy pages, dynamic content | ✅ Active                          | Apache-2.0 |
| **Nutrient [HTML-to-PDF API](https://www.nutrient.io/api/html-to-pdf-api/)** | Production apps, no binary install, scale      | ✅ Active                          | Commercial |

This tutorial covers the wkhtmltopdf + pdfkit path. If your HTML uses modern CSS or JavaScript-rendered content, consider WeasyPrint or Playwright instead.

**Note:** Both wkhtmltopdf and python-pdfkit are now deprecated. They still work for simple cases, but new projects should consider an actively maintained alternative — see the table above.

## Installing wkhtmltopdf

Before you can use wkhtmltopdf, you need to install it on your operating system.

### On macOS

Install with Homebrew (the cask still installs the final 0.12.6 build):

```bash

brew install --cask wkhtmltopdf

```

### On Debian/Ubuntu

The version in the default APT repositories is built without the wkhtmltopdf Qt patches, so outlines, headers, footers, and TOC support are disabled. For full functionality, download the latest `.deb` from the [wkhtmltopdf releases page](https://wkhtmltopdf.org/downloads.html):

```bash

sudo dpkg -i wkhtmltox_*.deb
sudo apt-get install -f

```

### On Windows

Download the latest installer from the [wkhtmltopdf website](https://wkhtmltopdf.org/downloads.html). Then add the wkhtmltopdf binary to your `PATH` environment variable.

## Installing python-pdfkit

Install python-pdfkit using pip:

```bash

pip install pdfkit

# or

pip3 install pdfkit # for Python 3

```

python-pdfkit provides [several APIs](https://github.com/JazzCore/python-pdfkit/blob/master/pdfkit/api.py) to create a PDF document:

- From a URL using `from_url`

- From a string using `from_string`

- From a file using `from_file`

## Creating a PDF from a URL

The `from_url` method takes two arguments: the URL and the output path. The following code snippet shows how to convert the Google home page to PDF using pdfkit:

```python

import pdfkit

pdfkit.from_url('https://google.com', 'example.pdf')

```

### Running the code

This section outlines two options for running the code.

#### Option 1: Direct execution

1. Save the code snippet in a file named `url.py`.

2. Run the script:

```bash

python url.py

```

If you’re using Python 3 and the default Python command points to Python 2, use:

```bash

python3 url.py

```

#### Option 2: Using a virtual environment

1. Create a virtual environment:

   ```bash

   python3 -m venv venv
   ```

2. Activate the virtual environment:

   ```bash

   source venv/bin/activate
   ```

3. Install pdfkit:

   ```bash

   pip install pdfkit
   ```

4. Save the code snippet in a file named `url.py` and run the script:

   ```bash

   python url.py
   ```

The output PDF will be saved in the current directory as `example.pdf`.![Python HTML to PDF conversion using wkhtmltopdf](@/assets/images/blog/2022/how-to-convert-html-to-pdf-using-wkhtmltopdf/google.png)

## Creating a PDF from a string

The `from_string` method takes two arguments: the HTML string and the output path. The following code snippet shows how to do this:

```python

import pdfkit

pdfkit.from_string('<h1>Hello World!</h1>', 'out.pdf')

```![Creating a PDF from a String - Python HTML to PDF conversion](@/assets/images/blog/2022/how-to-convert-html-to-pdf-using-wkhtmltopdf/string.png)

## Creating a PDF from a file

The `from_file` method takes two arguments: the path to the HTML file and the output path. The following code snippet shows how to do this:

```python

import pdfkit

pdfkit.from_file('index.html', 'index.pdf')

```

You’ll use an invoice template for the HTML file. You can download the template from [here](https://www.nutrient.io/api/assets/downloads/samples/invoice.zip). The following image shows the invoice template.![Invoice HTML to PDF example - Python HTML to PDF conversion](@/assets/images/blog/2022/how-to-convert-html-to-pdf-using-wkhtmltopdf/invoice.png)

It’s also possible to pass some additional parameters — like the page size, orientation, and margins. Add the [`options`](https://wkhtmltopdf.org/usage/wkhtmltopdf.txt) parameter to do this:

```python

options = {
    'page-size': 'Letter',
    'orientation': 'Landscape',
    'margin-top': '0.75in',
    'margin-right': '0.75in',
    'margin-bottom': '0.75in',
    'margin-left': '0.75in',
    'encoding': "UTF-8",
    'custom-header': [
        ('Accept-Encoding', 'gzip')
    ],
    'no-outline': None
}

pdfkit.from_file('index.html', 'index.pdf', options=options)

```

### Adding headers and footers

Use `header-html` and `footer-html` in the `options` dict to attach HTML files as repeating headers and footers on every page:

```python

import pdfkit

options = {
    'header-html': 'header.html',
    'footer-html': 'footer.html',
    'page-size': 'A4',
    'margin-top': '1in',
    'margin-right': '1in',
    'margin-bottom': '1in',
    'margin-left': '1in',
    'encoding': "UTF-8"
}

pdfkit.from_url('https://example.com', 'output_with_headers_footers.pdf', options=options)

```

## More use cases

Here are some common scenarios where HTML-to-PDF conversion with pdfkit is useful, with example code for each.

### Generating reports

If you need to generate reports from web data, you can convert HTML tables or dashboards to PDF for easy sharing and archiving:

```python

import pdfkit

html_report = """
<html>
  <head><title>Report</title></head>
  <body>
    <h1>Monthly Sales Report</h1>
    <table border="1">
      <tr><th>Product</th><th>Quantity</th><th>Price</th></tr>
      <tr><td>Product A</td><td>10</td><td>$100</td></tr>
      <tr><td>Product B</td><td>5</td><td>$200</td></tr>
    </table>
  </body>
</html>
"""

pdfkit.from_string(html_report, 'report.pdf')

```![Report HTML to PDF example - Python HTML to PDF conversion](@/assets/images/blog/2022/how-to-convert-html-to-pdf-using-wkhtmltopdf/report.png)

### Creating printable event tickets

Convert dynamically generated HTML event tickets into PDFs that users can print or store digitally:

```python

import pdfkit

event_ticket = """
<html>
  <head><title>Event Ticket</title></head>
  <body>
    <h1>Concert Ticket</h1>
    <p>Date: 2026-09-15</p>
    <p>Venue: Music Hall</p>
    <p>Seat: A12</p>
    <p>Confirmation: 1234567890</p>
  </body>
</html>
"""

pdfkit.from_string(event_ticket, 'ticket.pdf')

```![Event ticket rendered as PDF from HTML](@/assets/images/blog/2022/how-to-convert-html-to-pdf-using-wkhtmltopdf/ticket.png)

### Exporting blog posts to PDF

If you’re running a blog and want to offer readers the option to download posts as PDFs, you can convert the HTML content of a post into a PDF:

```python

import pdfkit

blog_post_html = """
<html>
  <head><title>My Blog Post</title></head>
  <body>
    <h1>How to Use Python for Web Development</h1>
    <p>Python is a versatile language...</p>
    <h2>Getting Started</h2>
    <p>To start developing web applications with Python...</p>
  </body>
</html>
"""

pdfkit.from_string(blog_post_html, 'blog_post.pdf')

```![Blog post rendered as PDF from HTML](@/assets/images/blog/2022/how-to-convert-html-to-pdf-using-wkhtmltopdf/blog_post.png)

### Invoice generation with data integration

Combine Python’s data processing capabilities with HTML-to-PDF conversion to generate invoices automatically:

```python

import pdfkit

customer_name = "John Doe"
items = [
    {"name": "Product 1", "quantity": 2, "price": 50},
    {"name": "Product 2", "quantity": 1, "price": 150},
]

total = sum(item["quantity"] * item["price"] for item in items)

invoice_html = f"""
<html>
  <head><title>Invoice</title></head>
  <body>
    <h1>Invoice for {customer_name}</h1>
    <table border="1">
      <tr><th>Item</th><th>Quantity</th><th>Price</th></tr>
      {''.join(f"<tr><td>{item['name']}</td><td>{item['quantity']}</td><td>${item['price']}</td></tr>" for item in items)}
      <tr><td colspan="2">Total</td><td>${total}</td></tr>
    </table>
  </body>
</html>
"""

pdfkit.from_string(invoice_html, 'invoice.pdf')

```![Generated invoice PDF with customer name and line items](@/assets/images/blog/2022/how-to-convert-html-to-pdf-using-wkhtmltopdf/invoice2.png)

### PDFs for e-learning materials

Create downloadable PDFs for e-learning courses, where the content is initially written in HTML:

```python

import pdfkit

course_material = """
<html>
  <head><title>Python Programming Course</title></head>
  <body>
    <h1>Introduction to Python</h1>
    <p>Python is a powerful, easy-to-learn programming language...</p>
    <h2>Lesson 1: Variables</h2>
    <p>Variables in Python are...</p>
  </body>
</html>
"""

pdfkit.from_string(course_material, 'python_course.pdf')

```![Python course material rendered as PDF from HTML](@/assets/images/blog/2022/how-to-convert-html-to-pdf-using-wkhtmltopdf/python_course.png)

### PDFs for product catalogs

Convert product catalogs stored as HTML into PDFs for distribution to clients or for offline viewing:

```python

import pdfkit

catalog_html = """
<html>
  <head><title>Product Catalog</title></head>
  <body>
    <h1>Our Products</h1>
    <div><h2>Product A</h2><p>Description of Product A...</p></div>
    <div><h2>Product B</h2><p>Description of Product B...</p></div>
  </body>
</html>
"""

pdfkit.from_string(catalog_html, 'catalog.pdf')

```![Product catalog rendered as PDF from HTML](@/assets/images/blog/2022/how-to-convert-html-to-pdf-using-wkhtmltopdf/catalog.png)

### Multipage PDF creation

You can create a multipage PDF by concatenating several HTML strings:

```python

import pdfkit

pages = [
    "<html><body><h1>Page 1</h1><p>Content for page 1...</p></body></html>",
    "<html><body><h1>Page 2</h1><p>Content for page 2...</p></body></html>",
    "<html><body><h1>Page 3</h1><p>Content for page 3...</p></body></html>"
]

pdfkit.from_string("".join(pages), 'multi_page.pdf')

```![Multipage PDF generated from concatenated HTML strings](@/assets/images/blog/2022/how-to-convert-html-to-pdf-using-wkhtmltopdf/multi_page.png)

## Common wkhtmltopdf gotchas

- **`IOError: 'No wkhtmltopdf executable found'`** — The binary isn’t on your `PATH`. Either add it, or pass an explicit configuration: `pdfkit.from_file('in.html', 'out.pdf', configuration=pdfkit.configuration(wkhtmltopdf='/usr/local/bin/wkhtmltopdf'))`.

- **Local images and CSS don’t render** — Pass `'enable-local-file-access': None` in `options` so wkhtmltopdf can read files from disk.

- **JavaScript-rendered content is missing** — wkhtmltopdf executes JavaScript via Qt WebKit but with a short default delay. Use `'javascript-delay': 1000` (ms) to wait for scripts.

- **Fonts look wrong on Linux servers** — Install the fonts your HTML references (e.g. `fonts-liberation`) before generating; wkhtmltopdf can’t fetch them at runtime.

## Conclusion

You now have a working HTML-to-PDF pipeline in Python using wkhtmltopdf and pdfkit — enough for invoices, reports, and other static documents.

When the toolchain starts to bite — complex CSS, JavaScript-heavy pages, missing fonts on a server, or simply the maintenance risk of two deprecated dependencies — Nutrient’s [HTML-to-PDF API](https://www.nutrient.io/api/html-to-pdf-api/) is a drop-in REST replacement that needs no binary install. For in-browser viewing, annotation, and signing, the [Nutrient JavaScript PDF library](https://www.nutrient.io/guides/web.md) integrates with [React.js](https://www.nutrient.io/blog/how-to-build-a-reactjs-pdf-viewer/), [Angular](https://www.nutrient.io/blog/how-to-build-an-angular-pdf-viewer/), and [Vue.js](https://www.nutrient.io/blog/how-to-build-a-vuejs-pdf-viewer/). Start a [free trial](https://www.nutrient.io/try) or [launch the demo](https://www.nutrient.io/demo/hello).

## FAQ

#### How can I convert HTML to PDF using Python with wkhtmltopdf?

To convert HTML to PDF using Python with `wkhtmltopdf`, install `pdfkit` with `pip install pdfkit`. Then use `pdfkit.from_file('input.html', 'output.pdf')` to generate a PDF.

#### What are the steps to install and configure wkhtmltopdf for Python HTML-to-PDF conversion?

First, install `wkhtmltopdf` on your system and ensure it’s in your `PATH`. Then, install `pdfkit` using `pip install pdfkit` and configure it in your Python script if needed.

#### Can I customize the PDF output when converting HTML to PDF with Python?

Yes, you can customize the PDF output by passing options like page size and margins to the `pdfkit` function when converting HTML to PDF with Python.

#### How can I troubleshoot errors in Python HTML-to-PDF conversion using wkhtmltopdf?

Review the error messages, ensure `wkhtmltopdf` is correctly installed, verify that HTML resources are accessible, and adjust `pdfkit` options to address rendering issues.
---

## Related pages

- [The business case for accessibility: Five ways it drives enterprise value](/blog/5-ways-accessibility-drives-enterprise-value.md)
- [Advanced Techniques For React Native Ui Components](/blog/advanced-techniques-for-react-native-ui-components.md)
- [Accessibility Untangled Why It Matters Guide](/blog/accessibility-untangled-why-it-matters-guide.md)
- [Auto Tagging And Document Accessibility In Dotnet Sdk](/blog/auto-tagging-and-document-accessibility-in-dotnet-sdk.md)
- [Best Document Viewers](/blog/best-document-viewers.md)
- [Ai Document Automation Extraction To Action](/blog/ai-document-automation-extraction-to-action.md)
- [The CEO’s AI playbook: Why decision architecture beats model selection](/blog/ceo-ai-playbook-decision-architecture.md)
- [Create Pdfs With React](/blog/create-pdfs-with-react.md)
- [Complete Guide To Pdfjs](/blog/complete-guide-to-pdfjs.md)
- [The CTO’s AI playbook: Why accountability architecture beats orchestration](/blog/cto-ai-playbook-accountability-architecture.md)
- [Digital Signatures](/blog/digital-signatures.md)
- [Document Ai Vs Ocr](/blog/document-ai-vs-ocr.md)
- [Document Viewer](/blog/document-viewer.md)
- [Emerging threats: Your logging system may be an agentic threat vector](/blog/emerging-threats-your-logging-system.md)
- [How To Build A Reactjs Viewer With Pdfjs](/blog/how-to-build-a-reactjs-viewer-with-pdfjs.md)
- [or](/blog/how-to-build-a-javascript-pdf-viewer-with-pdfjs.md)
- [or](/blog/how-to-build-a-reactjs-pdf-viewer-with-react-pdf.md)
- [How To Create Pdfs With React To Pdf](/blog/how-to-create-pdfs-with-react-to-pdf.md)
- [How To Embed A Pdf Viewer In Your Website](/blog/how-to-embed-a-pdf-viewer-in-your-website.md)
- [Html In Pdf Format](/blog/html-in-pdf-format.md)
- [base_url tells WeasyPrint where to resolve relative asset paths](/blog/how-to-generate-pdf-reports-from-html-in-python.md)
- [Pdf Page Labels](/blog/pdf-page-labels.md)
- [Linearized Pdf](/blog/linearized-pdf.md)
- [Nutrient Vs Conga Composer](/blog/nutrient-vs-conga-composer.md)
- [Open Pdf In Your Web App](/blog/open-pdf-in-your-web-app.md)
- [Pdf Sdk Compliance Security Checklist](/blog/pdf-sdk-compliance-security-checklist.md)
- [Online Document Viewer](/blog/online-document-viewer.md)
- [How To Convert Html To Pdf Using Html2pdf](/blog/how-to-convert-html-to-pdf-using-html2pdf.md)
- [Pdf Ua Compliance Guide](/blog/pdf-ua-compliance-guide.md)
- [Pdfjs Coordinate Systems Pdf To Screen](/blog/pdfjs-coordinate-systems-pdf-to-screen.md)
- [Pdf Sdk Performance Benchmark](/blog/pdf-sdk-performance-benchmark.md)
- [Pdfjs Eventbus Guide](/blog/pdfjs-eventbus-guide.md)
- [Pdfjs Limitations Commercial Upgrade](/blog/pdfjs-limitations-commercial-upgrade.md)
- [Pdfjs Navigation Zoom Rotation](/blog/pdfjs-navigation-zoom-rotation.md)
- [Pdfjs React Viewer Setup](/blog/pdfjs-react-viewer-setup.md)
- [Pdfjs Text Search Pdffindcontroller](/blog/pdfjs-text-search-pdffindcontroller.md)
- [Process Flows](/blog/process-flows.md)
- [or](/blog/sample-blog-updated.md)
- [Vector Pdf](/blog/vector-pdf.md)
- [Convert an HTML file to PDF.](/blog/top-ten-ways-to-convert-html-to-pdf.md)
- [What Are Annotations](/blog/what-are-annotations.md)
- [Web Sdk Is Now Headless](/blog/web-sdk-is-now-headless.md)
- [Wcag2 Accessibility Requirements Documents](/blog/wcag2-accessibility-requirements-documents.md)
- [Why Your Ai Agent Hallucinates Pdf Table Data](/blog/why-your-ai-agent-hallucinates-pdf-table-data.md)
- [What Is Pdf Ua](/blog/what-is-pdf-ua.md)
- [What Is A Vpat](/blog/what-is-a-vpat.md)

