Headless Pdfs: Printing Web Pages With Selenium

A simple method for converting web pages into PDFs using Selenium.

Last year, while I was job hunting between Spain, France, and Switzerland, I wanted an easy way to design my CV so it was both visually appealing and highly readable for ATS. I also wanted to be able to quickly adjust it for different roles (expanding relevant sections, condensing others, or filtering my skills to match a specific job description).

After exploring the market for CV generators and I decided to build my own solution, which was a simple script that used Jinja2 for templating and a bit of CSS/HTML for the layout. However, I hit a small issue when it came to generating a high-quality PDF from the final web page. I couldn't find any straightforward tutorial and AI didn't help that much. Luckily for me, a deep dive into the official Selenium documentation revealed exactly what I needed.

Turns out, Selenium provides a very clean way to execute the "print to PDF" command in the browser without wrestling with obscure configurations or setups. In fact, it's so simple that you only need a few lines of code:

from selenium import webdriver
from selenium.webdriver.common.print_page_options import PrintOptions

driver = webdriver.Chrome()

print_options = PrintOptions()
print_options.orientation = "portrait"
print_options.page_height = 27.94  # A4 height
print_options.page_width = 21.59  # A4 width

driver.get("https://example.com/cv")
pdf = driver.print_page(print_options)
driver.quit()

In reality, the print_page method returns a base64-encoded string. To save it as a PDF file, we need to decode the data and write it to a binary file:

from base64 import b64decode

# Anything else stays the same.

pdf_data = b64decode(pdf)
with open("cv.pdf", "wb") as f:
  f.write(pdf_data)

And that's it. As you can imagine, building a small CLI as I did to generate multiple versions of a CV becomes very easy.

Headless Pdfs: Printing Web Pages With Selenium