Skip to main content

OutSystems-maintained fork of HeadlessChromium.Puppeteer.Lambda.Dotnet (originally by Litmus): https://github.com/litmus/HeadlessChromium.Puppeteer.Lambda.Dotnet

Total Downloads
216
216
Published
Oct 7, 2026
14d ago

Get Started

dotnet add package HeadlessChromium.Puppeteer.Dotnet.OS.Fork --version 1.2.1.3
ProductVersions
.NET Standard
netstandard2.1

README

HeadlessChromium.Puppeteer.Lambda.Dotnet

Packages everything you need to run PuppeteerSharp in AWS Lambda or a Docker container on Chromium into a Nuget Package

Description

The chromium binary for this project has been extracted from the NPM project Sparticuz/chromium. It is automatically extracted to /tmp/chromium at runtime. For now, the chromium binary only supports x86_64

Supported platforms, auto-detected at runtime:

  • AWS Lambda dotnet8/dotnet10 (Amazon Linux 2023 based).
  • Ubuntu 22.04 LTS Docker containers (e.g. mcr.microsoft.com/dotnet/runtime:10.0-based images before they moved to 24.04, or any ubuntu:22.04-based image). Ubuntu 22.04 reuses the AL2023 dependency bundle - it was validated to run unmodified in a vanilla ubuntu:22.04 container, since AL2023's bundled shared libraries (NSS, NSPR, expat) satisfy what Ubuntu 22.04 needs and there is no separate Sparticuz-published Ubuntu build.
  • Chainguard / Wolfi containers (e.g. cgr.dev/chainguard/aspnet-runtime, or any Wolfi-based image reporting ID=wolfi or ID=chainguard). Wolfi reuses the AL2023 dependency bundle and adds wolfi.tar.br on top of it, which carries libsqlite3.so.0 - see below. End-to-end renders of both a local document and a live HTTPS page on the real image confirm the combination. See the assumptions below.
Why Wolfi needs an extra archive

A dependency walk of the Sparticuz binary resolves every library it links against from either the image or al2023.tar.br, which is why Wolfi first looked like a pure reuse of the AL2023 bundle. It is not. The first time a page needs TLS, NSS loads its PKCS#11 module libsoftokn3.so with dlopen(), and that module needs libsqlite3.so.0 for the SQLite-backed certificate database. Amazon Linux and Ubuntu ship libsqlite3.so.0 in the base image; Chainguard's distroless images do not, and failing NSS initialisation is fatal:

ERROR:crypto/nss_util.cc:256 Error initializing NSS with a persistent database
    (sql:/tmp/.local/share/pki/nssdb): libsqlite3.so.0: cannot open shared object file
FATAL:crypto/nss_util.cc:146  nss_error=-5925

Chromium aborts there, so the symptom reaching the caller is a TargetClosedException or NavigationException ("Target closed", "the remote party closed the WebSocket connection") in the middle of GoToAsync - and only for pages fetched over the network. Rendering a local document via SetContentAsync never touches NSS and keeps working, which is what makes this failure easy to miss.

payloads/wolfi.tar.br supplies the library, is extracted only on Wolfi, and is regenerated by tools/build-wolfi-payload.sh.

Chainguard / Wolfi assumptions

Chainguard support relies on three properties of the shipping images, all verified rather than assumed:

  • Non-root, uid 65532. The images run as nonroot with APP_UID=65532. Chromium and its libraries are extracted to /tmp, which is mode 1777 and therefore the one location this uid can write to. A read-only root filesystem is not supported - /tmp is hardcoded.
  • Distroless. There is no shell, so nothing can be diagnosed from inside a running container. Every failure path is therefore reported through log output and exception messages; enable DEBUG logging to see them.
  • x86_64 only. The Sparticuz Chromium payload is x86_64. Chainguard also publishes arm64 images, which this library cannot serve.

No change to your Dockerfile is required - no apk packages, no hand-installed Chromium. See sample/SampleAspNet-chainguard/ for a working ASP.NET example.

Platform detection

Platform detection runs automatically and needs no configuration in the common case:

  1. If the CHROMIUM_PLATFORM_OVERRIDE environment variable is set to a supported value (al2023, ubuntu-22.04, or wolfi - with chainguard accepted as an alias for wolfi), it's used immediately.
  2. Otherwise, /etc/system-release-cpe is checked for Amazon Linux 2023.
  3. Otherwise, /etc/os-release is checked. Matching is on the ID field (falling back to NAME when ID is absent), compared against known identifiers: ubuntu with VERSION_ID="22.04", or wolfi/chainguard. Wolfi's VERSION_ID is a rolling build date and is deliberately ignored.

If none of the above match - an invalid override value, or an unrecognized OS - ExtractChromium() throws a ChromiumExtractionException. The message names the OS that was detected, lists the supported platform identifiers, and points at CHROMIUM_PLATFORM_OVERRIDE. A caller that knows better can still set ChromiumExtractor.OperatingSystem before calling ExtractChromium(), which bypasses detection entirely.

Troubleshooting

Enable DEBUG-level logging on ChromiumExtractor to see which detection method was used and what platform was resolved. A ChromiumExtractionException mentioning the supported platform list means detection failed (invalid CHROMIUM_PLATFORM_OVERRIDE value, or no matching OS file) - set CHROMIUM_PLATFORM_OVERRIDE explicitly to unblock it, e.g.:

docker run -e CHROMIUM_PLATFORM_OVERRIDE=ubuntu-22.04 myimage
docker run -e CHROMIUM_PLATFORM_OVERRIDE=wolfi myimage

Upgrading

Unrecognized platforms now fail fast. Previously, when platform detection could not resolve a platform, a WARNING was logged and the OS-specific dependency archive was simply skipped. Chromium then failed later with a dynamic-linker error, which on a distroless image is close to undiagnosable. ExtractChromium() now throws a ChromiumExtractionException at that point instead.

  • If you already set ChromiumExtractor.OperatingSystem before calling ExtractChromium(), nothing changes - that still bypasses detection.
  • If you relied on warn-and-continue and set the platform afterwards, move the assignment before the call, or set CHROMIUM_PLATFORM_OVERRIDE.
  • On a supported platform, nothing changes.

The unreleased chainguard-20230214 platform identifier has been removed in favour of wolfi. It never shipped in a release and its detection could never fire, so no consumer can depend on it; chainguard is accepted as an alias for wolfi.

Usage

Screenshot a URL as a byte[].

var browserLauncher = new HeadlessChromiumPuppeteerLauncher(logger);

using(var browser = await browserLauncher.LaunchAsync())
using(var page = await browser.NewPageAsync())
{
    await page.GoToAsync(url);
    return await page.ScreenshotDataAsync();
}

For more use cases see the PuppeteerSharp documentation

Projects using this library

These projects are using this library and are good examples of how you might consume this nuget package

Building

To build locally:

.\build.ps1 -Target Build

Downloads by Version

Depended On By

Find packages that declare this package as a dependency. NuGet does not provide a reverse-dependency endpoint, so candidates are checked on demand.

Adoption Assessment

Assess this package against its supported frameworks, license, maintenance signals and dependency graph before making it a project standard.

Compatibility metadata lists 1 target framework; confirm the exact target used by your application.

Related Guides & Workflows

Learn how to evaluate, integrate, or audit this package in your .NET project.