DEV Community

Cover image for Generate PDFs from HTML with an API
APIVerve
APIVerve

Posted on • Originally published at blog.apiverve.com

Generate PDFs from HTML with an API

Every application eventually needs to generate PDFs. Invoices that accountants can file. Reports that executives can print. Receipts that customers can download. Certificates that recipients can frame. The format matters because PDFs preserve exact layout across every device and printer.

The traditional approach to PDF generation involves installing libraries, managing system dependencies, and learning layout APIs that have nothing to do with how you build the rest of your application. Headless browsers are an option but require infrastructure to run browser instances.

The simpler approach: write HTML, send it to an API, receive a PDF. Your existing CSS skills work. Your existing templating works. No binary dependencies to install or browser processes to manage.

Why HTML Works for PDFs

HTML and CSS were designed for document layout. Before the web, they were literally specification languages for formatting printed pages. The print stylesheet (@media print) exists precisely because browsers have always known how to render documents for paper.

This makes HTML a natural fit for PDF generation. You're not learning a new layout system—you're using the one you already know. Flexbox works. Grid works. Custom fonts work. Background colors, borders, tables—all of it translates directly.

The only adjustments involve thinking in fixed dimensions instead of responsive ones. A PDF has a specific page size. Content needs to fit within margins. Page breaks should fall in sensible places. These constraints exist in CSS already; most developers just haven't used them.

Common PDF Use Cases

Understanding what you're generating helps you design better templates.

Invoices need to be legally compliant documents. They require specific information: seller details, buyer details, line items, totals, tax breakdowns, payment terms. The layout should be clean and professional because customers will see these. Many will file them for accounting purposes.

Reports present data with context. They often include charts, tables, and explanatory text. Reports tend to be longer than other documents and may need headers, footers, and page numbers. The audience is usually internal—executives, analysts, stakeholders reviewing information.

Receipts are transactional records. They're typically short, confirming what was purchased, when, and for how much. Some receipts need to look like traditional paper receipts (monospace font, narrow width). Others can be more designed.

Certificates are ceremonial documents. Completion certificates, awards, diplomas—these are meant to be displayed or framed. They use formal typography, borders, and careful spacing. Landscape orientation is common.

Each type has different design priorities. Invoices prioritize clarity and compliance. Reports prioritize information density. Receipts prioritize scannability. Certificates prioritize aesthetics.

Designing for Print

Web design assumes infinite vertical space and varying horizontal space. Print design assumes fixed dimensions on both axes. This shift requires a few adjustments.

Page size matters. Letter (8.5" × 11") is standard in the US. A4 (210mm × 297mm) is standard elsewhere. Your PDF needs to target a specific size, and content must fit within it. Design your templates with these constraints in mind.

Margins create breathing room. Print documents need margins—both for readability and because most printers can't print to the edge. Half-inch margins are a reasonable default. Formal documents might use one-inch margins.

Page breaks need control. A table split awkwardly between pages looks unprofessional. CSS provides page-break-before, page-break-after, and page-break-inside properties to control where breaks occur. Use page-break-inside: avoid on elements that shouldn't be split.

Colors print differently. That vibrant blue on screen might look washed out on paper. If documents will be printed frequently, test your colors on actual paper. Consider offering a "print-optimized" version with higher contrast.

Template Architecture

Separate your PDF templates from your application logic. Templates should be pure HTML with placeholder tokens that your code fills in before generation.

This separation provides several benefits. Designers can modify templates without touching application code. Templates can be version-controlled independently. The same template can generate different documents by passing different data.

A template for an invoice might have placeholders like {{customer_name}}, {{line_items}}, and {{total}}. Your code retrieves the order data, fills in the placeholders, and sends the completed HTML for PDF generation.

Keep templates simple. Complex logic in templates becomes hard to maintain and debug. If a template needs conditional sections or loops, handle that logic before the template receives the data.

Embedding Images and Fonts

PDFs often need images—logos, signatures, charts. You have two options for embedding images in HTML that becomes a PDF.

External URLs work if the images are publicly accessible. The PDF generation service fetches them during rendering. This is simplest but requires public hosting for your images.

Base64 encoding embeds the image directly in the HTML. The image travels with the HTML, requiring no external fetch. This is more self-contained but increases the HTML payload size.

For logos and standard branding elements that appear on every document, base64 encoding makes sense. For dynamic content like charts or user-uploaded images, external URLs are more practical.

Custom fonts work similarly. Reference them via Google Fonts or another CDN, or embed them as base64. Standard web fonts like Arial, Georgia, and Courier are always available.

Page Layouts

Different document types call for different layouts.

Portrait orientation (tall) is the default and works for most documents. Invoices, letters, receipts, and most reports use portrait.

Landscape orientation (wide) suits documents with wide tables or horizontal content. Financial spreadsheets, Gantt charts, and certificates often work better in landscape.

Multi-column layouts can fit more content per page. Newsletters and some reports use two or three columns. CSS columns or Grid make this straightforward.

Headers and footers provide consistent information across pages. Page numbers, document titles, dates, and company logos commonly appear in headers or footers. CSS has @page rules for controlling headers and footers, though support varies.

Handling Long Content

Some documents span many pages. Reports with extensive data, contracts with many sections, or invoices with hundreds of line items all need to handle pagination gracefully.

The key is controlling where page breaks occur. You don't want a page break in the middle of a table row or between a heading and its first paragraph. CSS page break properties let you specify that certain elements should stay together.

For very long tables, consider repeating the header row on each page. This makes the document usable even when printed—readers don't have to flip back to see what each column represents.

Test your templates with maximum-length content. If your invoice template works fine with 5 line items but breaks horribly with 50, you'll find out at the worst possible time.

Storage and Delivery

Generated PDFs need to go somewhere. The generation API provides a temporary download URL, but that URL expires. For documents you need to keep, download the PDF and store it in your own system.

Cloud storage (S3, Google Cloud Storage, Azure Blob Storage) is the typical choice. Store PDFs with organized paths: /invoices/2026/03/INV-001234.pdf. This makes retrieval and cleanup straightforward.

For immediate delivery (user clicks "Download Invoice"), you can stream the PDF directly from the generation API. For background generation (nightly reports, batch invoicing), generate the PDFs, store them, and email links to recipients.

Generation Example

The actual API call is minimal. Prepare your HTML, send it, receive a PDF:

const response = await fetch('https://api.apiverve.com/v1/htmltopdf', {
  method: 'POST',
  headers: {
    'x-api-key': 'YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    html: invoiceHtml,
    landscape: false,
    marginTop: 0.5,
    marginBottom: 0.5
  })
});

const { data } = await response.json();
// data.downloadURL contains the PDF
Enter fullscreen mode Exit fullscreen mode

Most of the work is in preparing the HTML. The generation itself is a single API call.

Performance Considerations

PDF generation isn't instant. Complex documents with many images or large tables take longer to render. Plan for this in your user experience.

For user-initiated generation (clicking a download button), show a loading indicator. Generation typically takes 1-5 seconds depending on complexity.

For bulk generation (monthly invoice runs, batch reports), process documents in parallel but respect rate limits. Consider running batch jobs during off-peak hours.

Cache generated PDFs when the underlying data won't change. An invoice for order #12345 will always contain the same information. Generate it once and serve the cached version on subsequent requests.


Generate PDFs from HTML with the HTML to PDF API. Convert Markdown with the Markdown to PDF API. Capture entire websites with the Website to PDF API. Build document workflows without the infrastructure headaches.


Originally published at APIVerve Blog

Top comments (0)