Skip to content

URL to PDF

POST /render/url fetches the HTML at a public URL, then renders it through the same engine as HTML to PDF. Use it when the document already exists at a URL — a static site, a server-rendered page, a published invoice link — and you do not want to download and re-post the HTML yourself.

Terminal window
curl -X POST http://localhost:8080/render/url \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/page"}' \
--output out.pdf

The fetched URL becomes the base URL for the rendered document, so relative <img>, <link>, and <script> references inside the page resolve against the originating site automatically.

The JSON body accepts these fields:

FieldDefaultMeaning
urlThe http or https URL to fetch (required)
attachmentsOptional PDF/A-3 file attachments to embed in the output, identical to /render/html
embedColorProfiletrueEmbed the ICC output intent and produce PDF/A-3a + PDF/UA output. Set to false only when you explicitly need PDF/UA output without the PDF/A color profile.

The API performs three steps in order:

  • Fetch. Sends a single anonymous GET to the URL, with a configurable timeout and response size cap. Redirects are not followed (see Security below); a 3xx response is treated as a fetch failure.
  • Validate. Checks that the response status is 2xx and that Content-Type is text/html or application/xhtml+xml. The declared charset is honoured when decoding the body; missing or unknown charsets fall back to UTF-8.
  • Render. Hands the decoded HTML to the same PDF/A-3a + PDF/UA pipeline used by POST /render/html, with the fetched URL as the rendering base URL.

This endpoint shares the renderer with HTML to PDF, so the same support matrix applies:

  • CSS 2.1, @page, @font-face, inline SVG and raster images are supported.
  • JavaScript, Flexbox, Grid, and CSS animations are not. Pages that rely on client-side rendering produce empty or skeletal output.

Use this endpoint for static and server-rendered pages. For SPAs, render to HTML first with your own tooling and call POST /render/html instead.

The URL is fetched under the same guard as image assets:

  • Only http and https schemes are accepted.
  • The optional SSRF guard rejects loopback, private, link-local, and wildcard addresses before any request leaves the API. It is disabled by default (TRUST_PRIVATE_HOSTS=true) so the API works against internal hosts out of the box. Set TRUST_PRIVATE_HOSTS=false on any internet-facing deployment to enable the guard.
  • Redirects are not followed, so a redirect target cannot smuggle the request to an internal host.
  • The response body is read through a bounded stream and capped at the configured maximum size, even if the server omits Content-Length.

Set ASSET_ALLOWED_DOMAINS to restrict which hosts may be fetched.

The fetcher shares the existing asset configuration:

VariableDefaultMeaning
ASSET_TIMEOUT60000Connect and request timeout in milliseconds
ASSET_MAX_SIZE52428800Maximum response body size in bytes
ASSET_ALLOWED_DOMAINSOptional comma-separated allowlist of fetchable hosts; empty means any public host
TRUST_PRIVATE_HOSTStrueWhen true (default), the API will fetch URLs that resolve to loopback, private, or link-local addresses. Set to false to enable the SSRF guard. The http/https scheme check and ASSET_ALLOWED_DOMAINS allowlist always apply.
  • 200 OK — the rendered PDF as application/pdf, or { validation, pdf } when you send Accept: application/json. JSON negotiation cannot be combined with X-Upload-Url.
  • 400 Bad Request — the URL is missing, malformed, blocked by the SSRF guard, returned a non-2xx status, exceeded the size cap, or did not return HTML. The response body contains an error field with the reason.
  • 500 Internal Server Error — the PDF rendering pipeline failed unexpectedly.