October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
CSS

How to Set Fonts in Python pdfkit (Body Text, Custom Fonts, Headers and Troubleshooting)

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

Set the font in the HTML and CSS that pdfkit sends to wkhtmltopdf. Python’s pdfkit package does not provide a separate body-font API. Define a normal font-family rule (and, when appropriate, an @font-face rule), then pass that stylesheet with css= or through wkhtmltopdf’s user-stylesheet option. Headers and footers are different: wkhtmltopdf has dedicated font-name and font-size options for those regions.

How pdfkit font selection works

pdfkit is a Python wrapper around wkhtmltopdf. Your Python call assembles HTML, CSS and renderer options; wkhtmltopdf performs the actual layout and PDF rendering. Consequently, page content follows CSS, not a special pdfkit font parameter.

  • Body, headings, tables and other HTML: use CSS font-family, font-weight and font-style.
  • Header and footer text generated by wkhtmltopdf: use renderer options such as header-font-name and footer-font-size.
  • Custom font files: declare them with CSS @font-face, then verify that the renderer can read the files in its production environment.

A font installed in your desktop application is not automatically available to a server, container or CI runner. wkhtmltopdf depends on the runtime’s font configuration, including fontconfig and freetype2.

Set a standard installed font in CSS

Start with a system font so you can confirm that the stylesheet is being loaded:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
/* report.css */
html, body {
  font-family: Arial, Helvetica, sans-serif;
  font-size: 11pt;
  line-height: 1.45;
}

h1, h2, h3 {
  font-family: Georgia, "Times New Roman", serif;
}

Render an HTML file and attach the stylesheet with pdfkit:

import pdfkit

pdfkit.from_file("report.html", "report.pdf", css="report.css")

The same approach works with an HTML string:

import pdfkit

html = """
<!doctype html>
<html>
  <head><meta charset="utf-8"></head>
  <body><h1>Quarterly report</h1><p>Body text</p></body>
</html>
"""

pdfkit.from_string(html, "report.pdf", css="report.css")

For repeatable output, include an explicit UTF-8 declaration in the HTML and pass an encoding option when non-ASCII characters are present.

Use a custom font with @font-face

The usual implementation is to define the font file in CSS and apply it to the elements that need it:

/* report.css */
@font-face {
  font-family: "Report Sans";
  src: url("fonts/ReportSans-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
}

@font-face {
  font-family: "Report Sans";
  src: url("fonts/ReportSans-Bold.ttf") format("truetype");
  font-weight: 700;
  font-style: normal;
}

body {
  font-family: "Report Sans", sans-serif;
}

strong, b, h1, h2, h3 {
  font-weight: 700;
}

This syntax is standard CSS implementation guidance. The official materials do not guarantee that every wkhtmltopdf build supports every font-file format or web-font loading scenario, so validate the exact renderer build and operating system you deploy.

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

Make relative font paths deterministic

A relative URL such as fonts/ReportSans-Regular.ttf is resolved from the stylesheet or document context used by the renderer. Keep the HTML, CSS and font files in a known directory and test from the same working directory as your service. If you generate temporary files, use absolute paths where practical and ensure the conversion process has read permission.

Choose fallbacks deliberately

Always provide a fallback family. If the custom file cannot be loaded, the PDF will still render, but its metrics, line wrapping and pagination can change. A generic fallback such as sans-serif is safer than allowing an arbitrary platform default.

Attach CSS with css or a user stylesheet

pdfkit documents an external css argument:

import pdfkit

pdfkit.from_file(
    "report.html",
    "report.pdf",
    css="report.css",
)

The wrapper describes this argument as a workaround for a wkhtmltopdf stylesheet issue and recommends trying the renderer’s user-stylesheet option first when it is supported by your installed build:

import pdfkit

options = {
    "user-style-sheet": "report.css",
    "encoding": "UTF-8",
}

pdfkit.from_file("report.html", "report.pdf", options=options)

pdfkit option names omit wkhtmltopdf’s leading two hyphens. Thus, write user-style-sheet, not --user-style-sheet, in the Python dictionary. If the user stylesheet does not apply in your build, use css= and inspect verbose renderer output.

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.

Set header and footer fonts separately

CSS controls HTML content, but wkhtmltopdf-generated headers and footers have their own settings. The renderer exposes --header-font-name, --header-font-size, --footer-font-name and --footer-font-size. Its documented defaults are Arial and size 12 for the corresponding header and footer font settings.

import pdfkit

options = {
    "header-left": "Acme Report",
    "header-font-name": "Arial",
    "header-font-size": 10,
    "footer-right": "Page [page] of [topage]",
    "footer-font-name": "Arial",
    "footer-font-size": 9,
    "encoding": "UTF-8",
}

pdfkit.from_file("report.html", "report.pdf", options=options)

These options do not replace the CSS font for the page body. A CSS declaration on body will not necessarily change a renderer-managed header or footer; configure both paths when you need visual consistency.

Use a complete, production-oriented example

The following layout keeps assets together, enables UTF-8 and configures a renderer header and footer:

from pathlib import Path
import pdfkit

base = Path(__file__).parent
html_path = base / "report.html"
css_path = base / "report.css"
pdf_path = base / "out" / "report.pdf"
pdf_path.parent.mkdir(exist_ok=True)

options = {
    "encoding": "UTF-8",
    "header-left": "Monthly report",
    "header-font-name": "Arial",
    "header-font-size": 10,
    "footer-center": "Page [page] of [topage]",
    "footer-font-name": "Arial",
    "footer-font-size": 9,
}

pdfkit.from_file(
    str(html_path),
    str(pdf_path),
    css=str(css_path),
    options=options,
    verbose=True,
)
print(f"Wrote {pdf_path}")

Keep the same wkhtmltopdf executable, operating system image and font packages in development and production. The project identifies 0.12.6 as the stable series, released June 11, 2020; record the actual executable version used by your deployment because distribution builds can differ.

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

Diagnose a font that does not appear

1. Confirm that CSS is loaded

Temporarily set an unmistakable family, such as monospace, and render again. If nothing changes, the problem is stylesheet attachment or path resolution rather than the font file. Verify the css argument or user-style-sheet option and use verbose=True to expose wkhtmltopdf diagnostics.

2. Confirm runtime font availability

Install the font in the same server or container that launches wkhtmltopdf, or reference a file that the process can read. Font availability in a developer’s desktop editor does not prove availability to the renderer. Check the runtime’s fontconfig and freetype2 setup.

3. Check file paths and permissions

Inspect the exact path resolved by the renderer, capitalization and permissions. A CSS URL that works from one working directory can fail when a supervisor, worker queue or container starts the process elsewhere. Prefer a known absolute asset location for diagnostics.

4. Check the actual font metadata

The family name in CSS must match the family declared by the font resource, while font-weight and font-style should match the face you define. If you declare only a regular face and request a heavy weight, the renderer may synthesize or substitute a face.

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.

5. Separate body, header and footer tests

Render one test with a conspicuous body font and another with a conspicuous header/footer font. If body text changes but the header does not, configure the dedicated header/footer options rather than changing CSS.

6. Compare environments and versions

Record the wkhtmltopdf version, operating system, installed font packages and pdfkit version alongside a failing PDF. The stable 0.12.6 release dates from 2020, so a host’s package may include patches or platform-specific behavior that another host does not.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Reliability and pagination considerations

  • Font metrics affect layout: a fallback can widen lines, increase page count or move headings across page breaks.
  • Use explicit weights: define regular and bold faces when both are needed instead of relying on synthetic bold.
  • Freeze assets for deployments: package the CSS and font files with the application or image, and test after every base-image update.
  • Validate the output PDF: inspect glyphs, wrapping, page count and headers in the same viewer and environment used by recipients.
  • Keep diagnostics available: enable verbose output during troubleshooting, but route it to controlled logs in production.

Or skip the browser setup

If your real goal is capturing a web page rather than generating a document from HTML, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP or PDF; it is not a replacement for pdfkit’s CSS-to-PDF pipeline, but it avoids maintaining a browser-rendering setup for URL captures.

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}`);

See the ScreenshotNeo documentation for request options. Cookie banners, newsletter popups and chat widgets can be removed before capture; bot checks, blank pages and failed loads are not billed, and response headers report the page verdict and billing status. Its MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000. Sign up free.

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

Quick decision guide

Need Use
Font for normal page content CSS font-family in the HTML stylesheet
Custom typeface file CSS @font-face, readable by the renderer
Attach an external stylesheet pdfkit css= or supported user-style-sheet
Font for wkhtmltopdf header/footer header-font-* and footer-font-* options
Font works locally but not on server Install/package the font and verify fontconfig, freetype2, paths and permissions

Frequently Asked Questions

Does pdfkit have a body-font parameter?

No. Set the body font in the HTML/CSS passed to wkhtmltopdf.

Can I use a Google Fonts URL?

The documented material does not guarantee remote web-font behavior across wkhtmltopdf builds. For predictable output, package the font and reference it with a tested local path.

Why does changing CSS not change my footer?

wkhtmltopdf-generated footers use separate footer font-name and footer font-size options; configure those independently.

Which wkhtmltopdf version should I record?

Record the executable and platform actually deployed. The project lists 0.12.6 as the stable series, released June 11, 2020.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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

Read next

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.