Markdown & HTML to PDF — TOC, Headers, Page Numbers avatar

Markdown & HTML to PDF — TOC, Headers, Page Numbers

Pricing

from $5.60 / 1,000 pdf page rendereds

Go to Apify Store
Markdown & HTML to PDF — TOC, Headers, Page Numbers

Markdown & HTML to PDF — TOC, Headers, Page Numbers

PDF generator: turn Markdown or HTML into print-ready PDFs with automatic table of contents, headers, footers and page numbers, A4/Letter, Cyrillic-ready fonts and PDF/A-3b. Runs offline, no browser needed. Pay only per rendered page.

Pricing

from $5.60 / 1,000 pdf page rendereds

Rating

0.0

(0)

Developer

Andrew Boiko

Andrew Boiko

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

40 minutes ago

Last modified

Categories

Share

Turn Markdown or HTML into print-ready, paginated PDFs — with an automatic table of contents that shows real page numbers, headers and footers (Page 3 of 12), A4 / Letter / A5 / Legal pages, five built-in templates, Cyrillic and Latin-extended fonts included, and optional PDF/A-3b with embedded files (for example an XML invoice). It is a paged-media renderer (WeasyPrint), not a browser: it is fast, deterministic, makes no outgoing requests and runs no JavaScript. You pay only for pages of PDFs that were actually produced.

Perfect for

  • Reports, proposals and contracts generated from templates or by AI agents — write Markdown, get a PDF with page numbers and a TOC.
  • Invoices and archives that need PDF/A-3b with an attached XML (ZUGFeRD / Factur-X / UBL style workflows — formatting and embedding only).
  • CVs and resumes, e-books and handouts, documentation exports, newsletters — in English, Ukrainian, Polish, German, Portuguese and other languages written in Latin or Cyrillic.
  • Automation: n8n, Make, Zapier, Google Sheets, MCP-enabled AI assistants — send text in, get a link to a PDF out.
  • Batches: up to 1,000 documents per run, each up to 5 MB of source.

What you get

FeatureDetails
Input formatsMarkdown (tables, footnotes, raw HTML allowed) or full / partial HTML with your own CSS
Table of contentstoc.enabled; depth 1–4; clickable entries with dotted leaders and the correct page numbers
Headers / footersText with tokens {page} {pages} {title} {date}; default footer Page {page} of {pages}
Page setupA4, Letter, A5, Legal; portrait or landscape; margins 5–50 mm
Templatesreport, article, contract, cv, plain (see below)
FontsNoto Sans, Noto Serif and Noto Sans Mono — Latin, Latin Extended, Cyrillic, Cyrillic Extended — embedded in every PDF
PDF/ApdfVariant: "pdf/a-3b" plus up to 5 attachments of up to 5 MB each
Safe by designDocuments cannot fetch anything: http(s)://, file://, @import, <link>, <iframe>, <object> are ignored. Inline data: images work
OutputOne dataset record per document + the PDF in the run's key-value store (public link in url)

How to use it

  1. Open the Actor, paste your text into Documents (JSON list; each item has markdown or html).
  2. Pick a template, page setup, switch the table of contents on if you want one, adjust header/footer.
  3. Click Start. Open the url of each record in the dataset to download the PDF.
{
"documents": [
{
"title": "Quarterly Report",
"filename": "quarterly-report.pdf",
"markdown": "# Quarterly Report\n\n## Highlights\n\n- Revenue grew 12 %\n\n## Next steps\n\n| Task | Owner |\n|---|---|\n| Plan Q4 | Alex |\n"
}
],
"template": "report",
"page": { "size": "A4", "orientation": "portrait", "marginMm": 20 },
"toc": { "enabled": true, "depth": 2, "title": "Contents" },
"header": "{title}",
"footer": "Confidential — page {page} of {pages}"
}

Example input — PDF/A-3b invoice with an XML attachment, Ukrainian text

{
"documents": [
{
"html": "<h1>Рахунок № 2026-001</h1><p>Сума до сплати: <b>1 234,50 ₴</b></p>",
"filename": "invoice-2026-001.pdf",
"attachments": [
{ "name": "invoice.xml", "contentBase64": "PEludm9pY2U+PElEPjIwMjYtMDAxPC9JRD48L0ludm9pY2U+", "mimeType": "application/xml", "description": "Machine-readable invoice" }
]
}
],
"template": "plain",
"pdfVariant": "pdf/a-3b",
"language": "uk",
"footer": "Сторінка {page} з {pages}"
}

Example output (one dataset record)

{
"recordType": "pdf",
"index": 0,
"filename": "quarterly-report.pdf",
"title": "Quarterly Report",
"template": "report",
"pdfVariant": "none",
"pages": 3,
"bytes": 41873,
"url": "https://api.apify.com/v2/key-value-stores/abc123/records/pdf-7c26db334c6493fd.pdf",
"kvKey": "pdf-7c26db334c6493fd.pdf",
"status": "ok",
"reason": null,
"message": null,
"warnings": [],
"charged": { "event": "pdf-page", "units": 3 },
"processedAt": "2026-10-02T18:00:00.000Z"
}

Run-level totals (documents, pages, charged events, failures by reason, warnings) are written to the key-value store record OUTPUT; a short Markdown list is in RESULTS_MD.

Input reference

FieldMeaning
documentsList of up to 1,000 documents. Each: exactly one of markdown / html; optional title, filename, css, language, attachments, and per-document template, page, toc, header, footer that override the run-level values
templatereport (default), article, contract, cv, plain
page{size: A4 | Letter | A5 | Legal, orientation: portrait | landscape, marginMm: 5–50}
toc{enabled, depth 1–4 (default 3), title (default "Contents")}
header, footerText with tokens; footer defaults to Page {page} of {pages}; write none to disable
languageBCP-47 code (default en) — hyphenation and quotation marks
pdfVariantnone (default) or pdf/a-3b
attachmentsUp to 5 files (≤ 5 MB each) embedded in every PDF; a document can carry its own list. Each: name, contentBase64, optional mimeType (otherwise guessed from the file name) and description
maxPagesPerDocument1–500 (default 300). Longer documents are rejected, free of charge

Templates

TemplateLook
reportSans-serif business report, accent headings, zebra tables, quoted callouts
articleSerif, justified, hyphenated long-form reading
contractFormal serif, compact, centred title, bordered tables, signature blocks keep together
cvCompact one-column resume with accent section rules
plainMinimal styling — use with HTML that brings its own CSS

All templates keep headings with the following paragraph, never split table rows, and repeat table headers on each page.

TokenReplaced by
{page}Current page number
{pages}Total number of pages
{title}Document title (title, else the HTML <title>, else the first heading)
{date}Generation date, YYYY-MM-DD (UTC)

Anything else is printed literally and safely escaped — text cannot break out of the header or inject styles.

Pricing

$0.007 per page of a PDF that was produced successfully (event pdf-page). Nothing else is charged. $0.007 is the base (Free-plan) rate; paid Apify plans get lower per-page rates automatically.

JobPagesCost
One-page invoice1$0.007
20-page report20$0.14
100 invoices of 2 pages200$1.40
300-page manual300$2.10

Failed, rejected, duplicate and over-budget documents are never charged. If you set a maximum cost per run, the Actor never starts a document that its pages cannot pay for and stops with a clear note in OUTPUT.

When NOT to use it

  • Your page needs JavaScript (charts drawn by scripts, single-page apps, client-side rendering). No script is executed. Pre-render charts as SVG or PNG (data: URLs work).
  • You want a screenshot of a live web page or a URL. This Actor does not download anything; it converts the text you send. Use a browser-based screenshot Actor for that.
  • You need pixel-identical Chrome output. The engine implements CSS Paged Media (page margin boxes, running headers, page counters), which browsers do not; some modern web-layout features (e.g. complex CSS Grid in older edge cases) can differ.
  • You need e-invoice validation, signing or delivery (Peppol, KSeF, ZUGFeRD checkers). PDF/A-3b mode formats and embeds your file; it does not validate its content or send it anywhere.

FAQ

Are failures free? Yes. invalid_input, too_large, render_error, timeout, too_many_pages, budget and duplicate produce a dataset record with the reason and cost nothing.

Which fonts are used? Cyrillic? Noto Sans / Serif / Sans Mono with Latin, Latin Extended and Cyrillic (including Ukrainian ґ є і ї). They are embedded in every PDF, so it looks the same everywhere. Your own CSS can use only these families (other fonts cannot be downloaded).

Can I use my own images? Yes, as data: URLs (inline base64). Remote images are not fetched.

What happens with identical documents in one run? The second one is marked duplicate, is not rendered again and is not charged.

Where is my data stored? Only in your own run storage (dataset and key-value store). Nothing is sent to third parties; documents are never allowed to load external resources (every URL except inline data: images and the bundled fonts is refused).

How do I get the PDF file? Open the url field of the record (public link to the key-value store record pdf-….pdf, content type application/pdf), or download from the Storage tab.

Why does a document fail with too_many_pages? It would produce more pages than maxPagesPerDocument (default 300, maximum 500). Raise the limit or split the document.

Use it from code, n8n, Make or an AI assistant

$curl -X POST "https://api.apify.com/v2/acts/YOUR_USERNAME~paged-pdf-generator/run-sync-get-dataset-items" -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" -d '{"documents":[{"title":"Hello","markdown":"# Hello\n\nFirst PDF"}],"toc":{"enabled":false}}'
const run = await client.actor('YOUR_USERNAME/paged-pdf-generator').call({ documents: [{ title: 'Notes', markdown: '# Notes\n\nText' }], footer: 'Page {page} of {pages}' });
  • n8n / Make: HTTP Request or Apify module → send documents built from a previous step (CRM record, Google Doc text, form answer) → read url from the dataset → attach or email the PDF.
  • MCP / AI agents: "Use paged-pdf-generator to turn this Markdown into a contract PDF with a table of contents and footer 'Page {page} of {pages}', template contract, Letter size, and give me the link." Every input field has a description the agent can read.

Limits

Up to 1,000 documents per run, 5 MB of source per document, 120 s per document, 500 pages per document, 5 attachments of 5 MB. Documents are rendered one at a time with less than 2 GB of run memory and two at a time with 2 GB or more (always one at a time when you set a maximum cost per run). Very large or complicated documents need more memory: if one does not fit, it fails with render_error (not charged) and the other documents continue - start the run with more memory or split the document.

More tools by the same author