October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
CI/CD

How to Make wkhtmltopdf PDF Checksums Deterministic Across Runs

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To make wkhtmltopdf checksums repeatable, pin the exact executable and runtime image, vendor every input asset, freeze fonts and locale, remove clock and random data, set every rendering option explicitly, and define a metadata-normalization policy. Render the same input twice in that controlled environment and compare SHA-256 hashes. If they differ, inspect metadata, trailer identifiers, fonts, resource bytes, and PDF object ordering to locate the first divergence.

What deterministic means for a PDF

A deterministic build produces identical bytes for identical inputs and a defined environment. The test is simple: run wkhtmltopdf twice, calculate SHA-256 for both files, and require the hashes to match. This is stricter than visual equality. Two PDFs can render identically while differing in creation dates, trailer identifiers, embedded font subsets, compression, or object order.

Decide first whether generated metadata belongs to your artifact identity. If it does, preserve it and accept that values generated at run time can change the checksum. If it does not, normalize those fields in a controlled, documented post-processing step, then hash the normalized copy while retaining the original PDF for audit.

Why wkhtmltopdf output changes between runs

The renderer is only one part of the build

wkhtmltopdf is a headless Qt WebKit command-line renderer. It does not require a display service, but its output still depends on the executable build, Qt libraries, operating system, libc, fontconfig, freetype2, locale, timezone, and available fonts. The project’s downloads documentation identifies 0.12.6, released June 11, 2020, as the stable series and warns that distribution packages can behave differently.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
NQUO Rental Billing Software (Unit Pos)
  • FOR Small Facility, Complex, Housing, Arcade
  • ONE-TIME-PURCHASE; Small Investment
  • TOTAL 63 Features (Modules, 22 Reports)
  • Unit, Staff; Member Maintenance & Reporting
  • Request Trial, Try Features & Decide !

Upstream has documented non-determinism

Issue #2501, opened August 3, 2015, reports that converting the same source twice did not produce byte-identical files. Issue #4437, opened August 7, 2019 for an Alpine 3.10 build, reports non-deterministic output even after the creation date was ignored. The project is archived, and those records do not establish that every wkhtmltopdf build can emit byte-identical PDFs without environmental controls.

Time substitutions are explicit inputs

The 0.12.6 manual defines [date], [isodate], and [time] header and footer substitutions from the current system clock. A document containing any of these tokens is intentionally time-dependent. Remove them or replace them with fixed literals for checksum tests.

The reproducible-build contract

Write the following contract into your build documentation and enforce it in CI:

Dimension Deterministic requirement What to record
Executable One deliberately selected wkhtmltopdf build, distributed by digest; do not mix project binaries and distribution packages. wkhtmltopdf --version, package or image digest, architecture
Runtime One immutable operating-system or container image with fixed libc, shared libraries, locale, timezone, and environment variables. Image digest, OS release, architecture, locale and timezone values
Fonts Exact font files and fontconfig configuration packaged with the build; no host-font discovery. Font inventory and SHA-256 for every file
Inputs Vendored HTML, CSS, JavaScript, images, and web fonts; no changing network responses. Manifest of paths and hashes
Application data Fixed dates, random seeds or IDs, database ordering, and asynchronous content. Fixture version and generation parameters
Renderer options Explicit page size, dimensions, margins, DPI, image quality, media type, JavaScript policy, error behavior, outlines, headers, and footers. Complete command line or checked-in configuration
Validation Two renders from the same image and inputs, followed by SHA-256 comparison and a PDF-aware diff on failure. Both hashes, logs, and the first differing PDF component

Step-by-step deterministic setup

1. Pin and verify the executable

Select one build and distribute it as part of your image or artifact bundle. Record its version during every build:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
wkhtmltopdf --version

Do not assume that two packages labeled 0.12.6 are interchangeable. Record the binary digest as well as the version. Keep the executable, its patched-Qt dependencies, and the architecture fixed. A build that silently switches from an upstream package to a distribution package can change pagination or PDF internals.

2. Freeze the runtime image

Use an immutable container or virtual-machine image. Pin the operating-system release, architecture, libc, shared libraries, locale, timezone, and environment variables. Avoid tags such as latest; use an image digest in your build system. Run both checksum renders inside that image, not once on a developer workstation and once in CI.

Set locale and timezone explicitly even when the document appears language-neutral. They can affect date formatting, collation, number formatting, line breaking, and application-generated content.

3. Vendor and hash fonts

Install the exact font files and fontconfig configuration required by the document. Do not rely on whatever fonts happen to be installed on the host. A missing font can trigger fallback selection; a different fallback changes glyph widths, pagination, and embedded font data. Include font hashes in the input manifest and rebuild font caches in the pinned image rather than on an uncontrolled machine.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

4. Make every asset local and immutable

Vendor CSS, images, JavaScript, and web fonts. A live stylesheet, API response, advertisement, analytics script, or remote image makes the input mutable. If remote content is unavoidable, snapshot it and serve the snapshot locally. Disable or replace asynchronous code that updates the DOM after the nominal page load.

Use stable database fixtures and deterministic ordering. Never depend on an unordered query, a random identifier, a current timestamp, or a rotating feature flag. Freeze the application clock or inject a fixed date into the template data.

5. Make rendering options explicit

The 0.12.6 manual documents defaults such as A4 and 96 DPI, but relying on defaults makes a future command change harder to detect. Specify the options that affect layout and output, including page size or width and height, margins, DPI, image quality, media type, JavaScript behavior, load-error handling, outlines, headers, and footers.

A representative command is:

wkhtmltopdf --page-size A4 --dpi 96 --margin-top 12mm --margin-right 12mm --margin-bottom 12mm --margin-left 12mm --print-media-type --javascript-delay 0 --outline 0 --enable-local-file-access input.html output.pdf

Use only switches supported by the exact build you pinned. The example is not a universal policy: choose values that match your document and check them into source control. If JavaScript is required, make its completion condition deterministic rather than relying on a race between timers and network activity.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

6. Remove clock-dependent headers and footers

Search templates and command-line header or footer strings for [date], [isodate], and [time]. Replace them with a fixed release date or remove them. Also inspect application templates for generated timestamps; removing wkhtmltopdf substitutions alone does not freeze a timestamp inserted by your own code.

7. Define a metadata policy

After each render, inspect the PDF Info dictionary, any XMP metadata, the trailer /ID, producer-specific fields, embedded font subset names, and object ordering. If a field contains a run-specific value and metadata is not part of your identity, normalize it with a controlled PDF-aware post-processor. Hash the normalized bytes, keep the original artifact, and document exactly which fields were changed. Never strip metadata ad hoc after a failed comparison; that produces a checksum whose meaning is unclear.

8. Compare two renders in CI

Run the conversion twice without changing the image, input directory, environment, or command:

set -eu
wkhtmltopdf --version
wkhtmltopdf --page-size A4 --dpi 96 --margin-top 12mm --margin-right 12mm --margin-bottom 12mm --margin-left 12mm --print-media-type --outline 0 --enable-local-file-access input.html run-1.pdf
wkhtmltopdf --page-size A4 --dpi 96 --margin-top 12mm --margin-right 12mm --margin-bottom 12mm --margin-left 12mm --print-media-type --outline 0 --enable-local-file-access input.html run-2.pdf
sha256sum run-1.pdf run-2.pdf
test "$(sha256sum run-1.pdf | cut -d' ' -f1)" = "$(sha256sum run-2.pdf | cut -d' ' -f1)"

Store the command, version output, image digest, input manifest, and both hashes as CI artifacts. If the comparison fails, preserve both PDFs for diagnosis rather than overwriting one with the other.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How to find the first divergence

Use a PDF-aware binary or structural diff. Start with the cheapest, most likely causes and move toward object-level analysis:

Observed difference Likely cause Correction
Only Info or XMP fields differ Creation date, modification date, producer field, or application metadata. Remove clock inputs or apply the documented normalization policy before hashing.
Trailer /ID differs The renderer generated a run-specific identifier. Decide whether the identifier is part of identity; if not, normalize it consistently and retain originals.
Text wraps differently Font inventory, fontconfig, DPI, page geometry, locale, or fallback selection changed. Compare font files and configuration, then verify image, margin, DPI, and locale settings.
Embedded font bytes or subset names differ Different font files, font cache state, glyph discovery, or object-generation order. Use the same font files and image; rebuild caches inside that image and inspect subset naming.
Images or streams differ Remote assets, recompression, changing image bytes, or asynchronous content. Hash vendored resources and serve snapshots locally; remove nondeterministic transformations.
Page count changes Layout inputs changed: fonts, viewport, margins, media type, JavaScript timing, or data order. Make those inputs explicit and wait on a deterministic application-ready condition.
Same structure, different object order Renderer or library ordering changed despite equivalent visual output. Pin the complete runtime and binary; do not treat visual comparison as a byte-level pass.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Why two servers with the same version still differ

A version string identifies the front-end program, not every library and resource that contributes to the file. Compare these dimensions side by side:

  • Binary digest and architecture, not just the reported version.
  • Operating-system image, libc, Qt and shared-library versions.
  • Installed font files, fontconfig rules, and generated font caches.
  • Locale, timezone, environment variables, and application clock behavior.
  • Network access, DNS results, HTTP response bytes, and asset caching.
  • Complete command-line options, including defaults that one wrapper may add.
  • Post-processing and normalization versions.

Running the same command on two hosts is not a controlled test if either host can resolve a different URL, select a different font, or load a different library.

Performance and reliability practices

Reduce variation before optimizing speed

Local assets remove network latency and eliminate changing responses. They also make failures reproducible. Keep JavaScript minimal, avoid unnecessary web fonts, and use a deterministic readiness rule when scripts are required. A shorter render is useful only after the output contract is stable.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Separate rendering from normalization

Keep the original wkhtmltopdf output as an audit artifact. Run normalization in a separate, pinned step and hash its result. This lets you distinguish a renderer regression from a policy change and allows investigators to recover the exact bytes produced by wkhtmltopdf.

Fail early on environment drift

At job start, print the version, image identity, locale, timezone, and input manifest. Compare font hashes before rendering. A failed preflight is easier to diagnose than a checksum mismatch discovered after thousands of PDFs have been generated.

What a useful checksum proves

A matching SHA-256 proves that the bytes produced under your stated policy are identical for those two runs. It does not prove that the PDF is visually correct, accessible, semantically equivalent, or safe to open. Keep visual regression tests and PDF validity checks alongside the checksum test. Conversely, a mismatched checksum does not automatically mean a visible defect; metadata or internal ordering may be the only difference.

Or skip the browser setup

If your requirement is to capture a current web page as an image or PDF rather than reproduce a wkhtmltopdf build byte-for-byte, ScreenshotNeo provides a one-request API. It is not a replacement for pinning wkhtmltopdf when you own the PDF build, but it avoids maintaining a browser-rendering stack for capture jobs.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

ScreenshotNeo accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the capture; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

For the API parameters and all 63 capture options, see the ScreenshotNeo documentation. A cURL request is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The equivalent Python request is:

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}`);

Every plan includes the same features, including full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF controls, custom CSS and JavaScript, clicks, waits, request blocking, headers and cookies, timezone and geolocation, transparent backgrounds, resizing, configurable caching, signed links, asynchronous jobs, webhooks, bulk capture, usage reporting, and an OpenAPI specification. The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account to try it without a card.

Frequently Asked Questions

Should metadata be included in a release checksum?

Choose one policy before publishing artifacts. Include metadata when it is part of the record; otherwise normalize specified fields in a pinned step and hash only the normalized output while retaining the original.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can a visual PDF comparison replace SHA-256 comparison?

No. Visual comparison can miss metadata, font, stream, and object-order changes. Use it in addition to, not instead of, the byte-level test.

What should be retained when CI detects a mismatch?

Keep both PDFs, their hashes, the exact command, version output, runtime image identity, input manifest, font hashes, and environment values so the first differing component can be investigated.

Quick Recap

Bestseller No. 1
NQUO Rental Billing Software (Unit Pos)
NQUO Rental Billing Software (Unit Pos)
FOR Small Facility, Complex, Housing, Arcade; ONE-TIME-PURCHASE; Small Investment; TOTAL 63 Features (Modules, 22 Reports)
$70.00

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.