Markdown & HTML to PDF — TOC, Headers, Page Numbers
Pricing
from $5.60 / 1,000 pdf page rendereds
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
Maintained by CommunityActor 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
| Feature | Details |
|---|---|
| Input formats | Markdown (tables, footnotes, raw HTML allowed) or full / partial HTML with your own CSS |
| Table of contents | toc.enabled; depth 1–4; clickable entries with dotted leaders and the correct page numbers |
| Headers / footers | Text with tokens {page} {pages} {title} {date}; default footer Page {page} of {pages} |
| Page setup | A4, Letter, A5, Legal; portrait or landscape; margins 5–50 mm |
| Templates | report, article, contract, cv, plain (see below) |
| Fonts | Noto Sans, Noto Serif and Noto Sans Mono — Latin, Latin Extended, Cyrillic, Cyrillic Extended — embedded in every PDF |
| PDF/A | pdfVariant: "pdf/a-3b" plus up to 5 attachments of up to 5 MB each |
| Safe by design | Documents cannot fetch anything: http(s)://, file://, @import, <link>, <iframe>, <object> are ignored. Inline data: images work |
| Output | One dataset record per document + the PDF in the run's key-value store (public link in url) |
How to use it
- Open the Actor, paste your text into Documents (JSON list; each item has
markdownorhtml). - Pick a template, page setup, switch the table of contents on if you want one, adjust header/footer.
- Click Start. Open the
urlof each record in the dataset to download the PDF.
Example input — a report with table of contents and a custom footer
{"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
| Field | Meaning |
|---|---|
documents | List 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 |
template | report (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, footer | Text with tokens; footer defaults to Page {page} of {pages}; write none to disable |
language | BCP-47 code (default en) — hyphenation and quotation marks |
pdfVariant | none (default) or pdf/a-3b |
attachments | Up 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 |
maxPagesPerDocument | 1–500 (default 300). Longer documents are rejected, free of charge |
Templates
| Template | Look |
|---|---|
report | Sans-serif business report, accent headings, zebra tables, quoted callouts |
article | Serif, justified, hyphenated long-form reading |
contract | Formal serif, compact, centred title, bordered tables, signature blocks keep together |
cv | Compact one-column resume with accent section rules |
plain | Minimal 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.
Header / footer tokens
| Token | Replaced 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.
| Job | Pages | Cost |
|---|---|---|
| One-page invoice | 1 | $0.007 |
| 20-page report | 20 | $0.14 |
| 100 invoices of 2 pages | 200 | $1.40 |
| 300-page manual | 300 | $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
documentsbuilt from a previous step (CRM record, Google Doc text, form answer) → readurlfrom 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
- PDF Text and Table Extractor: Text and tables from PDFs, with OCR
- Website Screenshot API: Full-page, mobile and WebP screenshots