API v1 · Production ready

HTML to PDF API

Render HTML and CSS exactly as a browser does, then take it away as a PDF or a full-page PNG. Grid, flexbox, gradients and web fonts all work, with optional JavaScript execution and full control over page size, margins and scale.

Get started free Documentation POST https://api.corenexis.com/html-to-pdf/v1
Full CSSGrid, flexbox, web fonts
500+ PagesLong documents supported
PDF + PNGPage images for long documents
~250msTypical render
Features

Built for documents that have to look right

Invoices, reports, certificates, tickets and dashboards — rendered by the same engine that draws them on screen, so the output matches the design instead of approximating it.

Modern CSS

Grid, flexbox, custom properties, gradients and transforms, rendered by a real browser engine.

Fast

A warm engine renders a typical document in about a quarter of a second.

Full Page Control

Named or custom page sizes, orientation, margins and scale.

JavaScript

Run scripts before capture so charts and client-rendered content appear in the output.

Your Fonts

Web fonts and local families load and are waited for before the page is captured.

PDF or PNG

Take a paginated PDF, or a full-height screenshot of the entire page.

Pricing

Simple, transparent pricing

Start free and scale as you grow. No hidden fees.

Free
Free
  • 30 documents/month
  • 3 requests/minute
  • Up to 512 KB input (~150 pages)
  • Full modern CSS support
  • PDF as a hosted link, valid 2 hours
  • Page size, margins, scale
Start Free
Most popular
Starter
$6.99 /mo
  • 500 documents/month
  • 8 requests/minute
  • Up to 1 MB input (~290 pages)
  • JavaScript execution
  • PNG output, long documents as an image sequence
  • Hosted link valid 7 days
  • Headers, footers, page numbers
Get Started
Pro
$19.99 /mo
  • 2,500 documents/month
  • 15 requests/minute
  • Up to 1.5 MB input (~440 pages)
  • JavaScript execution
  • PNG output, long documents as an image sequence
  • Hosted link valid 7 days
  • Headers, footers, page numbers
Choose Pro
Max
$39.99 /mo
  • 8,000 documents/month
  • 25 requests/minute
  • Up to 2 MB input (~570 pages)
  • JavaScript execution
  • PNG output, long documents as an image sequence
  • Hosted link valid 7 days
  • Priority processing
Choose Max
Agency
Custom
  • Unlimited documents
  • Custom rate limit
  • Custom input size
  • All features included
  • Dedicated support
Contact Sales
Documentation

API reference

Everything you need to integrate the HTML to PDF API.

Authentication

Every request needs your API key in the x-api-key header. Keys are created in the dashboard and belong to your account rather than to a single API.

Header
x-api-key: your_api_key

Keep the key server side. Anyone holding it can spend your quota. Call this API from your backend, never from a browser.

API endpoint

POSThttps://api.corenexis.com/html-to-pdf/v1

One synchronous endpoint. Send the HTML and the finished document comes back in the same response — there is no job to poll.

What renders

Documents are rendered by a real browser engine, so what you see in a browser is what lands in the PDF. Grid, flexbox, custom properties, gradients, transforms, web fonts and SVG all work without a compatibility layer.

Backgrounds are printed by default. Coloured panels, gradients and background images appear in the output. There is no need for a print-specific stylesheet.

External resources

Stylesheets, images and web fonts referenced by public URL are fetched and waited for before capture. Reference them absolutely — a relative path has no page to resolve against.

Input modes

The HTML can arrive in any of these forms. Use whichever suits your environment.

cURL
curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"html": "<h1>Invoice</h1><p>Thank you.</p>", "page_size": "a4"}'

2. Form field

cURL
curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: your_api_key" \
  -F "html=<h1>Hello</h1>" \
  -F "page_size=letter"

3. File upload

cURL
curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: your_api_key" \
  -F "html=@invoice.html"

4. Raw request body

cURL
curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: your_api_key" \
  -H "Content-Type: text/html" \
  --data-binary @invoice.html

Parameters

Parameter Type Description
x-api-key Required String Your API key. Send in the request header.
html Required String The HTML to render. May also be sent as an uploaded file or as the raw request body.
format String pdf or png. PNG requires a paid plan.
Default: pdf
output String Only url. Every result is delivered as a hosted link, on every plan, so this can be omitted. base64 and binary were withdrawn and now return a clear error.
Default: url
page_size String a3, a4, a5, letter, legal or tabloid.
Default: a4
orientation String portrait or landscape.
Default: portrait
width Number Custom page width in millimetres, 20 to 2000. Must be sent with height.
height Number Custom page height in millimetres, 20 to 2000. Must be sent with width.
margin_top Number Top margin in millimetres, 0 to 100.
Default: 20
margin_right Number Right margin in millimetres, 0 to 100.
Default: 15
margin_bottom Number Bottom margin in millimetres, 0 to 100.
Default: 20
margin_left Number Left margin in millimetres, 0 to 100.
Default: 15
scale Number Render scale, 0.1 to 2.
Default: 1
js Boolean Run scripts in the page before capture. Paid plans only.
Default: false
wait_ms Number Extra delay after load, 0 to 5000 ms. Requires js.
Default: 0
header_html String HTML for the running header. Paid plans only.
footer_html String HTML for the running footer. Paid plans only.
filename String Name for the produced file, without extension.
Default: document

Everything except the HTML is optional. Send nothing else and you get a sensible A4 portrait document. Anything you do send is applied.

JavaScript, headers & footers

JavaScript

Set js to true to run scripts before capture, and use wait_ms to allow for work that finishes after load. Charts, templating and client-side rendering all work. Available on paid plans.

JSON
{
  "html": "<div id=\"chart\"></div><script>renderChart()</script>",
  "js": true,
  "wait_ms": 500
}

Give async work time to finish. The page is captured once the network goes quiet. If your script draws after that, add wait_ms.

Headers and footers

Send header_html and footer_html to place a running header or footer on every page. Inside them, <span class="pageNumber"></span> and <span class="totalPages"></span> are replaced with page numbers.

JSON
{
  "html": "<h1>Report</h1>",
  "margin_bottom": 25,
  "footer_html": "<div style=\"font-size:9px;width:100%;padding:0 12mm;text-align:right;color:#666\">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span></div>"
}

Give the page room. A header or footer draws inside the margin, so increase margin_top or margin_bottom or it will overlap the content.

Delivery & output

How the result is delivered

Every result is stored and handed back as a hosted link under data.url, on every plan including the free one. There is nothing to decode and nothing to stream.

Plan Link valid for Why
Free 2 hours Long enough to fetch and use the file in the workflow that produced it.
Any paid plan 7 days Long enough to email, queue or hand on to another service.

Fetch the file, do not hotlink it. The link expires. Download it once and store the bytes yourself rather than pointing your users at it.

What changed

Inline delivery was withdrawn. A caller still sending the old value gets an error that says so rather than a silent change of behaviour.

output Status Notes
base64 Withdrawn The file inside the JSON response. It inflated every result by a third and had to be held in memory twice.
binary Withdrawn The raw file as the response body. It could not carry a document that had become several images.
url The only mode A hosted link under data.url. This is now the default, so the parameter can be omitted.

PDF and page images

Set format to png to receive images instead of a PDF. PNG output is a paid feature.

png_mode What you get When to use it
stack The document laid out into pages, returned as an ordered sequence of images in data.images. Default. Reading or displaying a whole document.
first One image of page one. Thumbnails and previews.
page One image of the page named by png_page. Pulling a single page out of a long document.
viewport One continuous screenshot with no page breaks, at the page’s natural height. Capturing a design rather than a document.

Why paged is the default. A continuous capture stops at the renderer’s maximum height, so on a long page it silently returned only the top. The paged modes have no such limit: the pages are grouped into as many images as it takes, and image.truncated tells you whether the set is complete. viewport is still there when you want one unbroken image, and it reports clipped when it had to stop.

Code examples

Python

Python
import requests

resp = requests.post(
    "https://api.corenexis.com/html-to-pdf/v1",
    headers={"x-api-key": "your_api_key"},
    json={
        "html": open("invoice.html").read(),
        "page_size": "a4",
        "margin_top": 12,
        "margin_bottom": 12,
        "js": True,
        "wait_ms": 300,
    },
    timeout=120,
)
data = resp.json()
if not data["success"]:
    raise SystemExit(data["message"])

# The PDF is delivered as a hosted link in data.url
pdf = requests.get(data["data"]["url"], timeout=60)
with open("invoice.pdf", "wb") as fh:
    fh.write(pdf.content)

Node.js

JavaScript
const fs = require("fs");

const res = await fetch("https://api.corenexis.com/html-to-pdf/v1", {
  method: "POST",
  headers: { "x-api-key": "your_api_key", "Content-Type": "application/json" },
  body: JSON.stringify({
    html: fs.readFileSync("invoice.html", "utf8"),
    format: "png",
    output: "url",
  }),
});

const data = await res.json();
if (!data.success) throw new Error(data.message);
console.log(data.data.url, data.data.image);

PHP

PHP
<?php
$ch = curl_init('https://api.corenexis.com/html-to-pdf/v1');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'x-api-key: your_api_key',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'html'        => file_get_contents('invoice.html'),
        'page_size'   => 'a4',
        'orientation' => 'landscape',
    ]),
]);
$res = json_decode(curl_exec($ch), true);
curl_close($ch);

if (!$res['success']) {
    exit($res['message']);
}

// The PDF is delivered as a hosted link in data.url
file_put_contents('invoice.pdf', file_get_contents($res['data']['url']));

Set a User-Agent. Python’s built-in urllib sends a default agent string our edge network refuses. The requests library, Node, Go, Java and cURL all work unchanged.

Response

JSON
{
  "success": true,
  "plan": "pro",
  "data": {
    "status": "completed",
    "format": "pdf",
    "mime": "application/pdf",
    "pages": 1,
    "page_size": "a4",
    "orientation": "portrait",
    "scale": 1,
    "js_enabled": false,
    "render_time_ms": 305,
    "url": "https://cdn.corenexis.com/f/qLm6VWHVlur.pdf",
    "filename": "document.pdf",
    "size_bytes": 45589,
    "expires_at": "2026-08-16T06:24:41+00:00"
  },
  "usage": { "remaining": 2498, "rate_limit": 15, "monthly_limit": 2500 }
}

Always check the success field rather than the status code alone. On failure the body carries a code and a message naming what to change.

Every option, worked

Every option below was sent to the live API and the response shown is what came back, including the request that produced it. Copy a command, put your own key in it, and you get the same shape of answer.

Minimal request

Only the document is required. Grid, flexbox, gradients and web fonts all render, because a real browser engine draws the page.

curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "...your document..."
  }'
{
  "success": true,
  "plan": "basic",
  "data": {
    "status": "completed",
    "format": "pdf",
    "mime": "application/pdf",
    "page_size": "a4",
    "orientation": "portrait",
    "scale": 1,
    "js_enabled": false,
    "render_time_ms": 1539,
    "pages": 1,
    "url": "https://cdn.corenexis.com/f/M5Cd8FtSTtV.pdf",
    "filename": "document.pdf",
    "size_bytes": 16304,
    "expires_at": "2026-08-09T06:57:53+00:00"
  },
  "usage": {
    "remaining": 4987,
    "rate_limit": 120,
    "monthly_limit": 5000
  }
}

Page size and orientation

One of a3, a4, a5, letter, legal or tabloid, in either orientation.

curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "...your document...",
    "page_size": "letter",
    "orientation": "landscape"
  }'
{
  "success": true,
  "plan": "basic",
  "data": {
    "status": "completed",
    "format": "pdf",
    "mime": "application/pdf",
    "page_size": "letter",
    "orientation": "landscape",
    "scale": 1,
    "js_enabled": false,
    "render_time_ms": 318,
    "pages": 1,
    "url": "https://cdn.corenexis.com/f/J8XaCP3y547.pdf",
    "filename": "document.pdf",
    "size_bytes": 16276,
    "expires_at": "2026-08-09T06:57:53+00:00"
  },
  "usage": {
    "remaining": 4986,
    "rate_limit": 120,
    "monthly_limit": 5000
  }
}

Custom page dimensions

Millimetres, 20 to 2000, supplied together. Overrides page_size, and the response reports page_size as custom so it is clear which applied.

curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "...your document...",
    "width": 150,
    "height": 100
  }'
{
  "success": true,
  "plan": "basic",
  "data": {
    "status": "completed",
    "format": "pdf",
    "mime": "application/pdf",
    "page_size": "custom",
    "orientation": "portrait",
    "scale": 1,
    "js_enabled": false,
    "render_time_ms": 453,
    "pages": 1,
    "width_mm": 150,
    "height_mm": 100,
    "url": "https://cdn.corenexis.com/f/n6LiWb0bJ0D.pdf",
    "filename": "document.pdf",
    "size_bytes": 16296,
    "expires_at": "2026-08-09T06:57:54+00:00"
  },
  "usage": {
    "remaining": 4985,
    "rate_limit": 120,
    "monthly_limit": 5000
  }
}

All four margins

Millimetres, 0 to 100 each.

curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "...your document...",
    "margin_top": 25,
    "margin_right": 20,
    "margin_bottom": 25,
    "margin_left": 20
  }'
{
  "success": true,
  "plan": "basic",
  "data": {
    "status": "completed",
    "format": "pdf",
    "mime": "application/pdf",
    "page_size": "a4",
    "orientation": "portrait",
    "scale": 1,
    "js_enabled": false,
    "render_time_ms": 311,
    "pages": 1,
    "url": "https://cdn.corenexis.com/f/0iaopelfqvs.pdf",
    "filename": "document.pdf",
    "size_bytes": 16289,
    "expires_at": "2026-08-09T06:57:54+00:00"
  },
  "usage": {
    "remaining": 4984,
    "rate_limit": 120,
    "monthly_limit": 5000
  }
}

Scale

0.1 to 2.0. Scales the rendered page before it is paginated, so 0.75 fits more onto each sheet rather than shrinking the sheet.

curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "...your document...",
    "scale": 0.75
  }'
{
  "success": true,
  "plan": "basic",
  "data": {
    "status": "completed",
    "format": "pdf",
    "mime": "application/pdf",
    "page_size": "a4",
    "orientation": "portrait",
    "scale": 0.75,
    "js_enabled": false,
    "render_time_ms": 290,
    "pages": 1,
    "url": "https://cdn.corenexis.com/f/in3LLDB6jqu.pdf",
    "filename": "document.pdf",
    "size_bytes": 16317,
    "expires_at": "2026-08-09T06:57:55+00:00"
  },
  "usage": {
    "remaining": 4983,
    "rate_limit": 120,
    "monthly_limit": 5000
  }
}

JavaScript execution

Off by default. wait_ms waits after load for scripted content to settle, and only applies when JavaScript is enabled.

curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<html><body><h1 id='t'>placeholder</h1><script>document.getElementById('t').textContent='written by script';</script></body></html>",
    "js": true,
    "wait_ms": 300
  }'
{
  "success": true,
  "plan": "basic",
  "data": {
    "status": "completed",
    "format": "pdf",
    "mime": "application/pdf",
    "page_size": "a4",
    "orientation": "portrait",
    "scale": 1,
    "js_enabled": true,
    "render_time_ms": 2507,
    "pages": 1,
    "url": "https://cdn.corenexis.com/f/YL7zK3syOjb.pdf",
    "filename": "document.pdf",
    "size_bytes": 7764,
    "expires_at": "2026-08-09T06:57:57+00:00"
  },
  "usage": {
    "remaining": 4982,
    "rate_limit": 120,
    "monthly_limit": 5000
  }
}

Full HTML, up to 2000 characters each. The browser substitutes pageNumber and totalPages.

curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "...long document...",
    "header_html": "<div style='font-size:9pt;width:100%;text-align:center'>Invoice</div>",
    "footer_html": "<div style='font-size:9pt;width:100%;text-align:center'>Page <span class='pageNumber'></span> of <span class='totalPages'></span></div>"
  }'
{
  "success": true,
  "plan": "basic",
  "data": {
    "status": "completed",
    "format": "pdf",
    "mime": "application/pdf",
    "page_size": "a4",
    "orientation": "portrait",
    "scale": 1,
    "js_enabled": false,
    "render_time_ms": 2194,
    "pages": 94,
    "url": "https://cdn.corenexis.com/f/TSC4XHrqoJK.pdf",
    "filename": "document.pdf",
    "size_bytes": 527013,
    "expires_at": "2026-08-09T06:57:59+00:00"
  },
  "usage": {
    "remaining": 4981,
    "rate_limit": 120,
    "monthly_limit": 5000
  }
}

PNG, whole document

Pages are rendered and returned as an ordered sequence of images, so a long document comes back complete.

curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "...long document...",
    "format": "png"
  }'
{
  "success": true,
  "plan": "basic",
  "data": {
    "status": "completed",
    "format": "png",
    "mime": "image/png",
    "page_size": "a4",
    "orientation": "portrait",
    "scale": 1,
    "js_enabled": false,
    "render_time_ms": 56288,
    "pages": 94,
    "url": "https://cdn.corenexis.com/f/3Vqgm5fTcVa.png",
    "filename": "document-p1-17.png",
    "size_bytes": 1379418,
    "expires_at": "2026-08-09T06:58:56+00:00",
    "image": {
      "mode": "stack",
      "dpi": 144,
      "pages_total": 94,
      "pages_rendered": 94,
      "pages_per_image": 17,
      "truncated": false
    },
    "image_count": 6,
    "total_bytes": 7571082,
    "images": [
      {
        "url": "https://cdn.corenexis.com/f/3Vqgm5fTcVa.png",
        "filename": "document-p1-17.png",
        "size_bytes": 1379418,
        "expires_at": "2026-08-09T06:58:56+00:00",
        "page_from": 1,
        "page_to": 17,
        "width": 1192,
        "height": 28628
      },
      {
        "url": "https://cdn.corenexis.com/f/HHMBPPVvek2.png",
        "filename": "document-p18-34.png",
        "size_bytes": 1381082,
        "expires_at": "2026-08-09T06:58:56+00:00",
        "page_from": 18,
        "page_to": 34,
        "width": 1192,
        "height": 28628
      },
      "... 4 more, one per page range, in order"
    ]
  },
  "usage": {
    "remaining": 4980,
    "rate_limit": 120,
    "monthly_limit": 5000
  }
}

PNG, one chosen page

Any page the document has.

curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "...long document...",
    "format": "png",
    "png_mode": "page",
    "png_page": 12
  }'
{
  "success": true,
  "plan": "basic",
  "data": {
    "status": "completed",
    "format": "png",
    "mime": "image/png",
    "page_size": "a4",
    "orientation": "portrait",
    "scale": 1,
    "js_enabled": false,
    "render_time_ms": 2229,
    "pages": 94,
    "url": "https://cdn.corenexis.com/f/H7AoJ1d5zIR.png",
    "filename": "document.png",
    "size_bytes": 126506,
    "expires_at": "2026-08-09T06:58:58+00:00",
    "image": {
      "mode": "page",
      "dpi": 144,
      "pages_total": 94,
      "pages_rendered": 1,
      "pages_per_image": 17,
      "truncated": false
    },
    "image_count": 1,
    "total_bytes": 126506,
    "images": [
      {
        "url": "https://cdn.corenexis.com/f/H7AoJ1d5zIR.png",
        "filename": "document.png",
        "size_bytes": 126506,
        "expires_at": "2026-08-09T06:58:58+00:00",
        "page_from": 12,
        "page_to": 12,
        "width": 1192,
        "height": 1684
      }
    ]
  },
  "usage": {
    "remaining": 4979,
    "rate_limit": 120,
    "monthly_limit": 5000
  }
}

PNG, continuous viewport capture

One continuous screenshot with no page breaks, for capturing a design rather than a document. It stops at the renderer’s maximum height, so clipped tells you whether the whole page was captured.

curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "...your document...",
    "format": "png",
    "png_mode": "viewport"
  }'
{
  "success": true,
  "plan": "basic",
  "data": {
    "status": "completed",
    "format": "png",
    "mime": "image/png",
    "page_size": "a4",
    "orientation": "portrait",
    "scale": 1,
    "js_enabled": false,
    "render_time_ms": 435,
    "url": "https://cdn.corenexis.com/f/OuQ6HZMAjhm.png",
    "filename": "document.png",
    "size_bytes": 20267,
    "expires_at": "2026-08-09T06:58:59+00:00",
    "image": {
      "mode": "viewport",
      "width": 1280,
      "height": 1200,
      "clipped": false
    }
  },
  "usage": {
    "remaining": 4978,
    "rate_limit": 120,
    "monthly_limit": 5000
  }
}

Refused: retired output mode

Inline delivery was withdrawn. Every result is a hosted link.

curl -X POST "https://api.corenexis.com/html-to-pdf/v1" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "...your document...",
    "output": "binary"
  }'
{
  "success": false,
  "code": "INVALID_INPUT",
  "message": "'output' no longer accepts 'binary'. Every result is delivered as a hosted link, so omit the parameter or send output=url. The response carries the link in data.url."
}

Errors

Errors arrive as JSON with a stable code.

Code HTTP Meaning
MISSING_KEY 401 The x-api-key header was not sent.
INVALID_KEY 401 The key does not exist or has been revoked.
KEY_DISABLED 403 The key exists but has been switched off.
ACCOUNT_SUSPENDED 403 The account is suspended.
NO_SUBSCRIPTION 402 The account has no subscription to this API.
SUBSCRIPTION_EXPIRED 402 The subscription lapsed and the grace period has passed.
RATE_LIMIT_EXCEEDED 429 Too many requests this minute. Retry shortly.
QUOTA_EXCEEDED 429 The monthly allowance is used up.
PARAM_LIMIT_EXCEEDED 400 A requested feature or value is above what the plan allows. The response names the parameter.
INVALID_INPUT 400 Something in the request is malformed. The message names the field.
RENDER_TIMEOUT 408 The document took too long. Simplify it and retry.
PROCESSING_FAILED 422 The document could not be rendered.
RENDERER_BUSY 503 Every worker is busy. Retry in a moment.

Quota-safe failures. If rendering fails after your request was accepted, your monthly quota is not charged. Only successful documents count.

Rate limiting. Free 3/min · Starter 8/min · Pro 15/min · Max 25/min.

Limits

Limit Value
Maximum input size 512 KB free, up to 2 MB on Max
Pages that means in practice About 150 pages free, about 570 on Max, for ordinary prose
Page limit There is no page limit. A 660-page document renders in about 20 seconds
Maximum delivered file 15 MB
Render deadline 25 seconds in the renderer. Beyond it you receive RENDER_TIMEOUT and nothing is charged
Hosted link lifetime 2 hours on the free plan, 7 days on any paid plan
Concurrency One document at a time, so latency stays predictable

Documents render one at a time so latency stays predictable. If every worker is busy you receive RENDERER_BUSY and nothing is charged; retry a moment later.

Sample output

The samples/ directory in the project repository holds real output across page sizes, orientations and both formats, so you can see what each option produces before calling the API.

Ready to ship pixel-perfect PDFs?

Create your free account and turn your first HTML page into a PDF in seconds. No credit card required.

Stay in the loop

New APIs, features and offers, straight to your inbox. No spam.

Already subscribed? Manage preferences