Blog Post

How to Generate PDF Reports from HTML in Python

Illustration: How to Generate PDF Reports from HTML in Python

In this post, you’ll learn how to generate PDF reports from HTML using our Python PDF Generator API. With our API, you can generate 100 PDF reports per month for free. To access your API key, sign up for a free account.

This will be especially useful if you generate and distribute a high volume of standardized reports throughout the year. With our API, you can automate your report generation by dynamically injecting data and content into a standardized HTML template.

We’ll demonstrate how you can generate a report with a free PDF report template in HTML and CSS that can be customized to meet your specific requirements. You can easily style your report by updating the CSS file with your own custom images and fonts. For reports that span multiple pages, you can add a header and footer that repeats across all your pages.

Requirements

To get started, you’ll need:

To access your PSPDFKit API key, sign up for a free account. Your account lets you generate 100 documents for free every month. Once you’ve signed up, you can find your API key in the Dashboard > API Keys section.

Python is a programming language, and pip is a package manager for Python, which you’ll use to install the requests library. Requests is an HTTP library that makes it easy to make HTTP requests.

Install the requests library with the following command:

python -m pip install requests

Setup

Download the report template and extract the contents of the ZIP file into a folder. You’ll get an HTML file, Inter fonts, a Space Mono font, an SVG logo, images, and a README file.

Creating a CSS File

If you open the index.html file, you’ll see the styles between the opening and closing <style> tag. Copy the styles to a new file called style.css, and save it in the same folder:

@font-face {
	font-family: 'Inter';
	src: url('Inter-Regular.ttf') format('truetype');
	font-weight: 400;
	font-style: normal;
}

@font-face {
	font-family: 'Inter';
	src: url('Inter-Medium.ttf') format('truetype');
	font-weight: 500;
	font-style: normal;
}

@font-face {
	font-family: 'Inter';
	src: url('Inter-Bold.ttf') format('truetype');
	font-weight: 700;
	font-style: normal;
}

@font-face {
	font-family: 'Space Mono';
	src: url('SpaceMono-Regular.ttf') format('truetype');
	font-weight: 400;
	font-style: normal;
}

body {
	font-size: 0.75rem;
	font-family: 'Inter', sans-serif;
	font-weight: 400;
	color: #000000;
	margin: 0 auto;
	position: relative;
}

#pspdfkit-header {
	font-size: 0.625rem;
	text-transform: uppercase;
	letter-spacing: 2px;
	font-weight: 400;
	color: #717885;
	margin-top: 2.5rem;
	margin-bottom: 2.5rem;
	width: 100%;
}

.header-columns {
	display: flex;
	justify-content: space-between;
	padding-left: 2.5rem;
	padding-right: 2.5rem;
}

.logo {
	height: 1.5rem;
	width: auto;
	margin-right: 1rem;
}

.logotype {
	display: flex;
	align-items: center;
	font-weight: 700;
}

h1 {
	font-family: 'Space Mono', monospace;
	font-size: 2.25rem;
	font-weight: 400;
}

h2 {
	font-family: 'Space Mono', monospace;
	font-size: 1.5rem;
	font-weight: 400;
}

h3 {
	font-family: 'Space Mono', monospace;
	font-size: 1.25rem;
	font-weight: 400;
}

h4 {
	font-family: 'Inter', sans-serif;
	font-size: 1rem;
	font-weight: 400;
}

.page {
	margin-left: 5rem;
	margin-right: 5rem;
}

.column-layout {
	display: flex;
	justify-content: space-between;
	margin: 3rem 0 5rem 0;
	gap: 2rem;
}

.column {
	display: flex;
	flex-direction: column;
}

.width-30 {
	width: 30%;
}

.width-70 {
	width: 70%;
}

.column-title {
	font-size: 0.625rem;
	margin: 0;
}

.full-width {
	width: 100%;
}

.spacer-1 {
	height: 1rem;
}

.spacer-2 {
	height: 2rem;
}

.line-break {
	height: 1px;
	width: 100%;
	background-color: #000000;
	margin: 2.5rem 0 2.5rem 0;
}

.margin-b-0 {
	margin-bottom: 0;
}

.margin-t-0 {
	margin-top: 0;
}

.text-blue {
	color: #4537de;
}

#pspdfkit-footer {
	font-size: 0.5rem;
	text-transform: uppercase;
	letter-spacing: 1px;
	font-weight: 500;
	color: #717885;
	margin-top: 2.5rem;
	bottom: 2.5rem;
	position: absolute;
	width: 100%;
}

.footer-columns {
	display: flex;
	justify-content: space-between;
	padding-left: 2.5rem;
	padding-right: 2.5rem;
}

To access the styles from index.html, use the <link> tag. While referring to the stylesheet file, just use the name of the file and don’t create nested paths:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta
			name="viewport"
			content="width=device-width, initial-scale=1.0"
		/>
		<title>Report</title>
		<link rel="stylesheet" href="style.css" />
	</head>
</html>

Interacting with the API

Now, import requests and json to the pspdfkit.py file. Place the pspdfkit.py file in the root directory of your project:

import requests
import json

Preparing the Payload

Create a dictionary to hold the data you want to send to the API. However, later you’ll need to convert the dictionary to a JSON object using the json.dumps function.

The instructions object references files by the name of their parts that are appended in the form data as files:

instructions = {
    'parts': [
        {
            'html': 'index.html',
            'assets': [
               "style.css",
                "Inter-Regular.ttf",
                "Inter-Medium.ttf",
                "Inter-Bold.ttf",
                "SpaceMono-Regular.ttf",
                "logo.svg",
                "photo-1.png",
                "photo-2.png",
                "photo-3.png",
                "photo-4.png",
            ],
        }
    ]
}

To access the requests library, use the request method.

Now, make a POST request to the https://api.pspdfkit.com/build endpoint with the instructions object as the payload. Then, save the resulting PDF as result.pdf in the same folder as the Python file.

Don’t forget to replace YOUR_API_KEY with your API key:

response = requests.request(
    'POST',
    'https://api.pspdfkit.com/build',
    headers={
        'Authorization': 'Bearer {YOUR_API_KEY}', # Replace with your API key.
    },
    files={
        'index.html': open('index.html', 'rb'),
        'style.css': open('style.css', 'rb'),
        'Inter-Regular.ttf': open('Inter-Regular.ttf', 'rb'),
        'Inter-Medium.ttf': open('Inter-Medium.ttf', 'rb'),
        'Inter-Bold.ttf': open('Inter-Bold.ttf', 'rb'),
        'SpaceMono-Regular.ttf': open('SpaceMono-Regular.ttf', 'rb'),
        'logo.svg': open('logo.svg', 'rb'),
		   'photo-1.png': open('photo-1.png', 'rb'),
		   'photo-2.png': open('photo-2.png', 'rb'),
	     'photo-3.png': open('photo-3.png', 'rb'),
		  'photo-4.png': open('photo-4.png', 'rb'),
	 },
    },
    data={
        'instructions': json.dumps(instructions)
    },
    stream=True
)

if response.ok:
    with open('result.pdf', 'wb') as fd:
        for chunk in response.iter_content(chunk_size=8096):
            fd.write(chunk)
else:
    print(response.text)
    exit()

Generating the PDF

Now, run the Python application by executing the following command:

python3 pspdfkit.py

# Or for Python 2

python pspdfkit.py

You can see the full code below:

import requests
import json

instructions = {
    'parts': [
        {
            'html': 'index.html',
            'assets': [
                "style.css",
                "Inter-Regular.ttf",
                "Inter-Medium.ttf",
                "Inter-Bold.ttf",
                "SpaceMono-Regular.ttf",
                "logo.svg",
                "photo-1.png",
                "photo-2.png",
                "photo-3.png",
                "photo-4.png",
            ],
        }
    ]
}

response = requests.request(
    'POST',
    'https://api.pspdfkit.com/build',
    headers={
        'Authorization': 'Bearer {YOUR_API_KEY}' # Replace with your API key.
    },
    files={
        'index.html': open('index.html', 'rb'),
        'style.css': open('style.css', 'rb'),
        'Inter-Regular.ttf': open('Inter-Regular.ttf', 'rb'),
        'Inter-Medium.ttf': open('Inter-Medium.ttf', 'rb'),
        'Inter-Bold.ttf': open('Inter-Bold.ttf', 'rb'),
        'SpaceMono-Regular.ttf': open('SpaceMono-Regular.ttf', 'rb'),
        'logo.svg': open('logo.svg', 'rb'),
		  'photo-1.png': open('photo-1.png', 'rb'),
		  'photo-2.png': open('photo-2.png', 'rb'),
		  'photo-3.png': open('photo-3.png', 'rb'),
		  'photo-4.png': open('photo-4.png', 'rb'),
    },
    data={
        'instructions': json.dumps(instructions)
    },
    stream=True
)

if response.ok:
    with open('result.pdf', 'wb') as fd:
        for chunk in response.iter_content(chunk_size=8096):
            fd.write(chunk)
else:
    print(response.text)
    exit()

Conclusion

In this post, you generated a PDF report from an HTML template using our Python PDF generation API. We created similar PDF report generation guides using sample code from other programming languages:

In addition to templates for generating reports, we created free templates for other commonly used documents, like receipts, invoices, and certificates. If you’re interested in generating other types of documents in Python, check out the following posts:

All our templates are available for you to download on our PDF Generator API page. Feel free to customize or add any CSS to the template to fit your use case or help reflect your company’s brand.

Related Products
Share Post
Free 60-Day Trial Try PSPDFKit in your app today.
Free Trial

Related Articles

Explore more
PRODUCTS  |  API • Releases • Components

PSPDFKit API OCR and Office Conversion Improvements

DEVELOPMENT  |  API • Elixir • Insights

Rate Limiting Server Requests in Elixir

DESIGN  |  Web • Processor • API • PDF Generation • Tips

Adding Custom Fonts to HTML Documents