Deterministic output · .NET 8

Same HTML in, byte-identical PDF out.

Bhowra.Ink produces the exact same PDF binary from the same HTML — every run, every machine, every .NET version. No browser-version drift, no font-substitution surprises, no sub-pixel rendering noise.

Why "close enough" isn't good enough

Browser-based PDF generation isn't reproducible.

Driving a headless browser to produce a PDF means the output depends on whatever Chromium build, font stack, and OS font substitution happen to be installed at render time. That makes three common patterns unreliable:

Caching breaks silently

Hash-based caching assumes identical input produces identical output. If a browser upgrade shifts sub-pixel rendering, your cache key is now wrong and you don't find out until a customer does.

Checksums don't verify

Storing a document's checksum for later integrity verification only works if regenerating it produces the same bytes. Browser rendering drift makes that comparison unreliable across environments.

Golden-file tests flake

Regression tests that compare rendered output to a saved "golden" PDF start failing on unrelated browser-version bumps — noise that trains teams to ignore real regressions.

The fix — no browser, no drift

One rendering engine. One deterministic output.

Bhowra.Ink — a zero-dependency HTML-to-PDF library on NuGet — renders HTML and CSS in-process with its own layout and font engine, with fonts bundled into the assembly. There is no installed browser whose version can drift out from under you:

using Bhowra.Ink;
using System.Security.Cryptography;

string html = File.ReadAllText("invoice.html");

// Render — in-process, no browser involved.
byte[] pdf = HtmlConverter.ConvertToBytes(html);

// Same html -> same pdf bytes -> same hash, every time.
string hash = Convert.ToHexString(SHA256.HashData(pdf));

// Use the hash as a cache key, an audit fingerprint,
// or a golden-file regression check.

Re-run that same code on a different machine, in a different container, or a year later on a newer .NET 8 patch — the checksum matches, because the engine that produced the bytes didn't change out from under you.

Why it's reproducible where browser-based converters aren't

Bhowra.Ink Chromium-based converters
Same input, same output ✅ Byte-identical, always ❌ Drifts with browser version
Hash-based caching Reliable cache key Cache key can silently go stale
Checksum verification Regenerated copy matches Not guaranteed across environments
Golden-file regression tests Fail only on real regressions Flake on unrelated browser bumps
Rendering engine Fixed, in-process, versioned with your app Whatever Chromium build is installed

Frequently asked

What does "deterministic PDF generation" mean?

The same HTML input always produces the exact same PDF binary — byte for byte — regardless of which machine, container, or run generated it. There is no timestamp jitter, font-substitution drift, or sub-pixel rendering variance to account for.

Why don't browser-based converters produce identical output?

Headless-browser PDF generation depends on the installed Chromium build, its font-rendering stack, and OS-level font substitution — all of which can differ between machines and drift across browser updates, so the same HTML can render to a different PDF binary run to run.

What is this useful for?

Hash-based caching, document integrity verification, digital signing workflows, and golden-file regression tests that catch real layout regressions instead of failing on unrelated rendering noise.

Does this still work across .NET versions?

Yes. Because Bhowra.Ink has no native dependencies and does not shell out to a browser, output is identical across .NET 8 runtimes, operating systems, and container images.

Stop debugging PDFs that "look the same but aren't."

Add Bhowra.Ink and get output you can hash, cache, and diff with confidence — no browser required.

Get Bhowra.Ink on NuGet → See the full library