HTML to PDF in Node.js
Send HTML (or a URL) to the FrameForge API and get a PDF back. It is rendered in real Chromium, so modern CSS, web fonts and JavaScript all work. No browser to install or babysit.
The code
Node 18+ (built-in fetch). Set FRAMEFORGE_KEY to your API key.
import { writeFile } from "node:fs/promises";
const res = await fetch("https://api.frameforgeapi.com/render", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": process.env.FRAMEFORGE_KEY,
},
body: JSON.stringify({
html: "<h1>Invoice #1001</h1><p>Total: £49.00</p>",
format: "pdf",
width: 794, // A4 at 96 DPI
height: 1123,
}),
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
await writeFile("invoice.pdf", Buffer.from(await res.arrayBuffer()));
How it works
POST /rendertakes JSON with exactly one ofhtml(up to 1 MiB) orurl, plusformat(png,jpegorpdf),widthandheight(1 to 3840 px) andfullPage.- The response body is the file itself (
application/pdf), not JSON, so write the bytes straight to disk or stream them to the user. - Page size: the PDF page is
width×heightpixels.794 × 1123is A4 at 96 DPI and816 × 1056is US Letter. Content longer than one page flows onto more pages of the same size. WithfullPage: trueyou get one tall page instead. - Margins: pages have no printer margins, so add padding in your HTML (for example
body { padding: 48px }). - Caching: identical requests within 24 hours are served from cache and don't count against your quota. Check the
X-FrameForge-Cacheresponse header. - Errors come back as JSON with an
errorcode:401bad key,429rate limited,400 blocked_urlfor private or local addresses.
Rendering a URL instead of HTML
{"url": "https://example.com/report", "format": "pdf", "width": 1280, "height": 800, "fullPage": true}
Doing it yourself instead
Run headless Chromium yourself with Playwright or Puppeteer (page.pdf()). It works well, but you then own the browser process, memory, fonts, timeouts and SSRF protection on your server.
An API makes sense when you don't want Chromium on your servers, or when you need images (PNG/JPEG) and PDFs from the same call. If you render a few PDFs a month on a server you already run, self-hosting is perfectly reasonable.
Free tool: Website to PDF. Other languages: Python · PHP · Ruby · Go · Java · C# / .NET · curl / Bash · Next.js · Laravel · Django · Ruby on Rails