API documentation
One endpoint: send a URL or HTML, get a PDF back. Get a free API key to start.
Quick start
Send parameters as a form, JSON, or query string. Authenticate with your key in the header Authorization: Bearer YOUR_API_KEY. On success you get 200 with Content-Type: application/pdf.
curl -H "Authorization: Bearer YOUR_API_KEY" \
-d url=https://example.com \
-d page_size=A4 \
-o example.pdf \
https://pdfly.host/v1/convert
// Download the one-file client: https://pdfly.host/clients/php
require 'Pdfly.php';
$client = new \Pdfly\HtmlToPdfClient('YOUR_API_KEY');
$client->setPageSize('A4')
->setOrientation('portrait')
->setFooterHtml('Page <span class="pageNumber"></span> of <span class="totalPages"></span>');
$client->convertUrlToFile('https://example.com', 'example.pdf');
// HTML string → bytes, or straight to the browser:
$pdf = $client->convertString('<h1>Invoice #42</h1>');
$client->convertUrlToBrowser('https://example.com/invoice/42', 'invoice-42.pdf');
$ch = curl_init('https://pdfly.host/v1/convert');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query(['url' => 'https://example.com', 'page_size' => 'A4']),
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
]);
$pdf = curl_exec($ch);
if (curl_getinfo($ch, CURLINFO_RESPONSE_CODE) !== 200) {
throw new Exception(json_decode($pdf, true)['error']['message'] ?? 'PDF failed');
}
file_put_contents('example.pdf', $pdf);
import { writeFile } from 'node:fs/promises';
const res = await fetch('https://pdfly.host/v1/convert', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ url: 'https://example.com', page_size: 'A4' }),
});
if (!res.ok) throw new Error((await res.json()).error.message);
await writeFile('example.pdf', Buffer.from(await res.arrayBuffer()));
import requests
r = requests.post(
"https://pdfly.host/v1/convert",
headers={"Authorization": "Bearer YOUR_API_KEY"},
data={"url": "https://example.com", "page_size": "A4"},
timeout=120,
)
if r.status_code != 200:
raise Exception(r.json()["error"]["message"])
open("example.pdf", "wb").write(r.content)
Authentication
Any of these work: Authorization: Bearer KEY, X-Api-Key: KEY, HTTP Basic with the key as username or password, or a key parameter. Keep keys on your server — never put them in front-end JavaScript.
Check your usage
curl -H "Authorization: Bearer YOUR_API_KEY" https://pdfly.host/v1/account
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
url | string | — | Web page to convert. Send either url or text. |
text | string | — | HTML to convert (max 10 MB). Assets must use absolute URLs. html also works. |
page_size | string | A4 | A0–A6, Letter, Legal, Tabloid, Ledger. |
page_width / page_height | length | — | Custom page size, e.g. 80mm. Overrides page_size. |
orientation | string | portrait | portrait or landscape. |
margin_top / _right / _bottom / _left | length | 0.4in | Units: mm, cm, in, pt, px, pc. margin sets all four. |
no_margins | bool | false | Zero margins. |
header_html / footer_html | string | — | HTML on every page. Placeholders: <span class="pageNumber">, totalPages, title, url, date. Margin grows to 20mm automatically. |
use_print_media | bool | false | Use the page's @media print CSS instead of screen CSS. |
no_background | bool | false | Don't print background colors and images. |
javascript_delay | int (ms) | 0 | Wait after page load before printing (max 30000). For JS-heavy pages. |
wait_for_element | string | — | CSS selector: wait until it exists, e.g. #chart-ready. |
scale_factor | int (%) | 100 | Zoom, 10–200. |
print_page_range | string | all | e.g. 1-3,5. |
single_page | bool | false | Whole page as one long PDF page. |
css_page_size | bool | false | Let CSS @page { size: … } decide the page size. |
filename | string | document.pdf | Name in the Content-Disposition header. |
attachment | bool | false | Make browsers download instead of display. |
Booleans accept true/false, 1/0.
Errors
Errors come back as JSON: {"error": {"status": 400, "message": "…"}}
400 | Bad parameters — the message says which one. |
401 | Missing or invalid API key. |
402 | Monthly quota used up. |
403 | Key disabled. |
422 | The page couldn't be rendered (e.g. it returned a 5xx error). |
429 | Too many requests per minute — retry after the Retry-After seconds. |
502–504 | Renderer problem or timeout — safe to retry. |
Moving from pdfcrowd
Parameter names and PHP client methods match pdfcrowd's, so most integrations only need the class name and credentials changed:
- $client = new \Pdfcrowd\HtmlToPdfClient('username', 'apikey');
+ $client = new \Pdfly\HtmlToPdfClient('YOUR_API_KEY');
- catch (\Pdfcrowd\Error $why)
+ catch (\Pdfly\Error $why)
Header/footer placeholders pdfcrowd-page-number and pdfcrowd-page-count are translated automatically.