Convert a URL to PDF in Node with fetch
Node 18+ ships fetch, so the whole recipe is two awaited calls and a writeFile: POST the url, read the receipt, GET the download with the same header.
The POST holds until the render finishes and answers with the receipt JSON. The receipt's download url is the GET that carries the bytes, and it needs the Authorization header again, because the download endpoint answers only to the key that made the render.
The recipe
import { writeFile } from "node:fs/promises";
const ORIGIN = "https://webcapture.io";
const res = await fetch(`${ORIGIN}/v1/convert`, {
method: "POST",
headers: {
"Authorization": "Bearer wc_your_key",
"Content-Type": "application/json",
},
body: JSON.stringify({"url": "https://example.com/"}),
});
if (!res.ok) throw new Error(`convert failed: ${res.status}`);
const receipt = await res.json();
// receipt.download: ${ORIGIN}/v1/conversions/cnv_9f2c01ab.pdf
// the download is key-scoped: the GET carries the same header
const file = await fetch(receipt.download, {
headers: { "Authorization": "Bearer wc_your_key" },
});
if (!file.ok) throw new Error(`download failed: ${file.status}`);
await writeFile("page.pdf", Buffer.from(await file.arrayBuffer()));
receipt.download is read as a property of the parsed receipt, and the GET that follows repeats the Authorization header. The receipt also carries bytes (the document's size), attempts, and remaining (renders left this month), which is everything a queue worker needs for logging. Res.text() on a failed convert carries the endpoint's JSON error, so the throw names the real cause.
Same-key GET: 401 without it; 404 for another key.
The fields this recipe uses
url: the page address to render, a public http(s) URL.
Related
- Next: Get a free key to run this Node recipe, or read the API docs.
- More recipes: Node: poll an async render, Node: download with the key, Python: convert from a URL.
- The webcapture API reference: every field the convert endpoint admits, with the response shapes and the error table.
- The recipes hub: the same endpoint in the other languages.
- Going deeper: on Node and leaving wkhtmltopdf behind? the Puppeteer comparison is the same migration at the engine level. Wiring the call into an automation stack? The n8n, Zapier, and Make guides carry the same request.
- The free URL to PDF tool: try the render in a browser before you wire the call.
Method
Source: convert field reference, checked 2026-10-05. Corrections.