// api reference
One endpoint. Send raw HTML or a Nunjucks template plus JSON data and get back a pixel-perfect PDF. Full Chromium rendering. Modern CSS, web fonts, and even async JavaScript like charts and QR codes.
Base URL
https://e.customjs.io/html2pdfGet your API key from app.customjs.space, 600 free conversions every month, no credit card.
Pass your API key in the x-api-key header. The response is the raw PDF binary, so pipe it to a file.
curl -X POST https://e.customjs.io/html2pdf \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{ "input": { "html": "<h1>Hello World</h1>" } }' \
> output.pdfEvery response includes your current usage in the rate-limit headers.
| Response Header | Description |
|---|---|
| x-ratelimit-limit | Maximum requests allowed in the current window |
| x-ratelimit-used | Requests used in the current window |
| x-ratelimit-remaining | Requests remaining in the current window |
/html2pdfSend HTML, get a PDF. The whole document is rendered in a real Chromium instance, so your CSS, layout, and fonts come out exactly as in the browser.
| Field | Type | Description |
|---|---|---|
| input.html | string | Required. The HTML content to convert to PDF |
| input.data | object | Template data. When provided, the HTML is rendered with the Nunjucks template engine before conversion |
| input.config | object | Optional page configuration |
| input.config.pdfWidthMm | number | Page width in millimeters. Defaults to A4 (210) |
| input.config.pdfHeightMm | number | Page height in millimeters. Defaults to A4 (297) |
curl -X POST https://e.customjs.io/html2pdf \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"input": {
"html": "<h1>Hello World</h1>"
}
}' \
> output.pdfStore the design once and send only your data. Add a data object and reference it in the HTML with {{ variable }} placeholders. Perfect for invoices, reports, and certificates.
curl -X POST https://e.customjs.io/html2pdf \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"input": {
"html": "<h1>Hello {{ name }}</h1><p>Total: {{ total }}</p>",
"data": { "name": "John", "total": 100 },
"config": { "pdfWidthMm": 150, "pdfHeightMm": 150 }
}
}' \
> output.pdfBecause conversion runs in a real Chromium instance, your template can execute JavaScript. Load external libraries, draw charts, or generate QR codes at render time.
Import ES modules straight from a CDN inside a <script type="module"> tag.
<script type="module">
import QRCode from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
// Generate a QR code at render time
const qrDataUrl = await QRCode.toDataURL('https://example.com', {
width: 150,
margin: 1
});
document.getElementById('qr').src = qrDataUrl;
</script>
<img id="qr" alt="QR Code" />window.__RENDER_DONE__When your template does async work (QR codes, charts, API calls), set window.__RENDER_DONE__ = true when the content is ready. The generator waits for this flag before capturing the page.
<script type="module">
import QRCode from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
// Tell the generator we're not ready yet
window.__RENDER_DONE__ = false;
async function generateQR() {
const qrDataUrl = await QRCode.toDataURL('https://example.com');
document.getElementById('qr').src = qrDataUrl;
// Signal that rendering is complete
window.__RENDER_DONE__ = true;
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', generateQR);
} else {
generateQR();
}
</script> โ ๏ธ Important: without setting window.__RENDER_DONE__ = true, the PDF may be blank or incomplete because the generator won't wait for async operations to finish.
On success the API responds with Content-Type: application/pdf and the raw PDF bytes in the body. Pipe it to a file or stream it to your storage.
HTTP/1.1 200 OK
Content-Type: application/pdf
x-ratelimit-limit: 500
x-ratelimit-used: 12
x-ratelimit-remaining: 488
%PDF-1.4 ...binary...| Header | Description |
|---|---|
| Content-Type | application/pdf on success |
| x-ratelimit-limit | Maximum requests per window |
| x-ratelimit-used | Requests used in the current window |
| x-ratelimit-remaining | Requests remaining in the current window |
| Code | Meaning |
|---|---|
| 200 | Success. Body contains the PDF binary |
| 400 | Bad request. Missing or invalid input.html |
| 401 | Unauthorized. Missing or invalid API key |
| 500 | Internal error. Rendering failed |
// try it first
Open the interactive playground on the product page. Paste your HTML, watch the PDF render live, tweak the page size, and copy the generated curl or SDK snippet straight into your stack.
curl -X POST https://e.customjs.io/html2pdf \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"input": {
"html": "<h1>Invoice #{{ id }}</h1>",
"data": { "id": "1042" }
}
}' > invoice.pdf600 free conversions / month ยท no credit card