Markdown to PDF Python: Tools, Capabilities, and How They Work

Jul 29, 2026
ByPDFtoMD
Markdown Workflowsmarkdown pdf python

The markdown-pdf library can convert Markdown-formatted text into a PDF. But there are other libraries as well. In this article, I’ll look at three tools that do Markdown to PDF.

There are a number of ways to turn Markdown files into PDFs. One approach is using the python-markdown library’s markdown module with PyMuPDF, which converts Markdown to PDF. Another option is the md2pdf CLI tool and its library counterpart. Alternatively, you can use Spire.Doc for Python to automate Markdown-to-PDF conversion.

The markdown-pdf library uses the markdown module from the python-markdown project along with PyMuPDF (the PyMuPDF library) to produce PDFs. The library’s primary purpose is to take a Markdown file and generate a PDF by simply running it through Python code.

In addition to producing PDFs from Markdown, the markdown-pdf library has an extensive set of features that support PDF output. These features include UTF-8 encoded text in any language, embedded images, page breaks in the order that they appear, a table of contents based on your document headings, and CSS styling. You can even have different page sizes within a single PDF.

If you want more advanced functionality, such as sections or pagination control, you can use markdown-pdf’s section-based model, which treats each section separately. It also allows for hyperlinking to external websites (e.g., GitHub), as well as internal links between pages, such as those linking back to named headings. A variety of metadata is available, including document information such as the title, author, subject, keywords, creation date, and modification date, plus a plugin system for processing special sections marked as such.

The md2pdf command-line utility supports styling options via WeasyPrint’s CSS engine and offers additional extensions, such as emoji support. Additionally, you can create custom Jinja2 templates that draw context data from frontmatter headers.

Let me explain all of these tools, their features, and how they work.

Three main Markdown to PDF libraries are:

  1. markdown-pdf: This free, open-source Python module is available on PyPI, and provides several functions for generating PDF documents from Markdown files. The markdown-pdf library works by taking a Markdown-formatted text file and producing a PDF using Python code.

Three main Markdown to PDF libraries are:

  1. md2pdf: A simple CLI utility and library, both of which require WeasyPrint. You can install it via uv with “uv tool install md2pdf[cli]”. The tool produces a PDF file by converting the given Markdown document.

  2. Spire.Doc for Python: A third-party solution that automates Markdown-to-PDF conversion.

All of these libraries allow you to generate PDFs from Markdown-formatted text, but they offer differing combinations of capabilities and features, as shown in the following table.

The markdown-pdf library takes a Markdown-formatted text file and generates a PDF using the Python interpreter. markdown-pdf has been designed to take advantage of many of the formatting features supported by Markdown.

The markdown-pdf module allows you to specify various parameters when you generate the PDF file. Among them are the following:

UTF-8 encoding for text in any language

Embedding images in the PDF

Page breaks in the desired order

A table of contents derived from the headings in the document

Page breaks in the desired order

CSS styling

CSS styling

Different page sizes within a single PDF

Tables

Clickable hyperlinks

In addition, the markdown-pdf library manages the structure of the PDF, allowing you to define separate sections of the document. You can add sections, control where they go on the page, and add new pages as needed. You can even link one section of the document to another, or to an external web site.

How does markdown-pdf manage sections and page structure? What features exist for controlling the layout and appearance of your generated PDF document?

markdown-pdf supports two basic models for structuring a PDF document: the section-based model, and the page-based model.

In the section-based model, markdown-pdf creates a new section for every section heading in the document. By default, each section begins on a new page. You can override this behavior with some of the properties described later. When using the section-based model, you can control where individual sections start and end within the overall structure of the document.

You can use the page_count property to report how many pages the current section will take up in the final PDF. This value changes after markdown-pdf adds the section to the PDF. Initially, the page_count property returns 0, because markdown-pdf hasn’t created the PDF yet. Once markdown-pdf completes creating the first section, the page_count value becomes 1.

When you add a second section to the document, the page_count property reports how many pages markdown-pdf will create for that section. For instance, you might want to have markdown-pdf begin the second section with an external link to GitHub. In this case, you’d probably want markdown-pdf to begin the new section on a new page. To ensure that, you’d specify that markdown-pdf should start the new section on a new page, not just append it to the previous section. Otherwise, the GitHub logo might end up on the same page as the last section.

Internal links between sections are handled differently than external links to external sites. For example, you can add a clickable link to the name of a person who appears elsewhere in the document. Clicking that link would move the reader directly to the section containing that person’s name.

You’ll find more about the document metadata that markdown-pdf makes available to developers shortly.

The markdown-pdf library provides access to a wide range of document metadata that you can access during development. You can modify many of the document properties, and you can use the plugins feature to process special sections that contain specific types of content, such as PlantUML code blocks.

The metadata available in markdown-pdf includes the following:

Document information

Creation date and time

Modification date and time

Creator (which defaults to the PyMuPDF library)

Modification date and time

Creator (which defaults to the PyMuPDF library)

Producer (which also defaults to PyMuPDF)

Title

Author

Subject

Keywords

Document settings

Page size and orientation

Header and footer information

Margins

Number of columns

Other metadata

Other metadata

Plugins

As with any PDF document, you can assign the appropriate metadata, such as the title of your document, so that your users know what they’re looking at. You can assign author information to provide credit to yourself or to someone else. The subject field gives a brief description of the contents of the document. The keywords field provides search terms that users can use to locate your document.

Another powerful feature of markdown-pdf is its plugin system. Plugins are used to process specially marked sections of the document, usually to render them in some way. markdown-pdf contains several built-in plugins, which are triggered automatically depending on how the document is formatted. You can also supply your own plugins to perform any special task.

For example, the plantuml plugin recognizes a block of PlantUML code in the document and renders it as an image. The plugin then embeds that image into the PDF document, allowing the reader to see the diagram without leaving the PDF.

One of the most interesting features of the markdown-pdf library is that it exposes the document metadata to developers. The metadata is stored in the MarkdownPdf.meta dictionary, which contains the following properties:

creationDate – Specifies the date and time the document was created.

modDate – Specifies the date and time the document was modified.

creator – Identifies the program that was used to create the PDF document.

producer – Identifies the program that was used to generate the PDF document.

title – Sets the title of the document.

author – Sets the author of the document.

subject – Sets the subject of the document.

keywords – Provides a list of keywords associated with the document.

By default, the creator and producer fields are set to the PyMuPDF library.

The metadata fields are generally read-only, but the exception is the creator field, which can be overwritten if you’re using another library to produce the PDF.

Styling Options in md2pdf

md2pdf is a simple command line utility (CLI) and library, both of which rely on WeasyPrint for the generation of the PDF. You must have a working copy of WeasyPrint before you can use md2pdf.

The utility is written in Python, but doesn’t use the standard Python pip install method to install it. Instead, we recommend using the uv tool to install md2pdf. Install md2pdf by entering the following command:

uv tool install md2pdf[cli]

uv tool install md2pdf[cli]

The --css flag lets you specify an external stylesheet, such as a custom-styles.css file that you’ve created.

You can also specify extra extensions to md2pdf with the --extras flag, enabling you to customize the output further. Some useful extensions include pymdownx.emoji, which enables proper rendering of code blocks, and others, like markdown.extensions.toc, which automatically inserts a table of contents at the top of the rendered document.

Jinja2 Templating in md2pdf

Jinja2 templating is a powerful capability in md2pdf. With it, you can insert custom HTML elements inside the template to enhance your document’s layout. You can even insert your own scripts or inline styles.

Context data is supplied through a YAML header called frontmatter. Context variables can be used in conjunction with conditional tags, allowing you to dynamically choose the contents of your PDF. Input Markdown files can also contain special Jinja tags indicating the use of a particular template, or that certain parts of the document should be excluded.

An example is a groceries list consisting of two items, each with a name and a quantity. If you wanted to print out your grocery list using md2pdf, you could create a custom template containing a <table> tag. Inside the table, you’d use a Jinja for-loop to loop through the list of groceries. Each row in the table would display the item’s name and its quantity.

Markdown to PDF Python: Tools, Capabilities, and How They Work | Blog