Understanding PDF Generation with Headless Chrome
Headless browsers are currently gaining popularity as an efficient way to test web applications because they do not affect the user interface. In this post, I am going to discuss the benefits of Headless Chrome and two approaches for using Headless Chrome to automatically create PDF reports.
What is Headless Chrome?
Headless Chrome is a version of Chrome without a visible graphical user interface (GUI). With Headless Chrome, Chrome is run in the background of your computer but you cannot see it. Performing tests of web applications with Headless Chrome allows the program to sort through and interpret large amounts of data without the memory and speed costs of running the full Chrome system.
Some of the situations where Headless Chrome is beneficial include:
- Screenshots: Headless Chrome can be used to take automatic screenshots of webpages or applications. For example, if you want to test how your application looks on different screen sizes (desktop, mobile device), this is an easy way to automate the process and collect data.
- Reports: Headless Chrome can be programmed to automatically collect data and generate reports.
- Crawling: Headless Chrome can be used to rapidly browse multiple websites for information. For example, if you want to know the average price of a product on several different websites, Headless Chrome can be programmed to perform the search in seconds.
One of the largest benefits of using Headless Chrome is that everything happens in the back end, so you do not have to worry about users having slower data rate conversions or other browsers.
Generating PDFs
Recently, I used Headless Chrome to generate PDFs of target web pages. After some conversations to understand what the client was looking for, I decided that there might be two possible ways to do this.
With the first approach, I used the basic commands available within Headless Chrome. Here is an example snapshot of the code used to generate the PDF report:
In this example, I am using Chromium, an open source version of Chrome that works similarly. As you can see, I opened a terminal and ran the “chromium” command with the following options:
- Headless: Specifies that chromium will be run as a headless application and confirms that a window will not be opened.
- Disable-gpu: Though most servers do not have a graphic processing unit (GPU), this command ensures that the GPU is not engaged.
- Print-to-pdf: Commands Chrome to take a screenshot of the requested website and save it as a PDF report.
- (website): Identifies the website that the PDF is targeting. In the example above, the website used is https://grio.com.
Once the “chromium” command is executed, the following PDF is generated:
This approach is incredibly efficient, but I realized it had some limitations. As you can see in the example above, the screenshot was taken before the animation had time to finish, leaving the PDF of the site looking incomplete. This approach also makes several automatic determinations, including the information provided in the headers and footers and how many pages are generated. So, while this way is fast it isn’t necessarily the best way to get the results we were looking for.
An Improved Approach to Generating PDFs
To avoid the limitations of the first approach, the second approach uses two tools, Lighthouse and DevTools Protocol, to enhance the options available with Headless Chrome.
In this approach, I used Lighthouse to find the correct version of the web browser within the Chrome application and launch it. Lighthouse also performs several secondary tasks, including cross platform communication, disabling unnecessary Chrome services, automatically searching for the correct Chrome binary, and making the process node friendly.
I used the DevTools Protocol to issue commands to Chrome. With DevTools Protocol, you can tell Chrome to open a DevTools Protocol port and execute commands from that port. These commands can be nearly anything, including opening a website, ingesting JavaScript, loading CSS, and more. DevTools Protocol gives you the fine controls over your protocol options that the first approach was lacking.
In the improved Lighthouse and DevTools Protocol approach, you once again start by launching Headless Chrome:
As you can see, the launch options for this approach are similar to those used in the first approach. I am still using the “headless” and “disable-gpu” options. However, in this case, I am also able to set the size of the window that I want to render.
Once Headless Chrome is launched, you can issue the command to create the PDF:
As you can see in the sequence above, the first thing that this approach allows us to do is use an “await CDP” protocol, which ensures that the browser is fully loaded before the screenshot is taken.
You are also able to define additional details regarding how the PDF is going to be generated. As seen above, we can set the following PDF guidelines:
- Preferred width and height;
- Scale;
- Page ranges;
- Orientation of the page (landscape versus portrait);
- Whether the background should be printed;
- Header and footer information.
Once you set the PDF details, you can then save the generated PDF directly to a specified file. As you can see, the resulting PDF has undergone substantial improvements from the first approach:
We now have a two page PDF of the fully-loaded web browser with no unwanted headers or footers. This approach, though slightly more time consuming, nonetheless allows us to generate more useful, professional PDFs.
Final Thoughts
The automation and efficiency of PDF generation with Headless Chrome increases the amount of data we are able to generate and helps us more quickly optimize our web application. If you are trying this yourself, here are some other docs that I found helpful:
https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF
https://developers.google.com/web/updates/2017/04/headless-chrome
https://www.npmjs.com/package/chrome-launcher
1 Comment