How to Convert HTML to PDF with DocRaptor
Send HTML or a URL to DocRaptor, save the PDF response, and choose JavaScript and delivery options that fit your document.
To convert HTML to PDF with DocRaptor, send an authenticated JSON POST request to https://api.docraptor.com/docs with type: "pdf" and either document_content or document_url. A successful synchronous request returns PDF bytes. Check the HTTP status before saving the response so an error body is not mistaken for a PDF.
Use document_content when your application already has the HTML string. Use document_url when DocRaptor should retrieve a page and its assets. JavaScript is disabled by default; enable it only if the document needs script-rendered content. See the [DocRaptor API overview](https://docraptor.com/documentation/api/making_documents) and [API reference](https://docraptor.com/documentation/api) for current request details.
1. Choose HTML content or a URL
| Input | Use it when | Things to check |
|---|---|---|
document_content |
Your application has the HTML to convert. | For relative asset URLs, provide a base URL using prince_options.baseurl as shown in DocRaptor’s guide. Verify that images, stylesheets, and fonts resolve as expected. |
document_url |
The document is available at a URL DocRaptor can request. | Make sure DocRaptor can retrieve the page and any required assets. Check for access controls or unavailable resources if conversion fails. |
A minimal content payload looks like this:
{
"type": "pdf",
"document_content": "<html><body><h1>Invoice</h1></body></html>"
}
For URL input, replace document_content with document_url, for example "document_url": "https://example.com/invoice/123". The API requires the PDF document type and one of these inputs.
2. Make a PDF request with cURL
DocRaptor documents HTTP Basic Authentication with the API key as the username and a blank password as its preferred authentication method. The following sends HTML directly and writes a successful response to invoice.pdf:
curl --fail-with-body \
--user "YOUR_API_KEY:" \
--header "Content-Type: application/json" \
--data '{"type":"pdf","document_content":"<html><body><h1>Invoice</h1></body></html>"}' \
"https://api.docraptor.com/docs" \
--output invoice.pdf
The colon after YOUR_API_KEY supplies the blank Basic Auth password. Use a secret manager or environment variable in real scripts instead of committing a key into source control. To use a URL, change the JSON field to document_url and provide a retrievable URL. cURL’s --fail-with-body makes unsuccessful HTTP statuses visible while retaining the error body for diagnosis; check the exit status and do not use the output as a PDF when the request fails.
3. Make the request with Python
This example uses requests, checks for an HTTP error, and saves binary response bytes:
import os
import requests
api_key = os.environ["DOCRAPTOR_API_KEY"]
payload = {
"type": "pdf",
"document_content": "<html><body><h1>Invoice</h1></body></html>",
}
response = requests.post(
"https://api.docraptor.com/docs",
json=payload,
auth=(api_key, ""),
timeout=120,
)
response.raise_for_status()
with open("invoice.pdf", "wb") as pdf_file:
pdf_file.write(response.content)
print("Saved invoice.pdf")
Install the dependency with python -m pip install requests if it is not already available. Set DOCRAPTOR_API_KEY in the process environment before running the script. For URL input, use "document_url": "https://example.com/invoice/123" instead of document_content. The timeout is an application choice, not a DocRaptor service limit; choose one suitable for your documents and retry policy.
4. Make the request with Node.js
This example uses built-in fetch and saves the returned bytes. It requires a Node.js version with global fetch:
import { writeFile } from "node:fs/promises";
const apiKey = process.env.DOCRAPTOR_API_KEY;
if (!apiKey) throw new Error("Set DOCRAPTOR_API_KEY");
const payload = {
type: "pdf",
document_content: "<html><body><h1>Invoice</h1></body></html>",
};
const basicAuth = Buffer.from(`${apiKey}:`).toString("base64");
const response = await fetch("https://api.docraptor.com/docs", {
method: "POST",
headers: {
"Authorization": `Basic ${basicAuth}`,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
signal: AbortSignal.timeout(120_000),
});
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`DocRaptor returned HTTP ${response.status}: ${errorBody}`);
}
const pdfBytes = Buffer.from(await response.arrayBuffer());
await writeFile("invoice.pdf", pdfBytes);
console.log("Saved invoice.pdf");
Use document_url in the payload when DocRaptor should fetch a page. Keep the key in the server environment; code shipped to browsers is public to users.
5. Configure JavaScript, CSS, and page layout
JavaScript rendering
JavaScript execution is disabled by default. Leave it disabled for static HTML to avoid unnecessary processing. If the PDF needs a chart, font, or other content created by JavaScript, enable the relevant JavaScript option documented in the current [API reference](https://docraptor.com/documentation/api) or [JavaScript guide](https://docraptor.com/documentation/article/1067832-enabling-javascript). DocRaptor describes a primary JavaScript engine and a Prince JavaScript option; consult the guide for the current option names and behavior. Its guide recommends the primary engine for most users and notes that enabling both evaluates JavaScript twice.
For scripts that finish asynchronously, conversion needs a completion signal. DocRaptor documents docraptorJavaScriptFinished() for indicating that rendering is done. Call it only after the content needed in the PDF is ready. A script error or a completion signal sent too early can produce a failed or incomplete document.
Print and screen styles
Use CSS for page styling and print layout. DocRaptor’s examples show prince_options.media to choose screen or print media styles. Choose the media mode that matches the stylesheet you intend to render, and review the output when layout accuracy matters; do not assume every browser-specific CSS behavior will render identically. See DocRaptor’s [conversion guide](https://docraptor.com/documentation) for examples and current formatting guidance.
Relative assets and URL access
When sending an HTML string, relative links do not inherently identify a host. Set prince_options.baseurl if the document refers to relative images, stylesheets, or other resources. When using document_url, verify that the page and resources are accessible to DocRaptor. An asset that requires a logged-in browser session may not be retrievable simply because it works on your machine.
6. Handle the response and choose a delivery mode
For a synchronous successful request, the response body contains binary PDF data. Treat it as bytes: write it in binary mode or return the bytes from your server with an appropriate PDF content type. DocRaptor documents the X-DocRaptor-Num-Pages response header for PDF responses, which can help record the generated page count.
DocRaptor also documents hosted and asynchronous workflows. A hosted response provides a URL, while an asynchronous request returns a status identifier that you use to retrieve the completed document. Choose synchronous output for a request-response flow that can wait for generation; consider hosted or asynchronous handling when your application needs a separate retrieval or completion step. Follow the current API overview for the specific parameters and retrieval calls.
Generation errors can return XML, and HTTP status codes indicate success or failure. Always inspect the status before writing or serving a response as a PDF. A file extension does not make an error response a valid PDF.
7. Protect the API key
Keep production credentials on a server you control. DocRaptor’s browser integration submits a hidden form, but a key included in publicly accessible page code can be discovered. The [DocRaptor tutorial](https://docraptor.com/documentation/tutorial/html-and-javascript) warns against using that approach publicly and describes server-side or referrer-based workflows. Do not treat a test credential as a production configuration.
For a browser application, send the document data to your backend and have that backend authenticate to DocRaptor. Apply your own authorization and input-size controls at that endpoint so users cannot use your server as an unrestricted conversion proxy.
8. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| The saved file is not a readable PDF. | An error response was saved as if it were a successful binary result. | Check the HTTP status first and inspect the error body. Save bytes as a PDF only after a successful response. |
| The request is rejected or the document is missing. | type is not pdf, or neither document_content nor document_url is supplied. |
Send type: "pdf" and exactly the input your workflow needs. Refer to the [API reference](https://docraptor.com/documentation/api). |
| Images or styles are absent from supplied HTML. | Relative paths have no base URL, or an asset is unavailable to the conversion request. | Set prince_options.baseurl where appropriate and verify the asset URL is retrievable. |
| URL conversion cannot download the page. | The URL or a required resource is inaccessible to DocRaptor, or the document endpoint returned an error. | Check the URL from an unauthenticated server-side context where applicable, access restrictions, and the returned error details. |
| A chart or dynamic section is blank. | JavaScript is disabled, errors occurred, or rendering had not finished. | Enable the required JavaScript engine and use the documented completion signal for asynchronous rendering. Check script errors. |
| The output uses unexpected styling. | The selected media mode does not match the intended CSS, or a CSS behavior differs in the renderer. | Review prince_options.media, use print-specific CSS where needed, and validate the rendered result against the current formatting guide. |
| The key appears in browser tools or source. | A production key was embedded in client-side code. | Move the request to a server-side endpoint and rotate exposed credentials according to your account procedures. |
| The request times out in your application. | Your client timeout is shorter than document generation, or the synchronous workflow does not fit the job. | Choose a timeout appropriate to your workload or use the documented asynchronous workflow and retrieve the result by its status identifier. |
9. Performance, reliability, and cost considerations
- Enable only what the document uses. JavaScript is off by default and adds processing work when enabled. Static documents generally do not need it.
- Keep inputs and dependencies predictable. Supply stable HTML and accessible assets; dynamic pages add failure points such as script errors and late rendering.
- Make retries deliberate. Retry transient failures according to your application’s policy, but inspect status and error details first. Avoid blindly treating every failure as retryable.
- Choose the response workflow for latency. A synchronous request keeps the caller waiting for the PDF. Hosted or asynchronous modes change how the result is retrieved and may fit longer jobs better.
- Plan cost from current account information. The documentation reviewed here does not establish current pricing, account limits, retention terms, or service commitments. Check DocRaptor’s current account and policy documentation before budgeting or making operational promises.
Or skip the browser setup
If your goal is a PDF of a rendered web page rather than a document generated from your own HTML template, ScreenshotNeo can return a PDF from a single API request. This is a different workflow from sending HTML to DocRaptor. See the ScreenshotNeo API documentation for PDF options.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o page.pdf
Set the PDF output options described in the ScreenshotNeo documentation for PDF capture. ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and the response identifies page verdict and billing status in headers. Its MCP server gives AI agents tools to take screenshots, inspect page information, and capture PDFs. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for ScreenshotNeo’s free 1,000 shots per month, with no card required.
FAQ
Can I send HTML directly instead of hosting it?
Yes. Put the HTML string in document_content. Use document_url when DocRaptor should fetch the document from a URL.
Does DocRaptor run JavaScript by default?
No. JavaScript is disabled by default. Enable the needed engine only when the document depends on script-rendered content.
How do I know whether the response is a PDF?
Check for a successful HTTP status before handling the body as PDF bytes. Error responses can contain XML or other diagnostic content.
Can I safely call DocRaptor from frontend JavaScript?
A production API key embedded in public client code can be exposed. Use a server-side request path or a documented referrer-based workflow.
Does this guide cover spreadsheet output?
No. The API reference lists pdf, xls, and xlsx; this guide covers the PDF output type.


