Generate PDFs and Images with Puppeteer: From Beginner to Production

Imagine this: you need to generate weekly sales report PDFs or automatically create images for social media. Manual work is too tedious? Let Puppeteer help you!
What is Puppeteer?
Puppeteer is like a "headless" Chrome browser that you can control with code. What can it do?
- 📄 Convert web pages to PDF
- 📸 Take screenshots of web pages
- 🤖 Automate testing
- 📊 Generate reports
Best of all, it's completely free and maintained by Google!
💡 Quick Tip: If you need a simpler solution and don't want to handle server deployment and maintenance, consider using BulkDesign API. It provides ready-made templates and cloud rendering services, letting you focus on business logic rather than technical implementation.
Quick Start
Installing Puppeteer
# Create new project
mkdir my-pdf-generator
cd my-pdf-generator
npm init -y
# Install Puppeteer
npm install puppeteer
Installation will automatically download Chrome, so it might take a few minutes.
First Example: Web Page to PDF
Create generate-pdf.js
file:
const puppeteer = require('puppeteer');
async function createPDF() {
// Launch browser
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Navigate to webpage
await page.goto('https://www.google.com');
// Generate PDF
await page.pdf({
path: 'my-first-pdf.pdf',
format: 'A4'
});
// Close browser
await browser.close();
console.log('PDF generation complete!');
}
createPDF();
Run it:
node generate-pdf.js
That's it! Your first PDF is generated.
Practical PDF Generation Tips
1. Custom PDF Styling
async function createStyledPDF() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://your-website.com');
await page.pdf({
path: 'styled-report.pdf',
format: 'A4',
printBackground: true, // Include background colors
margin: {
top: '20px',
right: '20px',
bottom: '20px',
left: '20px'
},
// Add header and footer
displayHeaderFooter: true,
headerTemplate: '<div style="font-size:10px; text-align:center; width:100%;">My Report</div>',
footerTemplate: '<div style="font-size:10px; text-align:center; width:100%;">Page <span class="pageNumber"></span></div>'
});
await browser.close();
}
2. HTML Content to PDF
Don't want to generate from web pages? Use HTML content directly:
async function htmlToPDF() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
const htmlContent = `
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.header { color: #333; border-bottom: 2px solid #007acc; }
.content { margin-top: 20px; line-height: 1.6; }
</style>
</head>
<body>
<div class="header">
<h1>Monthly Sales Report</h1>
<p>Generated on: ${new Date().toLocaleDateString()}</p>
</div>
<div class="content">
<h2>This Month's Highlights</h2>
<ul>
<li>Sales increased by 25%</li>
<li>150 new customers</li>
<li>98% customer satisfaction</li>
</ul>
</div>
</body>
</html>
`;
await page.setContent(htmlContent);
await page.pdf({
path: 'sales-report.pdf',
format: 'A4',
printBackground: true
});
await browser.close();
console.log('Sales report generated!');
}
Web Screenshots Made Easy
1. Basic Screenshots
async function takeScreenshot() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Set page size
await page.setViewport({ width: 1200, height: 800 });
await page.goto('https://www.google.com');
// Take screenshot
await page.screenshot({
path: 'screenshot.png',
fullPage: true // Capture entire page
});
await browser.close();
console.log('Screenshot complete!');
}
2. Capture Specific Elements
async function captureElement() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://your-dashboard.com');
// Wait for element to load
await page.waitForSelector('.chart-container');
// Capture only the chart section
const element = await page.$('.chart-container');
await element.screenshot({ path: 'chart.png' });
await browser.close();
}
3. Generate Social Media Images
async function createSocialImage() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Set Twitter image dimensions
await page.setViewport({ width: 1200, height: 675 });
const htmlContent = `
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
background: linear-gradient(45deg, #667eea, #764ba2);
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
font-family: Arial, sans-serif;
color: white;
}
.container {
text-align: center;
padding: 40px;
}
h1 { font-size: 48px; margin-bottom: 20px; }
p { font-size: 24px; opacity: 0.9; }
</style>
</head>
<body>
<div class="container">
<h1>🚀 New Feature Launch</h1>
<p>Tools that make work more efficient</p>
</div>
</body>
</html>
`;
await page.setContent(htmlContent);
await page.screenshot({
path: 'social-media.png',
type: 'png'
});
await browser.close();
}
🎨 Designer-Friendly Alternative: If you frequently need to generate social media images, try BulkDesign's template system. You can design templates in a visual editor, then batch generate personalized images via API without writing complex HTML/CSS code.
Real-World Application Scenarios
1. Automated Report System
const express = require('express');
const app = express();
app.get('/generate-report/:userId', async (req, res) => {
try {
const userId = req.params.userId;
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Visit user-specific report page
await page.goto(`https://your-app.com/report/${userId}`);
// Wait for data to load
await page.waitForSelector('.report-ready');
const pdf = await page.pdf({ format: 'A4' });
await browser.close();
res.setHeader('Content-Type', 'application/pdf');
res.send(pdf);
} catch (error) {
res.status(500).send('Report generation failed');
}
});
app.listen(3000, () => {
console.log('Report service started on port 3000');
});
2. Batch Processing
async function batchGenerate(urls) {
const browser = await puppeteer.launch();
for (let i = 0; i < urls.length; i++) {
const page = await browser.newPage();
try {
await page.goto(urls[i]);
await page.pdf({
path: `report-${i + 1}.pdf`,
format: 'A4'
});
console.log(`PDF ${i + 1} generation complete`);
} catch (error) {
console.log(`PDF ${i + 1} generation failed:`, error.message);
}
await page.close();
}
await browser.close();
console.log('All PDFs generated!');
}
// Usage example
const reportUrls = [
'https://example.com/report/1',
'https://example.com/report/2',
'https://example.com/report/3'
];
batchGenerate(reportUrls);
âš¡ Batch Processing Optimization: For large-scale batch processing, BulkDesign API provides dedicated batch rendering endpoints and asynchronous processing capabilities. You can submit multiple tasks at once and receive completion notifications via webhooks, avoiding long waits and timeout issues.
Common Problem Solutions
1. Chinese Font Issues
// When using in Docker, need to install Chinese fonts
const browser = await puppeteer.launch({
args: ['--font-render-hinting=none']
});
// Or specify fonts in HTML
const htmlWithChineseFont = `
<style>
body {
font-family: "Microsoft YaHei", "SimHei", sans-serif;
}
</style>
`;
2. Waiting for Content to Load
async function waitForContent() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://dynamic-content-site.com');
// Wait for specific element to appear
await page.waitForSelector('.data-loaded');
// Or wait for network idle
await page.goto(url, { waitUntil: 'networkidle2' });
await page.pdf({ path: 'complete-content.pdf' });
await browser.close();
}
3. Memory Optimization
// For heavy processing, remember to clean up promptly
async function optimizedGeneration() {
const browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
try {
// Your processing logic
const page = await browser.newPage();
// ... processing code
await page.close(); // Remember to close pages
} finally {
await browser.close(); // Ensure browser closes
}
}
Production Deployment
Docker Configuration
FROM node:16-slim
# Install Chrome dependencies
RUN apt-get update \
&& apt-get install -y wget gnupg \
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
&& apt-get update \
&& apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
CMD ["node", "server.js"]
🚀 Maintenance-Free Cloud Solution: If you don't want to handle Docker deployment, server maintenance, and scaling issues, you can directly use BulkDesign Cloud API. We've handled all the infrastructure, you just need to call the API to get high-quality rendering results.
Summary
Puppeteer makes PDF and image generation super simple:
✅ Easy Installation: One command to get started ✅ Powerful Features: PDF, screenshots, automation all possible ✅ Highly Customizable: Styles and dimensions as you wish ✅ Production Ready: Maintained by Google, stable and reliable
Choose the Right Solution
Choose Puppeteer if you:
- Need complete control over the rendering process
- Have complex custom requirements
- Are willing to handle server deployment and maintenance
Choose BulkDesign API if you:
- Want to get started quickly and focus on business logic
- Need visual template design tools
- Want to avoid server operations work
- Need batch processing and asynchronous rendering
Next Steps
- Start Simple: Try basic PDF generation first
- Gradually Optimize: Add styling and error handling
- Expand Applications: Combine with your business scenarios
- Performance Tuning: Pay attention to memory management when processing large amounts of data
Start your automation journey now! Check the Puppeteer official documentation for questions or try BulkDesign free templates.
Related Resources:
- Puppeteer Official Documentation
- More Code Examples
- Performance Optimization Guide
- BulkDesign API Documentation
- Template Management API
Quick Experience: Want to immediately experience automated image generation? Try this simple API call:
curl -X POST https://api.bulkdesign.app/render/template \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "demo-template",
"format": "png",
"jsonData": {
"headline.content": "Your First Automated Image!"
}
}'
Ready to automate your work? Start coding! 🚀