FileToPDF.dev
API

HTML to PDF

Send HTML, get a pixel-perfect PDF.

Rendered in headless Chromium with full JavaScript execution.
Flexbox, CSS Grid, custom web fonts, Tailwind, Bootstrap — everything renders exactly as it does in the browser.

HTML to PDF
# Send an HTML string and get a pixel-perfect PDF
curl -X POST https://api.filetopdf.dev/html \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<html>\n<head>\n  <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap\" rel=\"stylesheet\">\n</head>\n<body>\n  <h1>Invoice #1042</h1>\n  <p>Amount due: <strong>$2,500.00</strong></p>\n</body>\n</html>",
    "css": "body { font-family: Inter, sans-serif; margin: 2in; }\nh1 { color: #1a1a2e; }"
  }' \
  --output output.pdf

Full JavaScript execution

Chart.js, D3, React, Vue — all JS runs before PDF capture.

Complete CSS support

Flexbox, CSS Grid, custom web fonts, Tailwind, Bootstrap.

Full PDF control

Paper size, margins, headers/footers, landscape, PDF/A.

Multi-file bundles

Send index.html with CSS, JS, images, and fonts in a single request.

Playground

Try it

Conversion Parameters

Configure optional rendering parameters.

Copy request as
Reference

Documentation

Endpoint

POSThttps://api.filetopdf.dev/html

Authentication

Include your API key in the x-api-key header. CORS is enabled.

Limits

Maximum total upload size is 30 MB (Starter & Pro) or 50 MB (Scale). Requests exceeding this limit are rejected with a 413 file_too_large error.

Parameters

This endpoint accepts two input formats. Use whichever fits your workflow.

Option A JSON body — for HTML strings

Send your HTML as a JSON string — no file uploads needed. Perfect for template engines, server-rendered HTML, or dynamically generated content. Use Content-Type: application/json.

FieldTypeRequiredDescription
htmlstringRequiredThe HTML content to render as PDF. Can be a full document or a fragment.
cssstringOptionalCSS styles injected as a <style> block into the document head. Convenient when you keep templates and styles separate.

Option B Multipart upload — for HTML + assets

Upload HTML files with linked CSS, JS, images, and fonts as multipart/form-data. Use this when your HTML references local assets by filename.

FieldTypeRequiredDefaultDescription
index.htmlfileRequiredThe HTML document to render. All assets are resolved relative to this file.
style.css, img.png, …fileOptionalAdditional assets (CSS, JS, images, fonts) referenced by filename in your HTML. Reference them by filename only — no paths.
header.htmlfileOptionalnoneFull HTML document rendered as a repeating page header. Inline styles only — external CSS and JS do not load here.
footer.htmlfileOptionalnoneFull HTML document rendered as a repeating page footer. Supports class="pageNumber" and class="totalPages" spans for automatic injection.

Conversion Parameters

These parameters work with both input options. Pass them as JSON fields (Option A) or form fields (Option B).

FieldTypeDefaultDescription
pdfaenumArchive-ready PDF format. PDF/A-1b has the widest support. Use PDF/A-3b if you also need to attach files (e.g. XML invoices). Mutually exclusive with encryption.
landscapebooleanfalseRotate the output to landscape orientation (wider than tall).
printBackgroundbooleanfalseInclude CSS background colors and images. Chromium strips backgrounds by default for print output — enable this if your design uses background styles.
paperWidthfloat (inches)8.5Page width in inches. A4 = 8.27, US Letter = 8.5. Overridden by preferCssPageSize.
paperHeightfloat (inches)11.0Page height in inches. A4 = 11.69, US Letter = 11.0. Overridden by preferCssPageSize.
marginTopfloat (inches)0.39Top margin in inches (~1 cm). Set to 0 for a full-bleed layout.
marginBottomfloat (inches)0.39Bottom margin in inches. Also controls the space available for a footer.html template.
marginLeftfloat (inches)0.39Left margin in inches.
marginRightfloat (inches)0.39Right margin in inches.
scalefloat1.0Content scale factor (0.1–2.0). Values below 1 shrink content; values above 1 enlarge it.
nativePageRangesstringRestrict output to specific pages. Accepts ranges (1-5), lists (1,3,5), or a mix (1,3-5). Pages are counted from 1.
waitDelaydurationFixed pause after page load before capture (e.g. '3s', '500ms'). Maximum: 15s. Use as a fallback when JS completion time is unpredictable. Prefer waitForExpression when possible.
waitForExpressionstring (JS expression)JavaScript expression evaluated in the page that must return true before capture (max 500 chars). Set window.status = 'ready' at the end of your script, then use waitForExpression=window.status === 'ready'.
preferCssPageSizebooleanfalseRead page dimensions from your CSS @page rule instead of paperWidth/paperHeight. Lets your stylesheet own the page size.
emulatedMediaTypeenumprintCSS media type Chromium emulates. 'print' strips backgrounds and applies @media print rules. 'screen' matches the browser viewport — use this if colors or backgrounds are missing.
singlePagebooleanfalseRender the entire document on one continuous page. Overrides paperHeight and nativePageRanges. Useful for receipts or full-page exports.
waitForSelectorstring (CSS selector)CSS selector of an element that must exist in the DOM before capture (max 500 chars). Ideal for SPAs — inject a sentinel element (e.g. <div id="app-ready">) when your data has finished loading.
omitBackgroundbooleanfalseRemove Chromium's default white background. Combined with a CSS transparent background, produces a PDF with a transparent base layer.
generateDocumentOutlinebooleanfalseGenerate a PDF bookmark pane from your HTML headings (<h1>–<h6>). Appears as a navigation sidebar in Acrobat and other viewers.
generateTaggedPdfbooleanfalseEmbed a logical structure tree (headings, paragraphs, images) for screen reader support. Required for PDF/UA accessibility compliance.
emulatedMediaFeaturesJSON arrayOverride CSS media features. Pass a JSON array of {name, value} objects. Example to force dark mode: [{"name":"prefers-color-scheme","value":"dark"}].
pdfuabooleanfalseApply PDF/UA (Universal Accessibility) post-processing. Pair with generateTaggedPdf for full compliance. Adds a second processing pass, so conversion is slower.
flattenbooleanfalseBake all interactive form fields (inputs, checkboxes) into static page content. The resulting PDF cannot be edited.
userPasswordstringPassword required to open the PDF. Mutually exclusive with PDF/A — setting both returns an error.
ownerPasswordstringPassword controlling PDF permissions (printing, copying, editing). Independent of userPassword.
metadataJSON objectXMP metadata to inject. Supported keys: Author, Title, Subject, Keywords (array), Creator, Producer, CreationDate, ModDate. Writing metadata breaks PDF/A compliance.
skipNetworkIdleEventbooleantrueWhen true (default), Gotenberg does NOT wait for zero network connections before converting. Set to false if your page fetches data via AJAX after initial load (dashboards, SPAs).
failOnConsoleExceptionsbooleanfalseFail the conversion (409) if any JavaScript exception is logged to the Chromium console during rendering. Essential for CI/CD quality gates on SPAs.
failOnResourceHttpStatusCodesJSON arrayFail conversion if any sub-resource (CSS, JS, images, fonts) returns a matching HTTP status. Use range convention: 499 = all 4xx, 599 = all 5xx.
extraHttpHeadersJSON objectCustom HTTP headers sent with every request during conversion. Supports scoped headers via ';scope=<regex>' to restrict to specific domains.
userAgentstringOverride the User-Agent header for all requests during conversion. Useful for forcing desktop/mobile layouts or identifying Gotenberg requests in server logs.

Response

Every endpoint supports two response formats. Choose the one that fits your integration.

Default Raw PDF binary

The response body is the PDF file itself. Pipe it straight to disk, return it to a client, or stream it to storage.

HeaderValue
X-Request-IdUnique request identifier
Content-Typeapplication/pdf
Content-Dispositionattachment; filename="filename.pdf"
Content-LengthPDF file size in bytes
X-Page-CountNumber of pages in the PDF
X-Credits-UsedConversions consumed (always 1)
X-Credits-RemainingConversions left in your cycle
X-Processing-TimeServer-side processing time (e.g. 1320ms)

Optional JSON with base64-encoded PDF

Add Accept: application/json to your request headers. The response body becomes a JSON object — useful for serverless functions, browser-based integrations, or pipelines where you need structured metadata alongside the PDF.

{
  "status": "success",
  "data": {
    "pdf": "JVBERi0xLjQgMSAwIG9i... (base64)",
    "filename": "output.pdf",
    "pages": 3,
    "size_bytes": 184320,
    "credits_used": 1,
    "credits_remaining": 49
  }
}

X-Request-Id and X-Processing-Time headers are still present on JSON responses.

FieldTypeDescription
statusstringAlways "success" on 200.
data.pdfstringBase64-encoded PDF binary. Decode and write to file, or embed as a data URI.
data.filenamestringSuggested filename for the converted PDF.
data.pagesnumberTotal page count of the generated PDF.
data.size_bytesnumberSize of the PDF file in bytes.
data.credits_usednumberNumber of credits consumed (always 1).
data.credits_remainingnumberCredits left in your billing cycle after this conversion.

Errors

All errors return JSON with error.code and error.message fields.

{
  "status": "error",
  "error": {
    "code": "missing_input",
    "message": "Missing input. Upload a file in the 'files' field, or provide a 'url' field."
  }
}
StatusCodeDescription
400missing_inputNo file uploaded and no url field provided.
400invalid_content_typeRequest is not multipart/form-data or application/json.
400unsupported_formatFile extension is not supported for PDF conversion.
400parse_errorCould not parse the multipart request body.
401missing_api_keyNo x-api-key header or Authorization token provided.
401invalid_tokenThe provided Firebase Auth token is invalid or expired.
402payment_requiredInsufficient credits. Top up or upgrade your plan.
402subscription_requiredNo active subscription found on the workspace.
403forbiddenInvalid API key, or user is not a member of the workspace.
405method_not_allowedRequest method is not POST.
408conversion_timeoutConversion exceeded the time limit.
413file_too_largeFile exceeds your plan's size limit (30 MB or 50 MB).
422conversion_failedThe document could not be converted to PDF.
429concurrency_limitToo many concurrent requests for your plan.
500internal_errorUnexpected server error. Retry or contact support.
503service_unavailableThe conversion service is temporarily unavailable.