How to Generate a PDF Invoice from HTML in Node.js (10 Lines of Code)
Skip the PDF library. Generate pixel-perfect PDF invoices from HTML templates using a single API call — works in any language, no headless browser to manage.
PDF libraries are a tax on developer time. You install one, fight the layout engine, discover it doesn't support your CSS, and spend a day rebuilding your invoice template in a proprietary DSL. There's a better way.
If your invoice already exists as HTML — or you can render it to HTML — you can turn it into a print-perfect PDF with a single API call.
The approach
PageBolt's /v1/pdf endpoint takes a URL or raw HTML and returns a PDF. It renders in a real browser, so your CSS grid, custom fonts, and @media print styles all work exactly as expected.
const fs = require('fs');
const html = `<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Inter, sans-serif; padding: 48px; color: #111; }
.header { display: flex; justify-content: space-between; margin-bottom: 48px; }
.amount { font-size: 32px; font-weight: 700; }
table { width: 100%; border-collapse: collapse; }
td, th { padding: 12px 0; border-bottom: 1px solid #eee; text-align: left; }
.total { font-weight: 700; font-size: 18px; }
</style>
</head>
<body>
<div class="header">
<div><strong>Acme Corp</strong><br>123 Main St, San Francisco CA</div>
<div>Invoice #1042<br>Due: March 15, 2026</div>
</div>
<table>
<tr><th>Item</th><th>Qty</th><th>Price</th></tr>
<tr><td>Pro Plan — March</td><td>1</td><td>$99.00</td></tr>
<tr><td>Extra seats (3)</td><td>3</td><td>$45.00</td></tr>
<tr><td class="total" colspan="2">Total</td><td class="total">$144.00</td></tr>
</table>
</body>
</html>`;
const response = await fetch('https://api.pagebolt.dev/v1/pdf', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ html, format: 'A4', printBackground: true })
});
fs.writeFileSync('invoice-1042.pdf', Buffer.from(await response.arrayBuffer()));
That's the complete implementation. The PDF is written to disk. Swap in your real template and you're done.
Passing a URL instead of raw HTML
If your app already renders invoices at a URL (e.g., /invoices/1042), pass the URL directly:
body: JSON.stringify({
url: 'https://yourapp.com/invoices/1042',
format: 'A4',
printBackground: true
})
PageBolt will fetch and render the page. For pages behind authentication, pass cookies:
body: JSON.stringify({
url: 'https://yourapp.com/invoices/1042',
cookies: ['session=abc123; Domain=yourapp.com'],
format: 'A4',
printBackground: true
})
Print-specific styling
Use @media print in your CSS to hide UI chrome (nav, buttons, banners) from the PDF:
@media print {
nav, .sidebar, .no-print { display: none; }
body { padding: 0; }
}
PageBolt renders with mediaType: "print" by default for PDF generation, so these rules apply automatically.
Margins and page format
body: JSON.stringify({
html,
format: 'Letter', // A4, Letter, Legal, A3, A5
margin: '1in', // all sides, or { top: '1in', bottom: '0.5in', ... }
printBackground: true // include background colors/images
})
Letter and A4 are the most common. Set margin to '0' if your HTML template already includes its own padding.
No PDF library. No Puppeteer setup. No Docker container to maintain. One fetch call, one file on disk.
Try it free
100 requests/month, no credit card. Generate your first PDF invoice in under 5 minutes.
Get API Key — Free