Send a JSON POST request to https://api.html2pdf.app/v1/generate with your API key in the X-API-Key header. For a successful synchronous conversion, Html2Pdf.app returns PDF bytes in the response body—not JSON—so check the HTTP status before saving response.content to a file.
What you need
- Python 3.10 or newer.
- The
requestspackage, installed withpip install requests. - An Html2Pdf.app API key. The provider says it emails the key after registration.
Run this integration in a trusted backend, server-side script, or job. Keep the API key out of browser JavaScript, public repositories, and client-side templates.
Make and save a PDF with Python requests
Set the key in your environment before running the script. For example, on macOS or Linux:
export HTML2PDF_API_KEY='your-api-key'
Then save this as generate_pdf.py and run python generate_pdf.py:
#1 Best Overall
import os
from pathlib import Path
import requests
api_key = os.environ["HTML2PDF_API_KEY"]
response = requests.post(
"https://api.html2pdf.app/v1/generate",
json={"html": "https://www.example.com"},
headers={"X-API-Key": api_key},
timeout=60,
)
response.raise_for_status()
Path("document.pdf").write_bytes(response.content)
The required JSON property is html. It can contain a publicly reachable webpage URL, as in the example, or raw HTML markup. The renderer must be able to reach the URL and its dependent resources. The timeout in the example prevents the client from waiting indefinitely; adjust it for your application’s request and job limits.
raise_for_status() stops the script on an HTTP error instead of saving an error response as if it were a PDF. On success, write the response as bytes: do not call response.json() or decode it as text.
Send HTML and control the PDF layout
Put rendering options in the JSON body alongside html. For example, this payload requests an A4 PDF using print CSS, sets margins in pixels, and supplies a filename:
Rank #2
payload = {
"html": "<h1>Invoice</h1><p>Total: $240.00</p>",
"format": "A4",
"media": "print",
"marginTop": 40,
"marginRight": 32,
"marginBottom": 40,
"marginLeft": 32,
"filename": "invoice.pdf",
}
response = requests.post(
"https://api.html2pdf.app/v1/generate",
json=payload,
headers={"X-API-Key": os.environ["HTML2PDF_API_KEY"]},
timeout=60,
)
response.raise_for_status()
Path("invoice.pdf").write_bytes(response.content)
The documented layout and rendering controls include:
- Paper size: Letter, Legal, Tabloid, Ledger, and A0 through A6.
- Orientation and dimensions: portrait or landscape, or a custom width and height.
- Margins: top, right, bottom, and left values in pixels.
- CSS media:
printorscreen. The selected mode can change which styles are applied. - Scale: adjust the rendered page scale.
- Headers and footers: provide templates for PDF headers and footers.
- Filename and PDF controls: set a filename and configure password or permission settings.
- JavaScript and asynchronous content: use
waitForfor a documented delay from 0 to 10 seconds when a page needs more time to load scripts or resources.
Rendering can vary with the selected CSS media mode, available fonts and other resources, and JavaScript timing. If a page is missing styles or content, first verify what the renderer can reach and when the page finishes loading.
Use POST for ordinary integrations
POST with a JSON body is the practical default: it avoids query-string escaping and length issues, especially when html contains markup or a long template. GET is also supported, but its query parameters must be URL-encoded; the provider cautions against using GET for raw HTML or long template values.
Choose synchronous conversion or a callback
The synchronous flow above holds the HTTP request open while conversion runs, then returns the finished PDF bytes in that same response. That is simplest when your caller can wait for the conversion.
For queued work, include callBackUrl and optionally state in the request body. The endpoint responds with 202 Accepted when it queues the job; that response is not the PDF. When conversion finishes, Html2Pdf.app sends JSON to your callback URL. Its document field contains the PDF encoded as base64, and the submitted state is returned unchanged.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use a publicly reachable HTTPS callback endpoint. Make callback handling idempotent because a delivery may be attempted more than once; the provider documents up to three retries for failed callback deliveries. Decode the base64 document before saving or serving the PDF. Keep the job identifier or your own correlation value in state so the callback can be matched to the original work.
| Workflow | When the PDF is available | Representation | What your application must handle |
|---|---|---|---|
| Synchronous | In the response to the conversion request | Binary response body | Keep the request open, check the status, and save or return the bytes. |
| Callback | Later, after the job is processed | Base64 data in the callback JSON’s document field |
Expose an HTTPS callback endpoint, correlate the job, handle repeat deliveries idempotently, and decode the data. |
Troubleshoot common errors and rendering problems
| Symptom | Likely cause | What to do |
|---|---|---|
400 response |
The source URL is inaccessible or a parameter is invalid. | Check that the renderer can reach the URL and verify each option’s name and value before retrying. |
401 response |
The API key is missing or invalid. | Confirm the X-API-Key header is present and that the environment variable contains the correct key. |
403 response |
The account has reached a plan limit. | Review the account limit and notification before trying again; repeating the same request will not resolve the limit. |
500 response |
An unhandled server error occurred. | Retry after a short delay, increasing the delay between attempts. Contact support if the error persists. |
| PDF is blank or styles are missing | The page, CSS, fonts, or images may not be reachable to the renderer, or content may not be ready when capture begins. | Confirm the source is public and its resources load without a browser-only session. Check whether media should be print or screen, and use waitFor for pages that need extra load time. |
| A saved file is not a valid PDF | An error or queued-job response may have been saved as though it were PDF bytes. | Check the HTTP status before writing the body. In callback mode, wait for the callback and decode its base64 document; a 202 response only indicates that the job was accepted. |
Do not automatically retry 400, 401, or 403 responses until you have corrected the input, credentials, or account-limit issue. A retry policy with increasing delays is appropriate for a persistent server-side failure, but avoid retrying without a limit.
Protect credentials and consider data handling
Keep the API key on the server. The provider’s documentation says generated PDFs are processed temporarily and not permanently stored on its servers; it also says raw HTML or text submitted in html is not stored in conversion logs. The documentation says selected request metadata and a source URL supplied in html may be retained in those logs. These are the provider’s stated practices, not an independent audit; consult its Privacy Policy and Data Processing Agreement for its detailed terms before sending sensitive content.
Or skip the browser setup
If what you need is a webpage screenshot rather than a custom HTML-to-PDF workflow, ScreenshotNeo offers a screenshot API and MCP server. Its one-call API can return an image or PDF; the example below saves a WebP screenshot:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Best Value
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for request options. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for free.
Frequently Asked Questions
Can the html field contain markup instead of a URL?
Yes. It accepts raw HTML or a publicly reachable URL; POST with JSON is preferable for markup and long values.
Does a 202 Accepted response contain the finished PDF?
No. In callback mode it means the job was queued; the PDF arrives later as base64 in the callback JSON’s document field.
Can I use the API key in browser-side JavaScript?
No. Keep it in backend code, server-side scripts, or trusted jobs rather than exposing it to visitors.
Recommended Free Tools
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




