How to Convert a URL to PDF with PDFCrowd’s API
Convert a reachable web page to PDF with PDFCrowd’s HTTP API. Learn the request format, binary response handling, rendering options, and common fixes.
To convert a reachable web page with PDFCrowd, send an authenticated multipart POST to https://api.pdfcrowd.com/convert/24.04/, put the page address in the url form field, and save the successful response body as PDF bytes. Use your PDFCrowd username as the HTTP Basic username and your API key as the password.
curl -f -s -S \
-u 'YOUR_USERNAME:YOUR_API_KEY' \
-o example.pdf \
-F url=https://example.com/ \
https://api.pdfcrowd.com/convert/24.04/
A successful response is 200 OK with Content-Type: application/pdf. The version is part of the endpoint; review PDFCrowd’s [HTTP API guide](https://pdfcrowd.com/api/html-to-pdf-http/) and versioning guidance before changing it. This article uses the documented API shape and does not claim a personally run conversion.
1. Set up credentials and the request
- Create or access a PDFCrowd account and obtain its API username and API key.
- Keep the key on the server or in a secret manager. Do not put it in browser JavaScript or commit it to source control.
- Send a form-encoded request for URL conversion, or multipart form data if uploading a file. JSON request bodies are not supported by this API.
- Check the HTTP status before treating the response as a PDF.
The credentials authenticate your call to PDFCrowd. They do not sign you in to the website being converted. For a protected source page, pass the site’s required cookies, website credentials, or custom HTTP header using the documented conversion settings.
2. Runnable examples
cURL
The official example uses multipart form data. The -f option makes cURL return a failure status for HTTP errors instead of silently treating the error body as a successful file.
curl -f -s -S \
-u 'YOUR_USERNAME:YOUR_API_KEY' \
-o example.pdf \
-F url=https://example.com/ \
https://api.pdfcrowd.com/convert/24.04/
For machine-readable error responses, add ?errfmt=json to the endpoint. It affects error formatting only; successful responses remain PDF bytes.
Python
This example uses the widely available requests package. Install it with python -m pip install requests, then run the script with credentials supplied through environment variables.
import os
import requests
username = os.environ["PDFCROWD_USERNAME"]
api_key = os.environ["PDFCROWD_API_KEY"]
endpoint = "https://api.pdfcrowd.com/convert/24.04/"
response = requests.post(
endpoint,
auth=(username, api_key),
files={"url": (None, "https://example.com/")},
timeout=75,
)
if response.status_code != 200:
raise RuntimeError(
f"PDFCrowd returned HTTP {response.status_code}: {response.text}"
)
content_type = response.headers.get("Content-Type", "")
if "application/pdf" not in content_type.lower():
raise RuntimeError(f"Expected PDF bytes, got Content-Type: {content_type}")
with open("example.pdf", "wb") as pdf_file:
pdf_file.write(response.content)
Set PDFCROWD_USERNAME and PDFCROWD_API_KEY in the process environment before running. The timeout is a client-side limit; it cannot extend PDFCrowd’s server-side processing limit.
Node.js
In current Node.js versions with built-in fetch, FormData, and Blob, send the form and write the returned bytes only after validating the status and content type.
import { writeFile } from "node:fs/promises";
const username = process.env.PDFCROWD_USERNAME;
const apiKey = process.env.PDFCROWD_API_KEY;
if (!username || !apiKey) {
throw new Error("Set PDFCROWD_USERNAME and PDFCROWD_API_KEY");
}
const endpoint = "https://api.pdfcrowd.com/convert/24.04/";
const form = new FormData();
form.set("url", "https://example.com/");
const basic = Buffer.from(`${username}:${apiKey}`).toString("base64");
const response = await fetch(endpoint, {
method: "POST",
headers: { Authorization: `Basic ${basic}` },
body: form,
signal: AbortSignal.timeout(75000),
});
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`PDFCrowd HTTP ${response.status}: ${errorBody}`);
}
const contentType = response.headers.get("content-type") ?? "";
if (!contentType.toLowerCase().includes("application/pdf")) {
throw new Error(`Expected application/pdf, got ${contentType}`);
}
await writeFile("example.pdf", Buffer.from(await response.arrayBuffer()));
Do not manually set the multipart Content-Type header in this example: the runtime adds the boundary required to parse the form.
3. Choose the right input source
| Input | Use it when | Important detail |
|---|---|---|
url |
The page is served over HTTP or HTTPS and reachable from PDFCrowd’s servers. | A local localhost address on your computer is not reachable by the service. |
text |
Your application already has the HTML string. | Use absolute resource URLs or an HTML <base> element for external CSS, images, and scripts. |
file |
You need to upload HTML and its local assets. | For related resources, upload a supported archive while preserving relative paths. If it contains multiple HTML files, specify zip_main_filename. |
For the complete accepted inputs and field details, consult PDFCrowd’s [parameter reference](https://pdfcrowd.com/api/html-to-pdf-http/ref/). HTML and file upload requests still use form fields; file uploads use multipart form data.
4. Adjust the rendered PDF
Add rendering settings as additional form fields beside url, text, or file. Check the parameter reference for each setting’s accepted values, availability, and default. The API overview lists these control groups:
- Page layout: paper size, margins, orientation, and page breaks.
- Headers and footers: supply HTML for repeated page furniture.
- Rendering behavior: viewport behavior, JavaScript delay, and waiting for an element before conversion.
- Content selection: use
element_to_convertto render a particular element. - Customization: add CSS or JavaScript, watermarks, and PDF options such as password protection, PDF/A, or tagged output where supported.
For example, the HTTP guide includes content_viewport_width=balanced explicitly in a sample. That is an example setting, not the API default. Avoid assuming a sample value or an omitted field’s behavior without checking the current reference. See the [PDFCrowd API overview](https://pdfcrowd.com/api/html-to-pdf-api/) for its feature categories.
5. Handle binary responses and errors
- Read the HTTP status and headers first.
- On success, expect
application/pdfand preserve the body as binary data. In Python, write bytes withwb; in Node.js, consume anArrayBufferor stream. Do not decode a successful body as UTF-8 or parse it as JSON. - On failure, retain the status, response body, and PDFCrowd reason code. Errors are plain text by default; use
errfmt=jsonwhen structured error data is useful. - Classify the failure before retrying: fix malformed input, settings, authentication, license, or credit problems directly. Retry only temporary failures, with a bounded retry count and increasing delays.
Applications that handle large PDFs can stream the response to storage instead of buffering it all in memory. Continue to verify status and content type before exposing the result as a downloadable PDF.
6. Limits, performance, privacy, and cost
Operational limits
PDFCrowd’s current HTTP guide states a maximum upload size of 300 MB and says conversions exceeding 60 seconds of processing time are stopped. Rate and concurrency limits depend on the license. These are vendor-published operational limits accessed in 2026 and may change; check the current [HTTP API guide](https://pdfcrowd.com/api/html-to-pdf-http/) before relying on them. Increasing your client timeout does not make a server-side conversion run longer.
Performance and reliability
- Convert public, stable URLs directly when the service can reach all required page resources.
- If a page builds content asynchronously, use a documented readiness option such as a JavaScript delay or wait-for-element field, while keeping the server-side execution limit in mind.
- Use a bounded retry policy with increasing delays only for transient failures. Avoid retry storms and do not retry bad credentials, invalid fields, or account-limit errors unchanged.
- Set client timeouts to cover connection and response handling, but treat the vendor’s processing limit as the hard constraint described by its current documentation.
Cost and trial
PDFCrowd’s pricing page currently states that a trial includes 100 test API credits valid for one month and that output consumes one credit per 0.5 MB. Prices and plan details should be checked in the live [PDFCrowd plan selector](https://pdfcrowd.com/pricing/); this guide does not assume a fixed price.
Privacy and retention
PDFCrowd says submitted HTML, uploaded files, and generated files are deleted from active processing systems within 30 minutes after they are no longer needed for conversion and result availability, with no backup copies of those files. Its security page also says converted URLs may be present in conversion logs under the account retention setting, with 14 days as the stated default and an option for no storage. These are the vendor’s current statements; review its [security and privacy information](https://pdfcrowd.com/data-security/) and applicable agreement before sending sensitive content.
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| HTTP 401 or authentication failure | Wrong username or API key, or malformed Basic authentication. | Use the PDFCrowd username as the Basic username and API key as the password. Check secret configuration and avoid logging credentials. |
| Source page cannot be fetched | The URL is local, private, blocked, malformed, or otherwise unreachable from PDFCrowd. | Provide a publicly reachable HTTP(S) URL or send the rendered HTML with text or file. |
| PDF omits images, styles, or scripts | Assets use local paths, inaccessible URLs, or load after conversion begins. | Use absolute URLs or a <base> element for HTML input, package local assets with the HTML archive, and configure a suitable readiness wait. |
| PDF is blank or content is missing | Page rendering is delayed, blocked behind authentication, or the wrong element was selected. | Configure source-site cookies or headers, wait for a reliable element, and verify element_to_convert matches the intended content. |
| Conversion stops near the processing limit | The page takes longer than the service’s stated maximum processing time. | Reduce page complexity or wait requirements, simplify the source, or render HTML/assets directly. A longer client timeout will not extend the server limit. |
| Upload rejected | The file or archive exceeds the upload limit or has an unsupported layout. | Keep uploads within the documented maximum, use a supported archive, preserve relative paths, and set zip_main_filename for a non-obvious entry page. |
| Response saved as a corrupt PDF | An error body was written to a file, or binary data was decoded as text. | Check status and Content-Type before writing; preserve raw response bytes on success and inspect the error body otherwise. |
| Rate, concurrency, or credit error | The account’s license or available credits do not permit the request. | Inspect the returned reason code and account limits, reduce concurrency or request volume, or review the current plan details. |
8. Or skip the browser setup
PDFCrowd converts a page to PDF. If your task is to capture a page as an image instead, ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. Its one-request API returns PNG, JPEG, WebP, or PDF output. The following call requests an image capture of Stripe; see the ScreenshotNeo docs for parameters and response handling.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
- Cookie and consent banners are accepted before capture; 60+ known consent platforms, newsletter popups, and chat widgets are removed. Each step can be turned off.
- Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Responses identify the page verdict and billing status in headers.
- An MCP server provides
take_screenshot,get_page_info, andcapture_pdftools for Claude, Cursor, and other MCP clients. - The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is available on every plan.
Sign up for 1,000 free screenshots a month, with no card required.
FAQ
Can I call PDFCrowd from any programming language?
Yes. The HTTP API uses a standard authenticated POST with form fields, so any language that can make HTTP requests and save a binary response can use it. PDFCrowd also documents client libraries in several languages.
Can PDFCrowd access a page on my development machine?
Not through your machine’s localhost. The URL must be reachable from PDFCrowd’s servers, or you should submit the HTML or a file upload.
Does errfmt=json make the success response JSON?
No. It requests JSON formatting for errors. A successful conversion still returns PDF bytes.
Should I use an SDK or direct HTTP?
Use an SDK if it fits your application and you want its language-specific interface. Direct HTTP is useful when you need a small dependency surface or are integrating from a platform without a suitable library; both still need correct authentication, status handling, and binary output handling.


