URL to PDF API
URL to PDF API: send any public web page URL, get a pixel-perfect PDF rendered by headless Chrome. 100 free pages, credits never expire.
Quick answer. Send POST https://html-pdf.com/v1/pdf with your API key and {"url": "https://..."}. The response body is the PDF.
curl https://html-pdf.com/v1/pdf \
-H "Authorization: Bearer $HTML_PDF_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "format": "A4"}' \
-o page.pdf
How it works
Here is what happens when you send a URL. The page opens in headless Chrome, its scripts run, and it is printed to PDF.
The response is the PDF itself. It comes with X-Pages and X-Credits-Remaining headers so you can track usage.
Make it look like the browser
These two options make the PDF match what you see on screen. Web pages are designed for screens, so print CSS can change how they look.
"media": "screen"uses screen CSS instead of print CSS. It keeps backgrounds and hides nothing your print stylesheet would hide."wait_delay": 2waits (up to 10 seconds) for JavaScript-heavy pages, charts or lazy-loaded images. For single-page apps,"wait_for_expression": "window.appReady === true"waits for a signal from your page instead.
{ "url": "https://example.com/dashboard/report", "media": "screen", "landscape": true, "wait_delay": 2 }
Other useful options are format (A3 to A6, Letter, Legal, Tabloid) or custom width/height, plus margin, page_ranges and footer_html with page numbers. Use max_pages to cap the cost of very long pages.
Python and Node.js
The same call works from any language. Here it is in Python and Node.js.
import os, requests
r = requests.post("https://html-pdf.com/v1/pdf",
headers={"Authorization": f"Bearer {os.environ['HTML_PDF_KEY']}"},
json={"url": "https://example.com", "media": "screen"}, timeout=60)
r.raise_for_status()
open("page.pdf", "wb").write(r.content)
const res = await fetch("https://html-pdf.com/v1/pdf", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.HTML_PDF_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ url: "https://example.com", media: "screen" }),
});
await fs.promises.writeFile("page.pdf", Buffer.from(await res.arrayBuffer()));
Want a link instead of a file? Add "response": "url" and you get a download URL valid for 24 hours.
Pages behind a login
This section shows how to convert pages that need authentication. The renderer only sees what an anonymous visitor sees. It can only reach public addresses, because private networks and internal hosts are blocked for security.
For dashboards, invoices or anything behind a login, render the page's HTML on your server. Then send it as html instead of url.
{ "html": "<!doctype html><html>…your rendered page…</html>" }
Use absolute https:// URLs for images and stylesheets, or inline them.
From an AI agent
AI assistants can convert URLs for you without any code. With the html-pdf.com MCP server, just ask "Save https://example.com/pricing as a PDF in landscape." The agent calls url_to_pdf and gives you the link.
Pricing
You pay only for the pages you render. 1 credit = 1 PDF page, so a 3-page article costs 3 credits. Failed renders cost nothing.
You get 100 free pages, then packs from $10 for 1,000 pages down to $0.005 per page. There is no subscription, and purchased credits never expire.
Get a free API key · API reference · HTML to PDF in Python
FAQ
How do I convert a URL to PDF with an API?
Send POST https://html-pdf.com/v1/pdf with Authorization: Bearer $HTML_PDF_KEY and a JSON body like {"url": "https://example.com"}. The response is the PDF file, rendered by headless Chrome.
Can I convert a page that requires a login?
Not by URL, because the renderer only sees what an anonymous visitor sees and cannot reach private networks. Render the page's HTML on your server and send it as html instead.
How much does URL to PDF conversion cost?
1 credit = 1 PDF page, and failed renders cost nothing. You get 100 free credits once with no card, then packs from $10 for 1,000 pages down to $0.005 per page that never expire.
How do I wait for JavaScript or charts to load before the PDF is made?
Use "wait_delay" (up to 10 seconds) or "wait_for_expression" with a condition like "window.appReady === true". The PDF is printed once the wait is over.
