PDF Generation April 5, 2026

Automated PDF Generation: From HTML Templates to Production

A practical guide to building PDF generation pipelines using HTML templates and browser-based rendering APIs. Covers invoices, reports, certificates, and how to scale to thousands of documents per day.

Why HTML-to-PDF?

Every application eventually needs to generate PDFs — invoices, receipts, reports, contracts, certificates, shipping labels. The two traditional approaches are PDF libraries that construct documents programmatically (like PDFKit, ReportLab, or iTextSharp) and HTML-to-PDF converters that render an HTML page and print it to PDF.

PDF libraries give you pixel-level control but require learning a separate layout system. Positioning text, drawing lines, inserting images — every element is placed manually with coordinates. Changes to document design require code changes, and the code is often verbose and difficult to maintain.

HTML-to-PDF converters let you design documents using familiar web technologies. Your frontend team creates the template with HTML and CSS. Your backend renders the template with dynamic data and converts it to PDF. Design changes require only HTML edits, not code changes. This separation of concerns makes HTML-to-PDF the preferred approach for most teams.

Designing Templates for Print

HTML templates designed for PDF output need different considerations than web pages designed for screens. Use CSS @page rules to set page dimensions and margins. The page-break-before and page-break-after properties control where content splits across pages — preventing tables from breaking mid-row and keeping section headings attached to their content.

Fixed-width layouts work better than fluid layouts for PDF output. Set a fixed container width that matches your target page size minus margins — for A4 with 15mm margins on each side, that is approximately 180mm or 680px at 96 DPI. This ensures consistent rendering regardless of the viewport size used during conversion.

Web fonts render in PDFs when the browser has time to download them. SnapAPI waits for font loading to complete before generating the PDF, ensuring your branded typography appears correctly. Self-hosted fonts, Google Fonts, and Adobe Fonts all work without configuration changes.

Building an Invoice Generation Pipeline

A typical invoice pipeline has four components: a data source (your billing system or database), an HTML template engine (Jinja2, Handlebars, EJS, or Blade), a web server that renders the template with dynamic data, and a PDF conversion API that captures the rendered page.

The flow works like this: your billing system triggers an invoice event with line items, customer details, and payment terms. Your backend renders the HTML template with this data at a unique URL — for example, /invoices/render/INV-2026-001. The backend calls SnapAPI's /v1/pdf endpoint with that URL. SnapAPI renders the page in Chromium and returns a PDF. Your backend stores the PDF and emails it to the customer.

This architecture cleanly separates concerns. Designers edit HTML and CSS templates. Backend developers handle data flow and business logic. The PDF conversion layer requires zero custom code — it is a single API call.

For templates that should not be publicly accessible, serve them on a private route or local network address and pass custom headers for authentication. SnapAPI forwards any custom headers you specify to the target URL during rendering.

Scaling to Thousands of PDFs per Day

Small-scale PDF generation — fewer than 100 documents per day — runs comfortably as synchronous API calls within your request handlers. Beyond that, blocking web requests on PDF generation adds latency and ties up server resources. Move to an async queue-based architecture.

Push PDF generation jobs to a message queue — Redis with BullMQ for Node.js, Celery with Redis for Python, or SQS for AWS-native stacks. Worker processes pull jobs from the queue, call SnapAPI, and store the resulting PDFs. This decouples PDF generation from your web server and allows you to scale workers independently based on queue depth.

For maximum throughput, send concurrent API calls from each worker. SnapAPI processes requests in parallel across its browser pool. A single worker sending 5 concurrent requests can generate 5 PDFs simultaneously rather than waiting for each one to complete before starting the next.

The webhook_url parameter provides an alternative async pattern. Instead of polling for completion, SnapAPI pushes the result to your endpoint when the PDF is ready. This eliminates the need for long-running worker processes — a serverless function can initiate the request and another function handles the webhook callback.

Headers, Footers, and Page Numbers

Professional documents require consistent headers and footers across every page: company logo, document title, page numbers, and confidentiality notices. SnapAPI's PDF endpoint supports custom header and footer HTML templates that are rendered on every page of the output.

Chromium's built-in template variables — pageNumber and totalPages — inject dynamic page numbering. Combined with inline CSS in the header or footer template, you can position elements precisely: a logo on the left, document title centered, and page number on the right.

Why SnapAPI for PDF Generation?

wkhtmltopdf is outdated and renders modern CSS incorrectly. Running Puppeteer yourself requires managing browser processes, memory limits, and crash recovery. Prince XML is expensive and requires a per-server license. WeasyPrint renders only a subset of CSS and struggles with complex layouts.

SnapAPI uses the same Chromium engine as Puppeteer but manages the infrastructure for you. The rendering quality is identical — your HTML prints to PDF exactly as it would from Chrome's print dialog. No browser to install, no process to manage, no memory to monitor.

Start free at snapapi.pics — 200 PDF conversions per month, no credit card required. Starter at $19/month for 5,000, Pro at $79/month for 50,000, Business at $299/month for 500,000.

Testing and Optimizing PDF Output

Preview your HTML templates in Chrome's print dialog during development — the output will closely match what SnapAPI produces since both use the same Chromium print engine. Check page breaks, font rendering, image positioning, and margin alignment before sending to the API.

For automated testing, generate a PDF from your template with known data and verify the file size, page count, and text content programmatically. Python's PyMuPDF library extracts text from PDFs for assertion in your test suite. This catches template regressions before they reach production.

Optimize PDF file size by using JPEG compression for embedded images rather than PNG. Set print_background: false if background colors and images are not essential — this significantly reduces file size for text-heavy documents like contracts and terms of service.

Store generated PDFs in object storage (S3, GCS, R2) with a structured key scheme: invoices/2026/04/INV-2026-001.pdf. Set lifecycle policies to archive or delete old documents based on your retention requirements.

Multi-Language Examples

The PDF endpoint works identically from any language. A Python example using requests takes five lines: import requests, set headers with your API key, post to the endpoint with URL and format parameters, parse the JSON response, and retrieve the PDF URL. Node.js with fetch is equally concise. Go uses the standard net/http package. PHP uses file_get_contents or Guzzle.

Official SDKs for 8 languages simplify integration further. The JavaScript SDK (snapapi-js on npm) provides typed methods for every endpoint. The Python SDK wraps requests with proper error handling and retry logic. Install via your package manager and call snapapi.pdf(url, options).

Edge Cases in PDF Generation

Pages with overflow: hidden on the body element may truncate content in PDF output. Override this with custom CSS: body { overflow: visible !important; }. Similarly, pages that use viewport-relative units (vh, vw) for layout may render differently in the print context where the viewport is the page size rather than the screen.

Interactive elements like dropdown menus, accordions, and tab panels require JavaScript injection to expand before capture. Use the custom_js parameter to trigger click events on the elements that need expanding, then add a short delay to allow transition animations to complete before the PDF renders.

Right-to-left language support works natively — set dir="rtl" on your HTML template and Chromium renders Arabic, Hebrew, and other RTL text correctly in the PDF output without any API-specific configuration.

Conclusion

Automated PDF generation with HTML templates and a browser-based API is the most maintainable approach for most teams. Designers work in HTML and CSS, backend developers handle data and routing, and the conversion layer requires zero custom code beyond a single API call. This clean separation of concerns scales from a handful of invoices to thousands of documents per day.

SnapAPI handles the Chromium rendering infrastructure so your team focuses on document design and business logic. Start free at snapapi.pics and generate your first PDF in under five minutes.

Automated PDF generation pipeline converts HTML templates to production quality documents.