How to authenticate Html2Pdf.app API requests with an API key
Authenticate Html2Pdf.app requests with the X-API-Key header. See runnable cURL, Python, and Node.js examples, plus secure key handling and callback guidance.
Send your Html2Pdf.app API key in the X-API-Key HTTP header when you call POST https://api.html2pdf.app/v1/generate. Set Content-Type: application/json and include an html field in the JSON body. A successful synchronous request returns PDF bytes, so save or stream the response as binary data.
Keep the key in trusted server-side code or configuration. Do not put it in browser JavaScript, a public repository, or a client-side template. Html2Pdf.app says it emails the API key after registration. See the official documentation for the current endpoint and options.
1. Get and store your API key
- Register for Html2Pdf.app and retrieve the API key sent by email.
- Store it as a server-side environment variable named
HTML2PDF_API_KEY. - Make requests from a backend, server-side script, or trusted job that can read the secret.
Never commit a real key to source control. If a key is exposed, revoke or replace it through the provider’s account process.
2. Send an authenticated request with cURL
This example converts a public URL to a PDF file. The shell expands the environment variable into the header; the key is not part of the URL.
export HTML2PDF_API_KEY='your-api-key'
curl --fail --show-error \\
--request POST https://api.html2pdf.app/v1/generate \\
--header 'Content-Type: application/json' \\
--header "X-API-Key: $HTML2PDF_API_KEY" \\
--data '{"html":"https://www.example.com"}' \\
--output document.pdf
--fail makes cURL report an HTTP error as a failure, and --show-error prints the error details. The output file should be treated as binary PDF data, not text.
3. Python example
Install the HTTP client with python -m pip install requests, set the environment variable in the process environment, then run:
import os
import requests
api_key = os.environ["HTML2PDF_API_KEY"]
endpoint = "https://api.html2pdf.app/v1/generate"
payload = {"html": "https://www.example.com"}
response = requests.post(
endpoint,
headers={
"X-API-Key": api_key,
"Content-Type": "application/json",
},
json=payload,
timeout=120,
)
response.raise_for_status()
with open("document.pdf", "wb") as pdf_file:
pdf_file.write(response.content)
The wb mode preserves the returned PDF bytes. The timeout is a client-side limit; choose a value suitable for your documents and runtime.
4. Node.js example
With a Node.js runtime that provides the built-in fetch API:
const apiKey = process.env.HTML2PDF_API_KEY;
if (!apiKey) throw new Error("Set HTML2PDF_API_KEY first");
const response = await fetch("https://api.html2pdf.app/v1/generate", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": apiKey,
},
body: JSON.stringify({ html: "https://www.example.com" }),
signal: AbortSignal.timeout(120_000),
});
if (!response.ok) {
const details = await response.text();
throw new Error(`Html2Pdf.app returned ${response.status}: ${details}`);
}
const pdf = Buffer.from(await response.arrayBuffer());
await import("node:fs/promises").then(({ writeFile }) =>
writeFile("document.pdf", pdf)
);
For older Node.js versions without built-in fetch or AbortSignal.timeout, use a supported HTTP client and its timeout option. Do not return the API key to a browser when building a web application; have your server make the request.
5. Choose URL input or raw HTML
The required JSON field is html. It can contain either a public URL or raw HTML markup.
{"html":"https://www.example.com"}
{"html":"<!doctype html><html><body><h1>Invoice</h1></body></html>"}
POST with JSON is the recommended request style. GET is also supported, but every query parameter must be URL-encoded; raw markup and long template values are especially awkward in a URL and can exceed client or intermediary limits.
6. Synchronous requests and callback mode
Synchronous: receive the PDF in the response
By default, the request remains open until conversion completes. On success, the response body is the PDF itself. Check the HTTP status before saving or forwarding the body, and do not try to parse a successful body as JSON.
Asynchronous: queue work with a callback URL
For background generation, include callBackUrl in the JSON request and keep the same X-API-Key header. The documented response is 202 Accepted: it means the job was queued, not that the PDF is ready. Html2Pdf.app later sends a POST to the callback URL with the generated document encoded in the callback payload.
curl --fail --show-error \\
--request POST https://api.html2pdf.app/v1/generate \\
--header 'Content-Type: application/json' \\
--header "X-API-Key: $HTML2PDF_API_KEY" \\
--data '{"html":"https://www.example.com","callBackUrl":"https://your-service.example/callback"}'
Confirm the callback payload format and callback endpoint requirements in the current provider documentation before implementing the receiver. Make the receiver tolerate retries or duplicate deliveries if the provider’s delivery behavior requires it, and validate that an incoming callback belongs to the job you expect.
7. Troubleshooting
| Symptom | Likely cause | What to check |
|---|---|---|
| Authentication fails | The key is missing, incorrect, or sent under the wrong header name. | Send X-API-Key exactly, check the server-side environment variable, and ensure no extra whitespace was copied into the key. |
| Request is rejected as malformed | The content type or JSON body is wrong. | Set Content-Type: application/json, send valid JSON, and include the required html field. |
| The saved file is not a usable PDF | An error response was written as if it were the successful binary response. | Check the HTTP status before writing the body. On errors, inspect the response details rather than opening the body as a PDF. |
| Request times out | Conversion or page loading took longer than the caller’s timeout. | Use a suitable client timeout. For work that should run in the background, use callback mode and handle the queued 202 Accepted response. |
| PDF is blank or missing styling | The page, stylesheets, fonts, images, or scripts may not be reachable or ready when rendering occurs. | Make dependent resources publicly reachable to the rendering service and check JavaScript load timing. Test a representative page and consult the provider’s rendering guidance. |
| Layout differs from the browser | Rendering can depend on CSS media mode, available fonts and resources, and JavaScript timing. | Check the source page under the relevant print or screen styles, verify fonts and assets load, and use representative test documents. |
8. Security, reliability, and cost considerations
- Protect the credential: keep it on the server, restrict access to the environment variable, and avoid logging request headers or exposing secrets in error reports.
- Handle binary data: write successful output in binary mode or stream it without text conversion. Avoid buffering large documents in memory when your application can stream them.
- Set timeouts: conversion involves loading and rendering content, so configure a client timeout appropriate to your request path. Use callback mode for jobs that should not hold a foreground request open.
- Account for rendering dependencies: a publicly accessible source URL may still reference private or blocked assets. Check the page, CSS, fonts, images, and JavaScript readiness when output is incomplete.
- Check current plan limits: the available research confirms account and credit plans exist, but does not establish current prices, quotas, or retry guarantees. Consult the provider’s account and documentation pages for those details.
9. Or skip the browser setup
If your goal is a clean screenshot of a page rather than a PDF conversion, ScreenshotNeo provides a website screenshot API and MCP server. One GET request can return PNG, JPEG, WebP, or PDF. Its documented options include full-page capture, element capture, device viewports, custom CSS and JavaScript, wait conditions, and PDF settings. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" \\
-d access_key=YOUR_API_KEY \\
--data-urlencode url=https://stripe.com \\
-o shot.webp
Equivalent Python request:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
Equivalent Node.js request:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture, and only clean shots are billed: bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, with the page verdict and billing status in response headers. Its MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card.
10. Frequently asked questions
What header does Html2Pdf.app use for API authentication?
Use X-API-Key: your-api-key on each request.
Can I authenticate from frontend JavaScript?
Do not expose the key in frontend code. Make the authenticated request from your server and return only the result your application needs.
Does a successful request return JSON?
For synchronous generation, success returns PDF bytes. Callback mode initially returns 202 Accepted to indicate queued work.
Can I send HTML without hosting a page?
Yes. Put raw HTML markup in the JSON html field; POST is recommended for this input.


