Run Gotenberg in Docker, then send a multipart POST request to /forms/chromium/convert/html with a file named index.html. Upload every stylesheet, image, font, or script the document needs in the same request, save the successful response body as a PDF, and reference those assets by filename. If the source is already a reachable website, use /forms/chromium/convert/url instead; that route does not accept file:// addresses.
This guide covers local files, remote URLs, asset paths, dynamic pages, Python and Node.js clients, failure handling, and an option that avoids maintaining a browser container when you only need a rendered capture.
Choose the Gotenberg route that matches your input
Gotenberg uses headless Chromium to render HTML and return a file. The two relevant routes differ by where Chromium obtains the document:
| Input | Route | Request field | Important constraint |
|---|---|---|---|
| Local HTML plus uploaded assets | /forms/chromium/convert/html |
Multipart files, including index.html |
Uploads are placed in one flat directory; use filename references. |
| Web page available at a URL | /forms/chromium/convert/url |
Multipart url |
file:// URLs return HTTP 400. |
Use the HTML route when the source is on disk or must remain private. Use the URL route when the page is publicly or internally reachable by the Gotenberg container and its JavaScript needs to run in a browser context.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstall#1 Best Overall
- Scanner type: Document
- Connectivity technology: USB
- With Auto Scan Mode, the scanner automatically detects what you're scanning
- Digitize documents and images
Start Gotenberg with Docker
Gotenberg is documented as a Docker-based conversion API. Publish port 3000 and run the container:
docker run --rm -p "3000:3000" gotenberg/gotenberg:8
Leave that process running. The API is then available at http://localhost:3000 from the host. In a deployed setup, put the container on a private network and expose the API only to trusted callers; the conversion service can fetch URLs and process uploaded content, so it should not be treated as an unauthenticated public endpoint.
Convert a local HTML file
- Prepare the entry file. Name the uploaded document
index.html. The HTML route requires that filename; a file calledreport.htmlshould be copied or renamed before submission. - Collect dependencies. Put images, CSS, fonts, and scripts beside the document for the upload. Every dependency that is not available from a reachable URL must be sent as another multipart
filespart. - Use filename-based references. If you upload
logo.png, referencelogo.pngin the HTML. Do not use/logo.png,./assets/logo.png, or an absolute path from your workstation: Gotenberg stores uploaded files in a flat directory. - POST the form and write the response. A successful conversion is HTTP 200 and the response body is the PDF.
A minimal document might look like this:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<img src="logo.png" alt="Company logo">
<h1>Invoice</h1>
</body>
</html>
Submit it with cURL:
curl
--request POST http://localhost:3000/forms/chromium/convert/html
--form files=@/path/to/index.html
--form files=@/path/to/styles.css
--form files=@/path/to/logo.png
-o invoice.pdf
For a document with no external assets, the shorter request is sufficient:
curl
--request POST http://localhost:3000/forms/chromium/convert/html
--form files=@/path/to/index.html
-o my.pdf
Do not print the binary response to a terminal. The -o option writes the PDF exactly as returned by Gotenberg.
Call the same endpoint from Python
The following example uploads the entry file and an image, checks the HTTP result, and writes the PDF:
Rank #2
- FAST SPEEDS - Scans color and black and white documents a blazing speed up to 16ppm (1). Color scanning won’t slow you down as the color scan speed is the same as the black and white scan speed.
- ULTRA COMPACT – At less than 1 foot in length and only about 1. 5lbs in weight you can fit this device virtually anywhere (a bag, a purse, even a pocket).
- READY WHENEVER YOU ARE – The DS-640 mobile scanner is powered via an included micro USB 3. 0 cable allowing you to use it even where there is no outlet available. Plug it into you PC or laptop and you are ready to scan.
- WORKS YOUR WAY – Use the Brother free iPrint&Scan desktop app for scanning to multiple “Scan-to” destinations like PC, Network, cloud services, Email and OCR. (2) Supports Windows, Mac and Linux and TWAIN/WIA for PC/ICA for Mac/SANE drivers. (3)
- OPTIMIZE IMAGES AND TEXT – Automatic color detection/adjustment, image rotation (PC only), bleed through prevention/background removal, text enhancement, color drop to enhance scans. Software suite includes document management and OCR software. (4)
import requests
url = "http://localhost:3000/forms/chromium/convert/html"
with open("index.html", "rb") as html_file, open("logo.png", "rb") as image_file:
files = [
("files", ("index.html", html_file, "text/html")),
("files", ("logo.png", image_file, "image/png")),
]
response = requests.post(url, files=files, timeout=90)
response.raise_for_status()
with open("output.pdf", "wb") as pdf_file:
pdf_file.write(response.content)
The tuple filename for the first part is deliberately index.html. If your local path has another name, setting the multipart filename to index.html satisfies the route’s requirement.
Call it from Node.js
Node.js versions with built-in fetch, FormData, and Blob can submit the files without an additional HTTP library:
import { readFile } from "node:fs/promises";
const form = new FormData();
form.append("files", new Blob([await readFile("index.html")], { type: "text/html" }), "index.html");
form.append("files", new Blob([await readFile("styles.css")], { type: "text/css" }), "styles.css");
form.append("files", new Blob([await readFile("logo.png")], { type: "image/png" }), "logo.png");
const response = await fetch("http://localhost:3000/forms/chromium/convert/html", {
method: "POST",
body: form
});
if (!response.ok) {
throw new Error(`Gotenberg returned ${response.status}: ${await response.text()}`);
}
const pdf = Buffer.from(await response.arrayBuffer());
await import("node:fs/promises").then(({ writeFile }) => writeFile("output.pdf", pdf));
Do not set a manual Content-Type header for a FormData request. The runtime adds the multipart boundary; overriding it can make Gotenberg reject an otherwise valid upload.
Recommended Free Tools
Make asset paths work in a flat upload directory
The HTML route does not preserve your local directory tree. Uploading assets/logo.png does not create an assets directory inside the conversion workspace. Either upload the file with the flat filename and change the document to logo.png, or generate a self-contained HTML document with data URLs.
- Use relative filename references such as
styles.cssandlogo.png. - Upload each referenced local file as its own
filespart. - Keep names unique; two files with the same basename can collide in the flat workspace.
- For remote fonts, images, or stylesheets, verify that Chromium in the container can reach the host and that the server returns them without an interactive login.
A missing asset often produces a valid-looking PDF with blank areas rather than an HTTP error, so inspect the output visually and check the browser-facing URLs independently.
Rank #3
- Up to 255 customize favorite scan file setting with "Single Touch" , Support Windows 7/8/10
- Turn paper documents into searchable, editable files - save scans as searchable PDF files; OCR function included
- Info Barcode function - automatic categorization of complicate documentation and data with 1D or 2D Barcode page.
- Intelligent color and image adjustments — Auto Rotate, Crop, Deskew and blank page remove with Plustek Image Processing Technology
- Easy send scanned files to FTP server or personal NAS (FTP) with PDFs , Jpeg , TIFF or Png format. User can download scanner driver from Plustek website
Convert a page that already has a URL
For a web page, submit the address in the url form field to the URL route:
curl
--request POST http://localhost:3000/forms/chromium/convert/url
--form url=https://example.com
-o page.pdf
The URL must be reachable from the Gotenberg container, not merely from your laptop. A hostname available only through a host-machine shortcut may fail from inside Docker. The URL route supports JavaScript execution and waiting controls, which makes it suitable for applications that build their content after the initial response.
Do not pass a local path as file://. That input returns HTTP 400. Serve the document over an HTTP endpoint that the container can reach, or use the HTML route and upload the files directly.
Wait for dynamic content before rendering
Chromium can execute page JavaScript, but conversion can begin before an asynchronous chart, API response, image, or font has finished. The route documentation provides request controls for waiting:
- Fixed delay: pause for a known number of milliseconds when the page has a predictable startup time.
- DOM selector or expression: continue only after a marker element or condition indicates that rendering is complete.
- Failed-asset behavior: configure how conversion reacts when a resource fails instead of silently accepting an incomplete page.
Choose the smallest wait that reliably produces complete output. A long fixed delay increases latency without guaranteeing correctness when an upstream request is slow. A selector that your application adds after data binding is usually more deterministic. Treat these as request controls, not a promise that every third-party page will finish successfully.
Rank #4
- Note: No software installation is required. You need 2 AA batteries ( not included) and a memory card ( included) to use it directly. Scan mode: Press and hold "Scan" for 2 seconds to turn on the device, and then press "Scan", the green light is on. The scanner moves to scan the file until the green light turns off automatically (or press the "Scan" key and the green light goes out). The number shown on the display increases by 1 to indicate that the scan is complete.
- Portable Scanner scans images or pictures quickly: Store JPEG/PDF files within seconds, scan images or pictures quickly, plug and play, no need any software preinstalled. Compatible with Windows XP/7/Vista/Mac OS 10.4 or above version.
- Lightweight and travel-friendly: Stored in Micro SD card directly, support read data on your computer or phone with USB connected. Powered by 2pcs AA batteries, Compact Design, it is convenient to carry outside.
- 3 Image Resolution: 3 modes of resolution for your options: 300dpi/600dpi/900dpi, you can save it at the clearest way, picture and document are showed clear as it is. Freely choose your favorite resolution.File Format: JPEG/PDF format is all available, Great storage capacity as it supports 32G Micro SD card(Included 16GB Card),total meet your need for business trip or daily use.
- Widely Used: It is applicable in bank, insurance business, real estate agency,home, office, library or outdoors. suitable for lawyer, businessmen, students, travelers and amateur archivists. Scan your important files and save them immediately, no struggling in finding a printing shop, keep it confidential.
Understand responses and failure modes
| HTTP result | Meaning | What to check |
|---|---|---|
| 200 | PDF created; the response body contains the file. | Save the binary body and verify the PDF opens. |
| 400 | Invalid form input, including an unsupported field or a file:// URL on the URL route. |
Check the route, field names, and required index.html filename. |
| 503 | Conversion did not complete within the configured maximum duration. | Inspect page reachability, asset waits, JavaScript work, and resource availability; then adjust the request or deployment limits. |
All conversion routes use a multipart/form-data POST and return a file. Have clients check the status before writing the body as a PDF; otherwise an error message can be saved with a .pdf extension.
Troubleshoot the common problems
“Required file index.html is missing”
The multipart filename is not index.html. Rename the local file or set the upload filename explicitly, as shown in the Python and Node.js examples.
The PDF has no logo or styles
Upload every local dependency and replace directory or absolute paths with flat filenames. For remote dependencies, test reachability from the container and confirm the server does not require a browser-only session.
The URL conversion returns 400
Confirm that you used /forms/chromium/convert/url with a url field and an HTTP(S) address. Local file:// addresses are not accepted; use the HTML upload route instead.
The page is cut off before data appears
Add a selector-based or delay-based wait for the asynchronous work, and configure failed-asset handling where appropriate. A wait cannot repair an API that never responds, so inspect the page’s network dependencies as well.
Free tools Windows power users keep installed
One-click scans. No signup required.
Best Value
- PORTABLE SCANNER FOR USE ON-THE-GO — The fastest and lightest mobile single-sheet-fed compact document scanner in its class¹
- QUICK DOCUMENT SCANNING ― This Epson ultra-fast scanner scans a single page as quickly as 5.5 seconds²; Windows and Mac compatible
- VERSATILE PAPER HANDLING ― Portable scanner scans documents up to 8.5 x 72 in; Also easily digitizes receipts and ID cards to make accounting, bookkeeping, and organizing simpler
- INTUITIVE, HIGH-SPEED SOFTWARE — Epson ScanSmart Software³ is a smart tool allowing you to easily scan, review, and save; Stay organized easily with the help of this Epson scanner
- EASY SETUP — USB-powered connect to your computer for quick and simple scanning; No batteries or external power supply required to operate portable document scanner; Standard Connectivity: USB 2.0
The request ends with 503
Look for a slow remote host, infinite JavaScript activity, an overly ambitious wait, or a resource that never loads. Reduce unnecessary work, make the completion condition explicit, and ensure the container can reach every required host.
The PDF opens as an error document
Check the HTTP status before saving. A 400 or 503 response is not a PDF even if your script writes it to output.pdf.
Operational notes for reliable conversions
- Keep the input deterministic. Bundle critical CSS, images, and fonts when possible instead of relying on third-party hosts.
- Use bounded waits. Selector-based completion avoids an arbitrary long sleep, while a fixed delay is useful only when the page’s timing is stable.
- Validate output. Record the status code, preserve the response headers and size, and perform a PDF-open or page-count check in your own pipeline.
- Plan for transient failures. Retry only failures that are plausibly temporary, with a limit and backoff; repeatedly retrying a page that always times out increases load without improving the result.
- Do not infer a benchmark. Conversion time depends on HTML complexity, asset size, JavaScript, network conditions, and the container’s resources. The route documentation does not establish a universal throughput or latency figure.
Or skip the browser setup
If your requirement is a rendered image or PDF of a reachable web page rather than a self-hosted HTML-to-PDF pipeline, ScreenshotNeo provides a single request. Its API can return PNG, JPEG, WebP, or PDF; the example below captures a page and saves the response:
ScreenshotNeo API documentation
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Before capture, ScreenshotNeo accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing result in X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Create a free ScreenshotNeo account to try it without a card.
Which approach should you use?
- Choose Gotenberg’s HTML route when your application owns local HTML and must upload its exact assets.
- Choose Gotenberg’s URL route when a reachable page must be rendered with browser JavaScript and explicit waits.
- Choose ScreenshotNeo when you want a managed capture endpoint, cleaned pages, billing only for clean shots, or MCP tools instead of operating the browser container yourself.
Frequently Asked Questions
Can I submit several HTML documents in one Gotenberg request?
The documented HTML workflow requires one uploaded entry file named index.html. Generate separate requests when you need separate documents.
Does Gotenberg preserve my local assets directory?
No. Uploaded files share a flat directory, so directory-based paths are not preserved; use uploaded basenames or embed the assets.
What should a client do with a non-200 response?
Read and log the status and error body, then stop before writing the response as a PDF. The documented HTML route uses 400 for invalid input and 503 for a conversion that exceeds its maximum duration.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteQuick 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.

