Serverless PDF · .NET 8

HTML to PDF in Azure Functions,
in pure C#.

Generate PDFs from HTML inside an Azure Function with no Chromium, no headless browser, and no native binaries. Bhowra.Ink renders in-process on .NET 8 — even on Windows Consumption plans, where browser-based converters can't run.

Why HTML-to-PDF is hard on Functions

Headless browsers don't belong in a Function.

The usual way to turn HTML into PDF — driving a headless browser — ships an entire Chromium engine with every deployment. Inside Azure Functions that means:

Blocked by the sandbox

The Windows Consumption plan blocks the native APIs a Chromium process needs to launch — so browser-based converters simply fail there.

Cold-start tax

Spawning a browser per invocation adds seconds of latency and hundreds of MB to your deployment — the opposite of what serverless is for.

An entire CVE stream

A bundled browser is a large, constantly-patched attack surface to track and update — on every Function you ship.

The fix — render in-process

One managed DLL. No browser.

Bhowra.Ink — a zero-dependency, serverless HTML-to-PDF library on NuGet — is pure C# on the .NET 8 base class library. There's nothing native to install, so it just runs inside your Function:

using System.Net;
using Bhowra.Ink;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;

public class InvoicePdf
{
    [Function("InvoicePdf")]
    public async Task<HttpResponseData> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req)
    {
        // The HTML you want to turn into a PDF (invoice, report, statement…)
        string html = await new StreamReader(req.Body).ReadToEndAsync();

        // One in-process call — no Chromium, no browser to launch.
        byte[] pdf = HtmlConverter.ConvertToBytes(html);

        var res = req.CreateResponse(HttpStatusCode.OK);
        res.Headers.Add("Content-Type", "application/pdf");
        await res.Body.WriteAsync(pdf);
        return res;
    }
}

The same code runs unchanged on Windows Consumption, Linux, AWS Lambda, and Docker — there are no per-platform native builds to manage.

Why it works where browser-based converters don't

Bhowra.Ink Chromium-based converters
Azure Functions (Windows Consumption) ✅ Works ❌ Blocked by sandbox
Native binaries None — pure .NET 8 Browser + driver + native libs
Deployment size ~895 KB, one DLL Hundreds of MB (full browser)
Cold start ~1 s (first call, incl. JIT) Seconds (browser spawn)
Memory per conversion Tens of MB ~0.5–1 GB per browser instance
Third-party dependencies None (no AGPL) A browser, its driver, and Node.js or native libraries

Frequently asked

Do I need Chromium or a headless browser on Azure Functions?

No. Bhowra.Ink renders HTML and CSS in-process in pure .NET — there is no Chromium and no native binaries to install or a sandbox to fight.

Does it run on the Azure Functions Consumption plan and on Linux?

Yes. Because there is no native code, the same managed DLL runs on Windows Consumption plans, Linux, AWS Lambda and Docker — there are no per-platform builds to manage.

What about cold starts?

There is no browser to spawn. The first call pays only normal .NET JIT (about a second); subsequent conversions run in-process and complete in well under a second.

Does it execute JavaScript?

No — by design. Bhowra.Ink renders static HTML + CSS, which is what server-generated documents (invoices, reports, statements, contracts) are. Pre-render any single-page app to HTML first.

Ship HTML-to-PDF on the smallest plan you've got.

Add Bhowra.Ink to your Functions project and convert your first document in under a minute — no browser required.

Get Bhowra.Ink on NuGet → See the full library