§ Next.js PDF generator
Next.js PDF Generator: Generate a PDF from HTML in Next.js
Generate a PDF from an HTML page or React component in your Next.js app with one HTTP call. Managed Chromium renders your real markup on the server, so you get a true, selectable PDF without bundling headless Chrome into a serverless function that will not fit. Try it on any URL below.
- Early access, launching soon
- No card required
- Your HTML stays yours
§ Live demo
Runs in your browser. Nothing is uploaded.
Your HTML
Live preview
Your PDF is downloading. Want this as one API call, with the page archived too?
§ Short answer
The blocker for a Next.js PDF generator is not writing the code, it is the runtime. Next.js has no built in PDF export, and on Vercel or any serverless host you cannot reliably launch full Puppeteer, the Chromium binary is far larger than the function size limit. Teams end up either wrestling @sparticuz/chromium into a function and fighting cold starts and size caps, or calling a rendering API that runs Chromium elsewhere. The API path is a single fetch from a route handler, returns a true vector PDF with selectable text, and works the same on Vercel, a Node server, or the edge.
Last updated July 2026. Written and fact checked by the Sitepdf team.
§ 00
Four ways to make a PDF in Next.js, compared
They differ most in whether you can run them on serverless without hitting the function size limit, and whether the PDF contains real, selectable text.
| Approach | Runs on Vercel serverless | Output | What you operate | Best for |
|---|---|---|---|---|
| puppeteer (full) | No: Chromium exceeds the function size limit | True vector PDF | A Chromium install, only on a long lived Node server | A self-hosted Next.js app on your own server |
| puppeteer-core + @sparticuz/chromium | Barely: fits the cap but fragile, slow cold starts | True vector PDF | A pinned chromium build you upgrade by hand | Teams committed to keeping Chromium inside the function |
| @react-pdf/renderer, client jsPDF | Yes | jsPDF is a raster snapshot; react-pdf is real but its own layout | Nothing, but you rebuild the layout in JSX | A bespoke document, not a copy of an existing page |
| Rendering API Sitepdf |
Yes, it is just a fetch | True searchable vector PDF, print accurate | Nothing, no browser in your deploy | Modern CSS at volume on serverless, plus a dated record |
The honest read: if your Next.js app runs on a long lived Node server you control, full Puppeteer works fine and is free, so use it. The pain is specific to serverless, where the Chromium binary does not fit and cold starts hurt. That is exactly where offloading the browser to an API pays for itself.
§ 01
Why headless Chrome is the hard part on Vercel
Almost every Next.js PDF tutorial starts with Puppeteer, and almost every one of them assumes a normal Node server. On Vercel and similar serverless hosts that assumption breaks. A serverless function has a hard size limit, and a full Chromium download is far larger, so npm install puppeteer and deploy simply fails to fit. The community workaround is puppeteer-core paired with @sparticuz/chromium, a Chromium build stripped down and compressed specifically to squeeze under the cap.
It can work, and for some teams it is worth it, but be clear eyed about the cost. You are now pinning two packages whose versions must stay compatible with each other and with the platform, every upgrade is a small risk, and each cold start has to decompress and boot Chromium, which adds noticeable latency to the first request after idle. Our Puppeteer PDF on AWS Lambda guide walks through this exact setup and its failure modes on Lambda, and the same constraints apply on Vercel functions.
§ 02
The API path: one fetch from a route handler
The alternative is to never put a browser in your deploy at all. A rendering API runs managed Chromium on its own servers, so from Next.js it is a single request. This works identically on a Vercel function, the edge runtime, or a self-hosted Node server, because nothing about it depends on your runtime being able to launch a browser.
// app/api/pdf/route.ts
export async function POST(req: Request) {
const { url } = await req.json();
const res = await fetch("https://api.sitepdf.com/v1/render", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.SITEPDF_KEY}` },
body: new URLSearchParams({ url, format: "Letter", archive: "true" }),
});
const { pdf_url } = await res.json();
return Response.json({ pdf_url });
}Point it at any route in your app, an invoice page, a receipt, a dashboard export, and Chromium loads that page exactly as a visitor would, runs your client JavaScript, waits for charts, and returns the PDF. If the document is a React component you would rather not expose as a route, render it to an HTML string on the server with renderToStaticMarkup and post the HTML instead, which the React to PDF page covers in full.
§ 03
When to skip the API
We will say plainly when you do not need us. If your Next.js app is deployed on a long lived Node server you control, a VPS, a container, a traditional host, then full puppeteer installs and runs without any size limit, and it is free. Run it yourself. The Puppeteer alternative page lays out that trade off honestly: self-hosting Chromium is the right call when you have somewhere to run it and someone to keep it patched and memory stable under load.
The API earns its place in two situations. The first is serverless, where the browser genuinely does not fit and every cold start costs you. The second is scale, where keeping a fleet of Chromium processes warm, patched and from leaking memory becomes real operational work you would rather not own. If neither applies to you, a local browser is a perfectly good Next.js PDF generator.
§ 04
Keep a dated copy of every PDF you generate
One capability no local approach offers is a record. When your Next.js app generates an invoice or a signed quote, the file ships to the customer and nothing verifiable stays behind. Add archive=true to the render call and Sitepdf stores a timestamped, immutable snapshot of exactly what it rendered, retrievable by id. For finance and compliance features that provenance is frequently the whole reason to render server side. The website archiving page explains the record, and the PDF generator API page has every parameter. Renders are transient by default; leave archiving off and we store nothing.
curl https://api.sitepdf.com/v1/render \
-H "Authorization: Bearer $SITEPDF_KEY" \
-F url=https://app.example.com/invoices/8842 \
-F format=Letter \
-F print_background=true \
-F archive=true
{
"pdf_url": "https://api.sitepdf.com/v1/documents/doc_4c8pn.pdf",
"pages": 2,
"rendered_in_ms": 1755,
"archive": {
"id": "arc_q92wl",
"captured_at": "2026-07-19T18:58:33Z",
"retrieve_url": "https://api.sitepdf.com/v1/archives/arc_q92wl"
}
}
The API is in early access; this is the documented call shape it opens with. Full request and response walkthrough.
§ 05
Questions about this job
How do I generate a PDF in Next.js?
Can I run Puppeteer on Vercel for PDF generation?
What is the best way to make a PDF from HTML in a Next.js API route?
Does the API work with the Next.js edge runtime?
How do I keep a copy of the PDFs my Next.js app creates?
§ Index
More PDF and archiving tools
- Convert HTML to PDF
- Webpage to PDF
- Save webpage as PDF
- URL to PDF API
- Website archiving
- Screenshot API
- React to PDF
- Laravel HTML to PDF
- Vue to PDF
- Angular to PDF
- Markdown to PDF API
- Django HTML to PDF
- Blazor HTML to PDF
- Spring Boot HTML to PDF
- Airtable to PDF
- Rails HTML to PDF
- PDF generator API
- Document generation API
- Bulk HTML to PDF
- Wayback Machine alternative
- Best HTML to PDF API
- DocRaptor alternative
- Puppeteer alternative
- Wkhtmltopdf alternative
- PDFShift alternative
- Urlbox alternative
- PDFCrowd alternative
- Api2Pdf alternative
- Browserless alternative
- APITemplate alternative
- CraftMyPDF alternative
- PDFMonkey alternative
- dompdf alternative
- Gotenberg alternative
- GrabzIt alternative
- How it works
- Features
- Pricing
§ Early access
Get on the early-access list
The API opens to the list first, in order. Early access locks the planned launch rates for 12 months. No card required, launching soon.