PDF generation in n8n: every method that works, and what each one costs you

27 August 2026 · five methods, tested · updated when they change

n8n cannot render a PDF on its own. There is no rendering engine inside it — the Convert to File node produces JSON, CSV, text, XML, base64 and iCal, and none of those involve drawing a page. Every working approach therefore brings the rendering from somewhere else, and the five ways of doing that differ enormously in what they cost you.

This page covers all five, including the free ones that compete with us. We sell one of them; it is marked. If your case fits a free method better, use the free method — you will find that out here rather than after a month of paying for something you did not need.

The five methods at a glance

MethodMoneyn8n CloudLayout controlReal cost
Google Docs or Slides Free Yes Low Fights you the moment layout gets specific
Gotenberg, self-hosted Free Only if reachable over HTTP Full A container to run and keep alive
Code node with a JS library Free No Medium Needs external modules enabled; no real browser
Community node Varies No Full Installation, and Cloud users are excluded
HTTP Request to an API Free tier to paid Yes Full Money, and a third party in the pipeline

1. Google Docs or Slides as a template

Make a document with placeholders, copy it per run, replace the text, export as PDF. Entirely inside the Google nodes, no extra service, no cost.

Use it when the document is mostly prose with a few variables — a letter, a simple statement, a one-page summary — and nobody will ask for a design change next quarter.

Where it stops. Precise tables, repeating headers across pages, exact fonts, page numbering, anything that has to match a brand: the Docs API was not built for layout control, and each of those turns into a fight. Teams usually start here, ship, and move when someone asks for a proper invoice.

2. Gotenberg, self-hosted

Gotenberg wraps Chromium and LibreOffice behind an HTTP interface. Free, open source, and genuinely good — this is the honest first choice if you already run infrastructure.

docker run --rm -p 3000:3000 gotenberg/gotenberg:8

From n8n, an HTTP Request node posting multipart/form-data to /forms/chromium/convert/html, with your HTML as a file field named index.html.

What it costs is not the licence, it is the operation. Roughly a gigabyte of image, a container to patch, memory to allocate, and the Sunday you discover a font is missing inside it. If you already run containers with monitoring and backups, that marginal cost is near zero and you should stop reading. If this would be the only container you run, you have just adopted a small server to avoid a small bill.

3. Code node with a JavaScript library

Libraries like pdf-lib or pdfmake build a PDF programmatically, without a browser. On self-hosted n8n you can allow external modules and call them from a Code node.

Use it when the document is generated rather than designed — a label, a barcode sheet, a fixed-format report where you place elements by coordinate.

Where it stops. There is no browser, so there is no CSS. You are positioning elements, not styling a page, and a designer cannot help you. On n8n Cloud it is not available at all, because you cannot enable external modules.

4. Community node

Several vendors publish dedicated nodes. They install cleanly and give you a proper node in the editor.

Community nodes only install on self-hosted n8n. If you are on Cloud, this method does not exist for you — and it is worth knowing that the vendors who chose this route made themselves unavailable to every Cloud user in the process.

We counted what people actually ship. Across 382 workflows in the public n8n template library that produce a document or an image, there are 3,650 node instances and zero community nodes. Every one uses the built-in HTTP Request. That is not a verdict on quality — it is what happens when a workflow has to survive being exported and imported by someone else.

5. HTTP Request to a rendering API what we sell

The node ships with n8n, so it runs on Cloud and self-hosted, and anyone can import your workflow and use it without installing anything. You post the HTML and the data, you get a file back.

The response carries a signed URL, which goes straight into a Drive, S3, Gmail or Slack node. Full detail in the HTTP Request guide.

What it costs is money and a dependency on someone else's uptime. There are many vendors; we are one of them, we are new, and we say so further down.

Which one fits your case

If this is youStart with
Simple document, mostly text, and you already use Google WorkspaceGoogle Docs
You run containers already, and want zero recurring costGotenberg
Fixed-format output placed by coordinate, self-hostedCode node with a library
You are on n8n Cloud and need real CSS layoutAn API — the other options are closed to you
The workflow will be shared or handed to someone elseHTTP Request, so nothing needs installing
Contracts or invoices at volume for a regulated businessAn established vendor with an SLA and a signed DPA

What breaks in every method, and how to fix it

These apply whichever renderer you pick, because they are properties of print layout rather than of any product.

Table headers vanish after page one

thead { display: table-header-group; }

Chromium then repeats the header on every page. Almost nobody sets this, and it is the single most common complaint about generated invoices.

Rows get cut in half at the page break

tr, .keep-together { break-inside: avoid; }
.new-page { break-before: page; }

The font is wrong on the server

The rendering machine does not have your local fonts. Linking a font CDN is worse than it looks: every render then waits on the network, and that wait counts against whatever timeout your method has. Embed as a data URI and the problem disappears permanently.

Margins fight each other

Set @page { margin: 0 } and control spacing with your own body padding. Mixing a renderer's margin option with CSS margins produces a file that looks right in the browser and wrong on paper.

Returning the file from a Webhook

Use a Respond to Webhook node in Binary mode, fed by an HTTP Request with Response Format: File. Or return the JSON with the URL, which is usually better: smaller response, no held-open connection, and the caller fetches the file when it suits them.

If method 5 is the one

emitforge takes an HTML template plus JSON and returns a signed URL to a finished PDF. Real Chromium, so the CSS you tested in the browser is the CSS that renders. 100 renders a month free, no card. Limits published: 10-second timeout, 2 MB template, 10 requests per second, files deleted after 24 hours.

Get a key   Read the docs

Where we are weaker, so you hear it from us: we are new and run by one person. One endpoint, no template editor, no asynchronous rendering, no SLA, no signed DPA. Other vendors have several of those and years of operation behind them. For a regulated business generating contracts at scale, that matters more than the price difference.

Questions

How do I generate a PDF in n8n?

There is no native node that renders one. You pick one of five routes: Google Docs or Slides as a template, self-hosted Gotenberg, a JavaScript library in a Code node, a community node, or an HTTP Request to a rendering API. On n8n Cloud only the first, second and fifth are available.

Is there a free way to generate PDFs in n8n?

Yes, two. Google Docs or Slides as a template costs nothing and works well for simple documents. Self-hosting Gotenberg is free and open source and gives full CSS control, in exchange for running a container.

Does n8n have a PDF node?

Not for generating one. Convert to File handles JSON, CSV, text, XML, base64 and iCal, and Extract from File reads text out of an existing PDF. Neither renders HTML into a document.

Can I use a community PDF node on n8n Cloud?

No. Community nodes install only on self-hosted instances. On Cloud your options are Google Docs, a self-hosted renderer reachable over HTTP, or an API through the built-in HTTP Request node.

Why does my generated PDF look different from the browser?

Fonts or page rules, nearly always. The rendering machine lacks your local fonts, and print layout obeys @page, break-inside and display: table-header-group — none of which you see on screen.

How do I generate a PDF from a template in n8n?

Keep the template out of the request body once it grows: put the HTML in a Set node, or build it in a Code node when rows repeat, and reference it from the HTTP Request. Inline HTML inside an expression becomes unreadable and hard to debug quickly.

Related guides