An HTML to PDF API that is one POST request
CurlShot is an HTML to PDF API. Send your HTML in a POST request with format=pdf and the answer is the PDF file. A real browser lays the page out and prints it, so your CSS, web fonts, tables and images come out as they look on screen, with text you can select and search. Paper size, margins, orientation and background printing are options, and page breaks follow your CSS. It works from any language that can send an HTTP request.
curl -X POST "https://curlshot.com/api/v1/screenshot" \
-H "X-Access-Key: YOUR_ACCESS_KEY" \
-H "Content-Type: application/json" \
-d '{"html":"<h1>Invoice 1042</h1><p>Total: 120.00</p>","format":"pdf","pdf_paper_format":"a4","pdf_margin":"20mm"}' \
--output invoice.pdfHow to convert HTML to PDF with the API in three steps
- 1
Write the document as HTML and CSS, as you would a web page.
- 2
Send it in a POST request with format set to pdf and the paper size you want.
- 3
Save the PDF that comes back, or make one for every order, user or report.
One POST request, in your language
Send the HTML in the html field of a JSON body, with format set to pdf. The answer is the PDF file itself. Your access key goes in the X-Access-Key header, so it stays out of logs.
const response = await fetch('https://curlshot.com/api/v1/screenshot', {
method: 'POST',
headers: { 'X-Access-Key': process.env.SCREENSHOT_ACCESS_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ html: invoiceHtml, format: 'pdf', pdf_paper_format: 'a4', pdf_margin: '20mm' }),
})
if (!response.ok) throw new Error((await response.json()).error_message)
await writeFile('invoice.pdf', Buffer.from(await response.arrayBuffer()))response = requests.post(
"https://curlshot.com/api/v1/screenshot",
headers={"X-Access-Key": os.environ["SCREENSHOT_ACCESS_KEY"]},
json={"html": invoice_html, "format": "pdf", "pdf_paper_format": "a4", "pdf_margin": "20mm"},
)
response.raise_for_status()
open("invoice.pdf", "wb").write(response.content)$context = stream_context_create(['http' => [
'method' => 'POST',
'header' => "X-Access-Key: " . getenv('SCREENSHOT_ACCESS_KEY') . "\r\nContent-Type: application/json",
'content' => json_encode(['html' => $invoiceHtml, 'format' => 'pdf', 'pdf_paper_format' => 'a4', 'pdf_margin' => '20mm']),
]]);
$pdf = file_get_contents('https://curlshot.com/api/v1/screenshot', false, $context);
if ($pdf === false) {
throw new RuntimeException('Render failed: ' . ($http_response_header[0] ?? 'no response'));
}
file_put_contents('invoice.pdf', $pdf);Paper sizes
pdf_paper_format takes any of these values. The default is a4; use letter for readers in the United States and Canada. pdf_landscape=true turns the paper on its side, and pdf_fit_one_page=true skips paper sizes and puts the whole document on one tall page.
Show the table (11 rows)
| Paper | pdf_paper_format | Millimetres | Inches | CSS pixels |
|---|---|---|---|---|
| A0 | a0 | 841 × 1189 | 33.1 × 46.8 | 3178 × 4493 |
| A1 | a1 | 594 × 841 | 23.4 × 33.1 | 2246 × 3178 |
| A2 | a2 | 420 × 594 | 16.54 × 23.4 | 1588 × 2246 |
| A3 | a3 | 297 × 420 | 11.7 × 16.54 | 1123 × 1588 |
| A4 | a4 | 210 × 297 | 8.27 × 11.7 | 794 × 1123 |
| A5 | a5 | 148 × 210 | 5.83 × 8.27 | 560 × 794 |
| A6 | a6 | 105 × 148 | 4.13 × 5.83 | 396 × 560 |
| US Letter | letter | 216 × 279 | 8.5 × 11 | 816 × 1056 |
| US Legal | legal | 216 × 356 | 8.5 × 14 | 816 × 1344 |
| Tabloid | tabloid | 279 × 432 | 11 × 17 | 1056 × 1632 |
| Ledger | ledger | 432 × 279 | 17 × 11 | 1632 × 1056 |
Margins, page breaks and print styles
The PDF is printed by a real browser, so the CSS you already know for printing works.
Show the table (6 rows)
| You want | How |
|---|---|
| A margin on every page | pdf_margin=20mm, or pdf_margin_top, _right, _bottom and _left for one side. Units: mm, cm, in or px. |
| A new page before each section | CSS: section { break-before: page; } |
| A table row or a card never split in two | CSS: tr, .card { break-inside: avoid; } |
| Your @media print rules to apply | media_type=print. The default draws the screen styles. |
| No background colours, to save ink | pdf_print_background=false. Backgrounds print by default. |
| Fonts and logos | Link them with full https:// addresses; relative paths have nothing to resolve against. |
- Without a margin option the content runs to the edge of the paper.
- HTML can be up to 2 MB. For many documents at once, use async=true with a webhook, or the bulk endpoint.

What people use it for
- Invoices and receipts from an HTML template
- Reports and statements with tables and charts
- Tickets, certificates and contracts with the details filled in
- A printable version of a page of your app
For developers: one request
The same thing from your own code. It is a plain HTTP request, so it works from any language. Create a free account to get an access key.
Questions people ask
How do I convert HTML to PDF?
Send the HTML to CurlShot in the html field of a POST request and add format=pdf. The answer is the PDF file.
Do backgrounds and colors print?
Yes. Background colors and images are printed unless you switch them off with pdf_print_background=false, for a document that saves ink.
Can I control page breaks?
Yes, with normal CSS. Rules such as break-before, break-after and break-inside work as they do when a browser prints.
Can the whole document be one long page?
Yes. pdf_fit_one_page puts everything on a single tall page with no breaks.
Guides that go deeper
- ReferenceWeb page to PDF: paper sizes, margins, print CSSPaper sizes in millimetres, inches, CSS pixels and points, how margins and page breaks work in a PDF of a web page, and the print CSS that controls them.
- CookbookHTML to image: six templates you can copySix copyable HTML and CSS templates: social card, certificate, receipt, quote card, ticket and stat card, with sizes and the rules that make them render right.
Related tools
- Markdown to PDFTurn Markdown into a clean, styled PDF or image with one API request. Headings, lists, tables and code are laid out for you. For notes, docs and reports.
- URL to PDF APIA URL to PDF API for developers: send a page address with format=pdf, get a PDF back. Paper size, margins, print styles, webhooks and signed links.
- HTML to imageRender your own HTML, CSS or Markdown into an image or a PDF with one API request. For social cards, certificates, receipts and reports.
- Web page to PDFTurn a web page into a PDF document from its address. Real pages, working links and selectable text. Paste the address, nothing to install. Also an API.