Converting Dynamic HTML to PDF in Node.js with Puppeteer

In this tutorial, we'll learn how to convert HTML content to a PDF file using Puppeteer in a Node.js environment. Puppeteer is a Node li...


In this tutorial, we'll learn how to convert HTML content to a PDF file using Puppeteer in a Node.js environment. Puppeteer is a Node library that provides a high-level API to control headless Chrome or Chromium over the DevTools Protocol, making it a powerful tool for automating web tasks, including generating PDF files from HTML content.


Converting Dynamic HTML to PDF in Node.js with Puppeteer


Prerequisites


Before we begin, ensure you have the following installed:

  • Node.js (with npm)
  • MySQL (for the database setup, optional for this tutorial)
  • Basic understanding of Node.js and JavaScript

Setting up the Project


First, let's set up a Node.js project and install the necessary dependencies.

Create a new directory for your project and navigate into it:

	
		mkdir html-to-pdf-nodejs
		cd html-to-pdf-nodejs
	

Initialize a new Node.js project:

	
		npm init -y
	

Install the required dependencies (Express, MySQL, Puppeteer, Open):

	
		npm install express mysql2 puppeteer open
	

Database Structure


For convert dynamic HTML to PDF we need to fetch data from MySQL table. So run below sql script which will create sampledata table in your database.

	
		CREATE TABLE `sampledata` (
		  `id` mediumint unsigned NOT NULL AUTO_INCREMENT,
		  `name` varchar(255) DEFAULT NULL,
		  `phone` varchar(100) DEFAULT NULL,
		  `email` varchar(255) DEFAULT NULL,
		  `address` varchar(255) DEFAULT NULL,
		  `postalZip` varchar(10) DEFAULT NULL,
		  `region` varchar(50) DEFAULT NULL,
		  `country` varchar(100) DEFAULT NULL,
		  PRIMARY KEY (`id`)
		) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
		
		INSERT INTO `sampledata` VALUES (1,'Stephen Taylor','1-802-830-1866','auctor.nunc@hotmail.com','5659 Luctus Rd.','21408','Dadra and Nagar Haveli','Poland'),(2,'Mason George','1-343-545-7768','mauris@aol.edu','Ap #221-6699 Lacus. St.','921307','FATA','Costa Rica'),(3,'Hasad Donaldson','1-666-557-3187','et.euismod@google.edu','Ap #383-4682 Ornare Av.','818143','Kinross-shire','United Kingdom'),(4,'Hall Holland','(805) 418-1538','tempor.est@icloud.com','P.O. Box 358, 7624 Tincidunt Avenue','486262','Madrid','Indonesia'),(5,'Adam Hampton','1-421-241-5178','cubilia.curae@google.ca','P.O. Box 161, 1859 Iaculis Av.','44837','Brussels Hoofdstedelijk Gewest','South Korea'),(6,'Elizabeth Allison','(538) 834-6212','elit.dictum@hotmail.edu','867-6580 At St.','33668','Jeju','Pakistan'),(7,'Neve Barber','1-552-311-0208','vestibulum.nec.euismod@google.com','224-8122 Donec Road','51174','Santa Catarina','Netherlands'),(8,'Fatima Pope','(619) 278-1176','nulla.integer@hotmail.couk','649-1054 Ipsum Rd.','748321','Bahia','Austria'),(9,'Shad Cobb','1-778-327-3349','dignissim.maecenas.ornare@outlook.edu','6983 Magna. Rd.','2163','Xīběi','Philippines'),(10,'Zephr Ruiz','1-544-316-1144','luctus.ipsum@google.ca','634-2043 Cras Avenue','3845','Mecklenburg-Vorpommern','Sweden'),(11,'Juliet Lynn','(375) 573-6793','proin.dolor.nulla@yahoo.net','Ap #179-6441 Cum Rd.','71829','Calabria','Turkey'),(12,'Candice Medina','1-441-292-1278','integer.vulputate@icloud.org','953-188 Et Rd.','440326','Vorarlberg','Australia'),(13,'Rhea Roach','(635) 768-6867','vitae.velit@icloud.edu','543-5616 Sem Av.','869566','Burgenland','Canada'),(14,'Dean Hendrix','(362) 760-8321','nunc.pulvinar@protonmail.ca','Ap #905-5267 Arcu Street','6755-4242','National Capital Region','Indonesia'),(15,'Malachi Mitchell','1-586-881-4174','eget.lacus.mauris@icloud.ca','P.O. Box 183, 1479 Massa. St.','367458','Västra Götalands län','Indonesia'),(21,'Gabriel Acevedo','1-215-463-4511','dictum.cursus@outlook.com','5681 Sit Rd.','28846','Lombardia','Italy'),(22,'Beau Norris','1-563-287-4004','eros@google.edu','Ap #533-2583 Duis Rd.','R8T 1S4','Eastern Visayas','United States'),(23,'Kylan Mckinney','1-533-833-5567','eleifend.vitae@hotmail.net','333-2972 Nec, Road','72866','Leinster','Australia'),(24,'Stone Parsons','1-584-246-2228','aenean@outlook.com','923-5509 Etiam Street','Y1R 5X7','Zamboanga Peninsula','Nigeria'),(25,'Neve Sweet','(764) 167-2572','tellus.aenean@aol.net','558-1070 Sed, St.','1023 PS','Vienna','United Kingdom');
	

Creating the Server and HTML Template


Now, let's create a basic Express server that serves an HTML page with sample data fetched from a MySQL database. We'll also include a button to trigger the conversion of the HTML to a PDF file.

Create a file named app.js with the following content:

app.js
	
		const express = require('express');
		const mysql = require('mysql2');
		//Add puppeteer library
		const puppeteer = require('puppeteer');
		const app = express();
		const port = 3000;
		app.use(express.json());
		//Serve static files (including index.html) from the root directory
		app.use(express.static(__dirname));
		const database = mysql.createConnection({
			host : 'localhost',
			user : 'root',
			password : '123456789',
			database : 'testing'
		});

		database.connect((error)=> {
			if(error){
				console.error('Error connecting to MySQL : ', error);
			} else{
				console.log('Connected to MySQL database');
			}
		});

		app.get('/data', (request, response) => {
			response.sendFile(__dirname + '/data.html');
		});

		app.post('/getData', (request, response) => {
			database.query('SELECT * FROM sampledata', async (error, results) => {
				response.status(200).json(results);
			});
		});

		app.listen(port, () => {
			console.log(`Server is running on http://localhost:${port}`);   
		});
	

Create a file named data.html with the following content:

	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>How to Convert HTML to PDF in Node.js using Puppeteer</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">How to Convert HTML to PDF in Node.js using Puppeteer</h1>
					<div class="card">
						<div class="card-header">
							<div class="row">
								<div class="col col-6">Sample Data</div>
								<div class="col col-6">
									<a href="/convertPDF" class="btn btn-primary btn-sm float-end">Download in PDF</a>
								</div>
							</div>
						</div>
						<div class="card-body">
							<div class="table-responsive">
								<table class="table table-bordered table-striped">
									<thead>
										<tr>
											<th>Name</th>
											<th>Phone</th>
											<th>Email</th>
											<th>Address</th>
											<th>Zip</th>
											<th>Region</th>
											<th>Country</th>
										</tr>
									</thead>
									<tbody id="dataArea"></tbody>
								</table>
							</div>
						</div>
					</div>
				</div>

				<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
			</body>
		</html>

		<script>
			getData();
			function getData(){
				fetch('/getData', {
					method: 'POST'
				})
				.then(response => {
					return response.json();
				})
				.then(data => {
					if(data.length > 0){
						let html = '';
						for(let i = 0; i < data.length; i++){
							html += `
							<tr>
								<td>${data[i].name}</td>
								<td>${data[i].phone}</td>
								<td>${data[i].email}</td>
								<td>${data[i].address}</td>
								<td>${data[i].postalZip}</td>
								<td>${data[i].region}</td>
								<td>${data[i].country}</td>
							</tr>
							`;
						}
						document.getElementById('dataArea').innerHTML = html;
					}
				})
				.catch(error => {
					// Handle errors
					//console.error(error);
					alert(error);
				});
			}
		</script>
	

Save this code in the root directory of your project.

HTML to PDF Conversion


We'll define a function convertHTMLToPDF in app.js file that takes HTML content as input, converts it to a PDF file using Puppeteer, and opens the generated PDF file.

app.js
	
		async function convertHTMLToPDF(htmlContent, pdfFilePath, margins = {top: '10mm', right: '10mm', bottom: '10mm', left: '10mm'}){
			const browser = await puppeteer.launch();
			const page = await browser.newPage();
			// Set the page content
			await page.setContent(htmlContent);
			// Generate PDF
			await page.pdf({ path : pdfFilePath, format : 'A4', margin : margins });
			// Open the generated PDF file in the default PDF viewer
			const open = await import('open');
			await open.default(pdfFilePath);
			//close the browser
			await browser.close();
		}
	

Serving HTML and Triggering Conversion


Finally, we'll set up routes to fetch data from MySQL table and convert into HTML and serve the HTML data and trigger the conversion to PDF when the user clicks on Download in PDF button.

app.js
	
		app.get('/convertPDF', async (request, response)=>{
			database.query('SELECT * FROM sampledata', async (error, results) => {
				let html = '';
				if(results.length > 0){
					html += `
					<table width="100%" border="1" cellpadding="5" cellspacing="0">
						<tr>
							<th width="20%">Name</th>
							<th width="10%">Phone</th>
							<th width="20%">Email</th>
							<th width="20%">Address</th>
							<th width="10%">Zip</th>
							<th width="10%">Region</th>
							<th width="10%">Country</th>
						</tr>
					`;
					results.map((row)=>{
						html += `
						<tr>
							<th>${row.name}</th>
							<th>${row.phone}</th>
							<th>${row.email}</th>
							<th>${row.address}</th>
							<th>${row.postalZip}</th>
							<th>${row.region}</th>
							<th>${row.country}</th>
						</tr>
						`;
					});
					html += `
					</table>
					`;
				}
				await convertHTMLToPDF(html, 'data.pdf');
			});
		});
	

Running the Server


To run the server, execute the following command:

	
		node app.js
	

Visit http://localhost:3000/data in your web browser to see the sample data table. Click the "Download in PDF" button to convert the HTML table to a PDF file.

Conclusion


Congratulations! You've learned how to convert HTML content to a PDF file in Node.js using Puppeteer. This technique can be useful for generating PDF reports, invoices, or any other printable documents from dynamic HTML content.

Feel free to customize the code to suit your specific requirements and explore additional features offered by Puppeteer for web automation and PDF generation.

Complete Source Code


app.js
	
		const express = require('express');
		const mysql = require('mysql2');
		//Add puppeteer library
		const puppeteer = require('puppeteer');
		const app = express();
		const port = 3000;
		app.use(express.json());
		//Serve static files (including index.html) from the root directory
		app.use(express.static(__dirname));
		const database = mysql.createConnection({
			host : 'localhost',
			user : 'root',
			password : '123456789',
			database : 'testing'
		});

		database.connect((error)=> {
			if(error){
				console.error('Error connecting to MySQL : ', error);
			} else{
				console.log('Connected to MySQL database');
			}
		});

		app.get('/data', (request, response) => {
			response.sendFile(__dirname + '/data.html');
		});

		app.post('/getData', (request, response) => {
			database.query('SELECT * FROM sampledata', async (error, results) => {
				response.status(200).json(results);
			});
		});

		async function convertHTMLToPDF(htmlContent, pdfFilePath, margins = {top: '10mm', right: '10mm', bottom: '10mm', left: '10mm'}){
			const browser = await puppeteer.launch();
			const page = await browser.newPage();
			// Set the page content
			await page.setContent(htmlContent);
			// Generate PDF
			await page.pdf({ path : pdfFilePath, format : 'A4', margin : margins });
			// Open the generated PDF file in the default PDF viewer
			const open = await import('open');
			await open.default(pdfFilePath);
			//close the browser
			await browser.close();
		}

		app.get('/convertPDF', async (request, response)=>{
			database.query('SELECT * FROM sampledata', async (error, results) => {
				let html = '';
				if(results.length > 0){
					html += `
					<table width="100%" border="1" cellpadding="5" cellspacing="0">
						<tr>
							<th width="20%">Name</th>
							<th width="10%">Phone</th>
							<th width="20%">Email</th>
							<th width="20%">Address</th>
							<th width="10%">Zip</th>
							<th width="10%">Region</th>
							<th width="10%">Country</th>
						</tr>
					`;
					results.map((row)=>{
						html += `
						<tr>
							<th>${row.name}</th>
							<th>${row.phone}</th>
							<th>${row.email}</th>
							<th>${row.address}</th>
							<th>${row.postalZip}</th>
							<th>${row.region}</th>
							<th>${row.country}</th>
						</tr>
						`;
					});
					html += `
					</table>
					`;
				}
				await convertHTMLToPDF(html, 'data.pdf');
			});
		});


		app.listen(port, () => {
			console.log(`Server is running on http://localhost:${port}`);   
		});
	

data.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>How to Convert HTML to PDF in Node.js using Puppeteer</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">How to Convert HTML to PDF in Node.js using Puppeteer</h1>
					<div class="card">
						<div class="card-header">
							<div class="row">
								<div class="col col-6">Sample Data</div>
								<div class="col col-6">
									<a href="/convertPDF" class="btn btn-primary btn-sm float-end">Download in PDF</a>
								</div>
							</div>
						</div>
						<div class="card-body">
							<div class="table-responsive">
								<table class="table table-bordered table-striped">
									<thead>
										<tr>
											<th>Name</th>
											<th>Phone</th>
											<th>Email</th>
											<th>Address</th>
											<th>Zip</th>
											<th>Region</th>
											<th>Country</th>
										</tr>
									</thead>
									<tbody id="dataArea"></tbody>
								</table>
							</div>
						</div>
					</div>
				</div>

				<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
			</body>
		</html>

		<script>
			getData();
			function getData(){
				fetch('/getData', {
					method: 'POST'
				})
				.then(response => {
					return response.json();
				})
				.then(data => {
					if(data.length > 0){
						let html = '';
						for(let i = 0; i < data.length; i++){
							html += `
							<tr>
								<td>${data[i].name}</td>
								<td>${data[i].phone}</td>
								<td>${data[i].email}</td>
								<td>${data[i].address}</td>
								<td>${data[i].postalZip}</td>
								<td>${data[i].region}</td>
								<td>${data[i].country}</td>
							</tr>
							`;
						}
						document.getElementById('dataArea').innerHTML = html;
					}
				})
				.catch(error => {
					// Handle errors
					//console.error(error);
					alert(error);
				});
			}
		</script>
	


COMMENTS

Nama

Add,1,Ajax,2,ajax tutorial,1,Ajax with javascript,1,Ajax with node.js,1,application,2,array,1,array to string,1,array to string conversion nodejs,1,array to string in node js,1,array to string nodejs,1,Asynchronous JavaScript,1,authentication,1,authentication node js,1,authorization,1,availability,1,backend,1,bootstrap offcanvas dynamic content,1,bootstrap offcanvas dynamic content node.js,1,bootstrap offcanvas dynamic data,1,bootstrap offcanvas remote dynamic content,1,cart,1,centos 7,1,centos7,1,check,1,contact form node js,1,contact form nodemailer,1,contact us form node,1,conversion,1,create,1,crud,4,crud application,1,crud operation in node js,1,crud operation in node js with mysql,1,CSS,1,data,1,database,1,databases,1,datatables,1,DataTables integration in React.js,1,date range,1,delete,2,download,1,drag &amp; drop,1,drag and drop,1,drag and drop files,1,drag and drop multiple file,1,drag n drop,1,dynamic dropdown in react js,1,dynamic dropdown in react.js,1,ecommerce,2,edit,1,educational project,1,email address,1,email verification,1,email verification using jwt,1,express,3,expressjs,1,fetch,1,file upload,1,file upload in node js,1,files,1,filter,1,Front-end development tutorial,1,Frontend,1,GET,1,how to send email using node js,1,how to send emails in node js,1,html,1,html 2 pdf,1,html to pdf,1,html to pdf node,1,insert,2,insert data in mysql node js,1,Javascript,3,JavaScript tutorial,1,join array nodejs,1,js,1,json,1,jwt,3,jwt authentication,2,jwt authentication node js,1,jwt authentication php,1,jwt email verification,1,jwt login,1,jwt login php,1,jwt php example,1,jwt token,1,jwt token email verification,1,laravel 10,1,laravel 10 tutorial,1,laravel datatables,1,laravel datatables date range filter,1,laravel date filter,1,laravel date range filter,1,last insert id in node,1,learn reactjs,1,linux,1,live,2,live check email address availability,1,live search,1,load more data on click,1,load more data on click javascript,1,load more javscript node.js,1,load more nodejs,1,load more results,1,load more results with node js and ajax,1,login,1,merge 2 arrays in node js,1,merge array in nodejs,1,merge array node,1,merge two array in node js,1,MongoDB,1,mongodb crud,1,mongodb crud operations,1,multer,1,multiple file upload,1,mysql,7,mysql 8,1,mysql tutorial,1,mysql8,1,node,3,node js,8,node js array merge,1,node js array to string,1,node js crud,2,node js crud mysql,1,node js crud operation with mysql,1,node js load more pagination,1,node js mongodb crud,1,node js mysql last insert id,1,node js tutorial,2,node mongodb crud,1,node mysql get last insert id,1,node pdf,1,node.js,8,node.js array,1,node.js crud,1,node.js mysql,1,node.js tutorial,2,nodejs,9,nodejs array,1,nodejs array merge,1,nodejs create pdf,1,nodejs crud,1,nodejs pdf,1,nodejs pdf create,1,nodejs programming,1,offcanvas,1,open source,1,Optimizing web application performance,1,parking management system,1,parking management system in php,1,parking management system project,1,password,1,pdf-creator-node,1,php,3,php jwt authentication example,1,php jwt login,1,php login jwt,1,php parking management system,1,php project,1,PHP server-side processing,1,populate dropdown from database,1,programming tutorial,1,project,1,Puppeteer,1,Puppeteer HTML to PDF,1,React,1,react file upload,1,react js,2,react js dynamic dropdown,1,react js file upload validation,1,react js tutorial,1,react php myql,1,React.js,1,react.js dependent select,1,react.js file upload,1,Reactjs,4,reactJS CRUD,1,reactjs file upload,1,reactjs file upload app,1,reactjs file upload sample code,1,reactjs tutorial,1,read,1,register,1,registration,2,remove,1,request form node,1,reset,1,search,1,select,1,send activation email php,1,sending email using node js,1,server,1,Server-side data processing,1,shopping cart,1,shopping cart in node js,1,shopping cart javascript,1,shopping cart project in javascript,1,shopping cart using node js,1,shopping-cart,1,society management system in php,1,society management system php,1,society management system php source code,1,society management system project in php,1,society management system project php,1,source code,1,string,1,token,2,tutorial,8,update,2,using jwt for email verification,1,vanilla,1,vite,1,vitejs,1,vitejs crud app,1,web development,7,Web development guide,1,webslesson,2,what is jwt authentication,1,
ltr
item
kumpulan driver: Converting Dynamic HTML to PDF in Node.js with Puppeteer
Converting Dynamic HTML to PDF in Node.js with Puppeteer
https://i.ytimg.com/vi/fGC6Ywvu5Jo/hqdefault.jpg
https://i.ytimg.com/vi/fGC6Ywvu5Jo/default.jpg
kumpulan driver
https://kepsuk.blogspot.com/2024/02/converting-dynamic-html-to-pdf-in_20.html
https://kepsuk.blogspot.com/
http://kepsuk.blogspot.com/
http://kepsuk.blogspot.com/2024/02/converting-dynamic-html-to-pdf-in_20.html
true
6399859916032798219
UTF-8
Loaded All Posts Not found any posts VIEW ALL Readmore Reply Cancel reply Delete By Home PAGES POSTS View All RECOMMENDED FOR YOU LABEL ARCHIVE SEARCH ALL POSTS Not found any post match with your request Back Home Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sun Mon Tue Wed Thu Fri Sat January February March April May June July August September October November December Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec just now 1 minute ago $$1$$ minutes ago 1 hour ago $$1$$ hours ago Yesterday $$1$$ days ago $$1$$ weeks ago more than 5 weeks ago Followers Follow THIS PREMIUM CONTENT IS LOCKED STEP 1: Share to a social network STEP 2: Click the link on your social network Copy All Code Select All Code All codes were copied to your clipboard Can not copy the codes / texts, please press [CTRL]+[C] (or CMD+C with Mac) to copy Table of Content