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.