Generate professional PDFs from HTML templates directly in your Microsoft Power Automate flows. Perfect for invoices, receipts, reports, certificates, and any document that requires custom styling and layouts.
📖 Want a complete step-by-step guide? Check out our Power Automate PDF Generation Tutorial with screenshots, QR code examples, and best practices.




What you get:
The action accepts complete HTML documents with embedded CSS and JavaScript. You can:
@font-face or web fonts<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 40px; }
.header { text-align: center; margin-bottom: 30px; }
.invoice-details { margin: 20px 0; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }
</style>
</head>
<body>
<div class="header">
<h1>INVOICE</h1>
<p>Invoice #12345</p>
</div>
<div class="invoice-details">
<p><strong>Bill To:</strong> John Doe</p>
<p><strong>Date:</strong> 2025-01-14</p>
</div>
<table>
<thead>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>Web Development</td>
<td>10 hours</td>
<td>$100</td>
<td>$1,000</td>
</tr>
</tbody>
</table>
<div style="text-align: right; margin-top: 30px;">
<h2>Total: $1,000</h2>
</div>
</body>
</html>
The best practice is to use a Data Operation - Compose action to map your trigger data to clean field names, then reference those fields in your HTML template.
You can use external JavaScript libraries like QRCode.js in your PDF templates. When using ES Modules, wrap your import in a module script tag:
<script type="module">
import QRCode from 'https://cdn.jsdelivr.net/npm/qrcode@1.5.4/+esm';
// Generate QR code
const qrDataUrl = await QRCode.toDataURL('https://example.com', {
width: 150,
margin: 1
});
// Set the image source
document.getElementById('qr').src = qrDataUrl;
</script>
<img id="qr" alt="QR Code" /> When using asynchronous JavaScript (QR codes, charts, API calls), you must signal when your content is ready by setting window.__RENDER_DONE__ = true. The PDF generator waits for this flag before capturing the page.
<script type="module">
import QRCode from 'https://cdn.jsdelivr.net/npm/qrcode@1.5.4/+esm';
// Initialize as false
window.__RENDER_DONE__ = false;
async function generateQR() {
// Your async operations
const qrDataUrl = await QRCode.toDataURL('https://example.com');
document.getElementById('qr').src = qrDataUrl;
// Signal that rendering is complete
window.__RENDER_DONE__ = true;
}
// Start generation
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', generateQR);
} else {
generateQR();
}
</script> ⚠️ Important: Without setting window.__RENDER_DONE__ = true, your PDF may be blank or incomplete because the generator won't wait for async operations to finish!