How to generate PDF of a website page with Node.js

Yogesh Chavan
JavaScript in Plain English
5 min readJan 21, 2020

--

Easily create the same quality of pdf that we get when we do Ctrl + P or Command + P (Mac) on Chrome Browser to print the pdf

Photo by Bank Phrom on Unsplash

In this article, we will see how easy it is to generate PDF of any webpage using Nodejs and send the generated pdf back to the client side application.

We will use puppeteer tool which is a headless chrome API to generate pdf
So let’s get started.

Create a package.json file using

npm init -y

Install puppeteer using

npm install --save puppeteer@2.0.0

We will generate a sample pdf of the hacker news page.

Create a server folder and add index.js file inside it with the following code:

The waitUntil option in the above code will wait for the page to load completely before generating a pdf.

To execute the code, run

node server/index.js

Once you execute the above command, you will see a new pdf file with the name hacker_news.pdf is generated.

If you want to maintain the background color of the webpage, you need to add printBackground: true option while generating pdf

We have used the A4 format for creating pdf.
The most widely used formats are A4 and Letter.

Otherformat options are:

  • Letter: 8.5in x 11in
  • Legal: 8.5in x 14in
  • Tabloid: 11in x 17in
  • Ledger: 17in x 11in
  • A0: 33.1in x 46.8in
  • A1: 23.4in x 33.1in
  • A2: 16.54in x 23.4in
  • A3: 11.7in x 16.54in
  • A4: 8.27in x 11.7in
  • A5: 5.83in x 8.27in
  • A6: 4.13in x 5.83in

You can set viewport width and height using setViewport before generating pdf using page.pdf function

await page.setViewport({ width: 1680, height: 1050 });

If you want to display the default header and footer, you need to add displayHeaderFooter option and specify the margin for header and footer

This will add the header with the current date in pdf as shown below

and page URL will be added in the footer in pdf as shown below

We have provided a 38px margin for all the sides for the header and footer which is approximately equal to 1cm.

Custom header and footer:
We can also provide our custom header and footer using headerTemplate and footerTemplate options respectively.

In all of the above examples, we are storing the generated pdf in the root folder which is not ideal.

Let’s see how we can change the location to store the generated pdf files.
We will use the current timestamp to use as the name for the generated pdf.

Create a new files folder in server directory.

Import the path node package at the top:

const path = require('path');

Get today’s date using:

const todays_date = new Date();

change path option in page.pdf function to

path: `${path.join(__dirname, 'files', todays_date.getTime() + '.pdf')}`,

__dirname points to the current directory which is server in our case.

We are using the join method of the path node package so it will correctly create the file because Linux/mac path has forward slashes in the file path and windows has backward slashes.

The path node package handles this conversion for us automatically.

Now we will connect our backend nodejs with the front end so we can send the pdf from server to client when the user clicks on a button or a link to download the pdf

Install express using:

npm install --save express@4.17.1

Create a new file server.js and add the express app using

const express = require('express');
const app = express();

1.Copy the previous code of pdf generation in the get handler and start the server using app.listen
2. Store the pdf file path in a separate variable so we can use it later

const pdfURL = path.join(__dirname, 'files', todays_date.getTime() + '.pdf');

3. Store the result from page.pdf function call in pdf variable
4. Set the response content type and send the pdf back to the client using

res.set({
"Content-Type": "application/pdf",
"Content-Length": pdf.length
});
res.sendFile(pdfURL);

If you are having trouble understanding the server creation code, check out my previous article regarding creating REST API’s in Nodejs HERE.

Now start the express server by executing

node server/server.js

and navigate to http://localhost:5000/pdf

You will see your generated pdf in the browser

Now, create a public folder and index.html inside it with the following content

In server/server.js file, before the get /pdf route, specify the public folder path so we can access all the files under the public folder

app.use(express.static(path.join(__dirname, '..', 'public')));

Now, restart the server using

node server/server.js

and navigate to http://localhost:5000/ which will load the index.html file we created

If you click the GET PDF link, you will be able to see the generated pdf where you can view or download the pdf file

We can also add any CSS styling to the generated pdf using

await page.addStyleTag({
content: `
body { border: 1px solid #ccc }
`
});

We will need to call the addStyleTag before calling the page.pdf method.

Generate PDF from local HTML file:

To generate a pdf from an HTML file we need to specify the HTML file url using file:<path_of_file> inside the page.goto method

Create a lorem.html file inside the public directory with the following content

and reference the file in page.goto function as

await page.goto(`file:${path.join(__dirname, '..' , 'public', 'lorem.html')}`, { waitUntil: "networkidle2" });

To learn more about puppeteer check HERE

Puppeteer Documentation: https://pptr.dev/

Complete Github Source Code: https://github.com/myogeshchavan97/pdf_generation_puppeteer

That’s it for today. Hope you learned something new today.

Don’t forget to subscribe to get my weekly newsletter with amazing tips, tricks, and articles directly in your inbox here.

--

--