You cannot pipe header or footer markup directly into wkhtmltopdf through stdin. The --header-html and --footer-html options expect a URL or file location. wkhtmltopdf’s stdin mode, --read-args-from-stdin, reads command-line arguments, not the contents of those HTML documents. Generate temporary files, serve the markup from a local URL, or pass a batch command that points to those resources.
What wkhtmltopdf reads from stdin
There are two separate input paths, and confusing them causes most failed attempts:
| # | Preview | Product | Price | |
|---|---|---|---|---|
| 1 |
|
Image to PDF Converter | Buy on Amazon |
--header-html <url>and--footer-html <url>receive a location. That location may be a local file or a URL whose response is an HTML document.--read-args-from-stdinreceives one complete wkhtmltopdf command line per input line. It does not reinterpret the next lines as header or footer document bodies.
Consequently, this does not do what it appears to do:
printf '%s' '<div>My header</div>' | wkhtmltopdf --header-html - input.html output.pdf
The hyphen is not a documented stdin resource for --header-html. Use a file path or an HTTP URL instead. A temporary file is normally the simplest bridge for generated markup and does not need to remain after the conversion.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitches#1 Best Overall
- All item converter to pdf
Use a temporary HTML file for a single conversion
Create a private temporary directory, write one document for each resource, and pass those paths to wkhtmltopdf:
tmpdir=$(mktemp -d)
cat >"$tmpdir/header.html" <<'HTML'
<!doctype html>
<html>
<body>
<div class="header">My header</div>
</body>
</html>
HTML
cat >"$tmpdir/footer.html" <<'HTML'
<!doctype html>
<html>
<body>
<div class="footer">Confidential</div>
</body>
</html>
HTML
wkhtmltopdf
--header-html "$tmpdir/header.html"
--footer-html "$tmpdir/footer.html"
input.html output.pdf
rm -rf "$tmpdir"
Both resources can be complete HTML documents. Keep their styles self-contained unless you deliberately provide stylesheet and image URLs that the wkhtmltopdf process can reach. The temporary directory is preferable to a predictable filename because separate jobs cannot accidentally overwrite one another.
Make cleanup reliable
When conversion can fail, register cleanup before running wkhtmltopdf. This also handles an interrupt:
set -eu
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT INT TERM
cat >"$tmpdir/header.html" <<'HTML'
<!doctype html><html><body><div>Build report</div></body></html>
HTML
cat >"$tmpdir/footer.html" <<'HTML'
<!doctype html><html><body><div>Generated for the release pipeline</div></body></html>
HTML
wkhtmltopdf
--header-html "$tmpdir/header.html"
--footer-html "$tmpdir/footer.html"
input.html output.pdf
Use a unique directory for every conversion, especially in a worker pool. Never put untrusted markup in a shared predictable path.
Generate a dynamic header or footer without a permanent file
“Without writing a permanent file” generally means “write an ephemeral file and remove it after the process exits.” Generate the markup from variables, then pass the resulting path:
set -eu
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT INT TERM
report_name="${REPORT_NAME:-Nightly build}"
created_at=$(date -u '+%Y-%m-%d %H:%M UTC')
cat >"$tmpdir/header.html" <HTML
<!doctype html>
<html><body>
<div class="header">${report_name}</div>
</body></html>
HTML
cat >"$tmpdir/footer.html" <HTML
<!doctype html>
<html><body>
<div class="footer">Created ${created_at}</div>
</body></html>
HTML
wkhtmltopdf
--header-html "$tmpdir/header.html"
--footer-html "$tmpdir/footer.html"
input.html output.pdf
The unquoted heredoc deliberately expands the shell variables. If values can contain user input, escape them for HTML before writing them; otherwise a value containing markup can change the document or break the resource.
Page numbers and document substitutions
The official usage documentation lists these header/footer text substitutions: [page], [frompage], [topage], [webpage], [section], [subsection], [date], [isodate], [time], [title], [doctitle], [sitepage] and [sitepages]. For example:
wkhtmltopdf
--header-html "$tmpdir/header.html"
--footer-html "$tmpdir/footer.html"
--footer-right "Page [page] of [topage]"
input.html output.pdf
These substitutions are documented for header/footer text options. If your build leaves tokens literal inside an HTML resource, keep the page-number expression in --footer-right (or another text option) and use the HTML resource for branding and layout.
Free tools Windows power users keep installed
One-click scans. No signup required.
Use --read-args-from-stdin for batch jobs
Stdin is useful when you need to feed many invocations to one wkhtmltopdf process. Each line is a command line; the line must point to already-created header and footer resources:
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
cat >"$tmpdir/header.html" <<'HTML'
<!doctype html><html><body><div>Batch header</div></body></html>
HTML
cat >"$tmpdir/footer.html" <<'HTML'
<!doctype html><html><body><div>Batch footer</div></body></html>
HTML
printf '%sn'
"--header-html $tmpdir/header.html --footer-html $tmpdir/footer.html input-1.html output-1.pdf"
"--header-html $tmpdir/header.html --footer-html $tmpdir/footer.html input-2.html output-2.pdf"
| wkhtmltopdf --read-args-from-stdin
Do not append the header markup to those lines and do not expect a later line containing HTML to become the resource. Shell quoting also matters: paths containing spaces must be quoted in each command line, and a robust batch producer should generate escaped command lines or use paths without spaces.
Serve generated markup from a local URL instead
A local HTTP service is useful when many workers share templates, when the HTML references relative assets, or when a separate rendering service already exists. The command still supplies a URL, not the document body:
wkhtmltopdf
--header-html http://127.0.0.1:8080/jobs/42/header.html
--footer-html http://127.0.0.1:8080/jobs/42/footer.html
input.html output.pdf
Bind the service only where the converter can reach it, give each job an unambiguous identifier, and return the correct content type and character encoding. A local URL adds a server dependency and a network request, but it avoids filesystem sharing between isolated containers. Confirm that the installed wkhtmltopdf build is permitted to fetch the URL and any referenced assets.
Recommended Free Tools
Fit the header and footer inside the page margins
Header and footer spacing is measured separately from the header/footer document itself. If the reserved space is larger than the corresponding page margin, the content can be pushed outside the printable page or clipped. Increase the top margin for a header and the bottom margin for a footer, then adjust the spacing settings in small increments:
wkhtmltopdf
--margin-top 28mm
--margin-bottom 24mm
--header-spacing 4
--footer-spacing 4
--header-html "$tmpdir/header.html"
--footer-html "$tmpdir/footer.html"
input.html output.pdf
Measure the actual rendered header rather than guessing from CSS height. A large top margin with a small header wastes space; a small margin causes overlap or clipping. The libwkhtmltox page-settings reference names the HTML resource setting header.htmlUrl and documents the separate spacing and margin interaction.
Choose files or a local service
| Approach | Process isolation | Cleanup and concurrency | Assets | Best fit |
|---|---|---|---|---|
| Per-job temporary files | Strong when each job has its own directory | Simple with mktemp and a cleanup trap; safe for parallel jobs |
Local relative assets may need file access or absolute URLs | One-off and worker-based conversions |
| Local HTTP service | Central service must be secured and reachable | Templates persist; job routing and expiry are your responsibility | Convenient for shared CSS, images and fonts reachable by URL | High-throughput or containerized pipelines |
| Batch stdin | One wkhtmltopdf process handles multiple command lines | Resources still need separate files or URLs; isolate paths per job | Same rules as the selected file/URL resource | Queued conversions where process startup is expensive |
Check wkhtmltopdf --version on every deployment target. Header and footer HTML rely on the patched-Qt features supplied by supported builds; some distribution packages are compiled without those features or expose a reduced option set.
Troubleshooting
“Unknown long option –header-html”
Your executable may be a reduced or differently packaged build. Compare the output of wkhtmltopdf --version on the failing host with a build that includes the patched-Qt header/footer features, and verify the option list before changing your command.
The process waits forever when I pipe HTML
--read-args-from-stdin waits for command lines and end-of-file. It never treats arbitrary HTML as a header document. Send one complete argument line per invocation and close stdin, or omit stdin mode and run a normal command with file or URL arguments.
The header or footer is missing
Check the path or URL from the same account and container that runs wkhtmltopdf. Confirm that the file is readable, that the local service is listening on the expected address, and that the HTML has a complete body. Then inspect the PDF margins; an element outside the reserved margin can appear to be absent.
The content overlaps the page
Increase --margin-top or --margin-bottom and reduce the corresponding spacing. Avoid relying on a CSS height that does not match the rendered content, especially when fonts or images load asynchronously.
Images, CSS or fonts are absent
Relative references resolve from the header/footer resource location. A file resource and an HTTP resource therefore resolve different relative URLs. Use URLs reachable from the converter, package critical styling with the document, or serve all related assets from the same local endpoint.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Page variables remain visible as text
Put substitutions such as [page] and [topage] in a documented header/footer text option such as --footer-right. HTML-resource substitution can vary by build; do not assume a token inside arbitrary markup will be replaced.
Parallel jobs overwrite each other
Do not use fixed names such as /tmp/header.html. Allocate a directory with mktemp -d, keep all job resources inside it, and remove that directory in a process-exit trap.
Reliability, performance and security notes
- Temporary files add a small local write and read but avoid a network hop and are easy to make deterministic.
- A local service can improve template reuse and asset loading, but it introduces availability, routing and cleanup concerns.
- Batch stdin can reduce process-start overhead, yet one malformed command line can affect the queue. Log each input line and output path so failures can be retried individually.
- Keep generated resources private when they contain customer data. Restrict a local HTTP listener, validate job identifiers, and avoid exposing arbitrary filesystem paths.
- Set explicit margins and wait behavior in your conversion command, then retain the generated PDF and wkhtmltopdf stderr together for diagnosis.
Or skip the browser setup
If your real requirement is to turn a public URL into a clean screenshot or PDF rather than maintain a wkhtmltopdf installation, ScreenshotNeo provides a hosted API. It is not a way to feed header HTML to wkhtmltopdf; it is an alternative rendering path when browser setup is the part you want to remove.
One GET request returns a PNG, JPEG, WebP or PDF. The API accepts the URL as a parameter:
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' }); const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo API documentation for request options and response headers. Before capture, it accepts the cookie or consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and each response identifies its result with X-Page-Verdict and X-Billed headers. An MCP server supplies take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.
The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan, and yearly billing gives two months free. Create a free ScreenshotNeo account to try the hosted route.
FAQ
Can the header and footer documents be partial HTML fragments?
Yes. The documented interface accepts an HTML document, and a full document with <html> and <body> elements is the least ambiguous form. Keep the resource self-contained when portability matters.
Is a localhost URL equivalent to a temporary file?
Both satisfy the URL/file argument expected by --header-html and --footer-html. They differ in asset resolution, isolation and operational dependencies, so choose based on how your workers share templates and files.
Can one stdin line create several PDFs?
No. Each line supplied to --read-args-from-stdin represents one wkhtmltopdf invocation. Put separate input and output paths on separate lines and create the referenced resources before sending them.
Frequently Asked Questions
Can the header and footer documents be partial HTML fragments?
Yes. The documented interface accepts an HTML document, and a full document with <html> and <body> elements is the least ambiguous form. Keep the resource self-contained when portability matters.
Is a localhost URL equivalent to a temporary file?
Both satisfy the URL/file argument expected by --header-html and --footer-html. They differ in asset resolution, isolation and operational dependencies, so choose based on how your workers share templates and files.
Can one stdin line create several PDFs?
No. Each line supplied to --read-args-from-stdin represents one wkhtmltopdf invocation. Put separate input and output paths on separate lines and create the referenced resources before sending them.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Quick 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.




