Building a PDF feature?
Save this to your Work Desktop.

Back to Resources
TutorialPythonNode.jsEngineering

How to Generate PDFs from HTML using Python and Node.js

The Hard Way: Building a Microservice

If you are building a PDF generator in 2025, the standard is Headless Chrome via Playwright or Puppeteer.

Python Setup

from playwright.sync_api import sync_playwright def generate_pdf(url): with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page() page.goto(url) # ... wait for network idle ... page.pdf(path="invoice.pdf") browser.close()

It looks simple, but in production, it's a nightmare. Before you commit to this path, make sure you grab a print-optimized HTML template to test with—standard web pages often break when printing.

The Hidden Costs of Self-Hosting

After processing thousands of PDFs, here is what you will encounter (as detailed in our Cost Comparison Guide):

  1. Memory Leaks: Chrome is a RAM hog. A single instance can consume 1GB+. If you don't manage the browser lifecycle perfectly, your server will OOM (Out of Memory) and crash.
  2. Zombie Processes: "Orphaned" chrome processes often linger after a crash, slowly eating up CPU until the server freezes.
  3. Font Rendering: deploying to Linux/Docker? Good luck. You'll spend hours debugging why emojis are squares or why "Helvetica" looks like "Times New Roman" (hint: you need to install font packages in your Dockerfile).
  4. The 50MB Limit: If you are deploying to Vercel or AWS Lambda, Headless Chrome (150MB+) literally won't fit in the deployment package.

Is it worth maintaining this? Check the hidden costs of self-hosting Puppeteer to see the numbers.

The Solution: Hosted API

We built pdfmyhtml to solve exactly these engineering headaches.

New: Don't mix HTML and Python

Don't want to mix HTML f-strings in your Python code? We recently added native Jinja2 support. Instead of building strings, you can store your templates in our dashboard and just send the JSON data. Learn about our hosted Jinja2 engine.

Node.js Example (Using API)

const res = await fetch('https://api.pdfmyhtml.com/v1/html-to-pdf', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': 'YOUR_KEY' }, body: JSON.stringify({ html: '<h1>Hello World</h1>' }) });

Result: 0% CPU usage on your server, perfect PDFs every time.

Ready to build?

Stop fighting with PDFs. Start shipping.