Introduction

Converting a live website to PDF sounds straightforward — point a renderer at a URL and save the result. In practice, modern websites throw a few curveballs: regional redirects that change the domain, cookie consent banners that obscure your content, and lazy-loaded images that won't appear unless you scroll.

In this tutorial we'll capture BBC.com as a complete, pixel-perfect PDF, tackling each problem one at a time and building up to a production-ready snippet you can adapt for any website.

Why BBC.com? It's a great real-world example. Visitors from the UK are automatically redirected from bbc.com to bbc.co.uk, the homepage shows a GDPR cookie banner, and most images are lazy-loaded. Solve these three problems and you can capture almost any website.

Project setup

Create a new console app (or add to an existing project) and install the CobaltPDF NuGet package:

Terminal
dotnet new console -n BBC-Capture
cd BBC-Capture
dotnet add package CobaltPdf

CobaltPDF bundles Chromium automatically via NuGet — there's nothing else to install.

Step 1 — Basic capture

Let's start with the simplest possible capture to see what we get:

Program.cs
using CobaltPdf;

await new CobaltEngine()
    .RenderUrlAsPdfAsync("https://www.bbc.com")
    .SaveAsAsync("bbc-basic.pdf");

Console.WriteLine("Done — saved bbc-basic.pdf");

Download bbc-basic.pdf

Run it with dotnet run and open the resulting PDF. You'll notice two problems straight away:

  1. A cookie consent banner covers a portion of the page.
  2. Images below the fold are missing — the page uses lazy loading and CobaltPDF (like any headless browser) only renders the visible viewport by default.
BBC.com captured without any options — cookie banner visible and images missing below the fold
Basic capture — notice the cookie consent banner and missing images below the fold.

Let's fix these one at a time.

Step 2 — Dismissing the cookie banner

The BBC shows a GDPR cookie consent banner to every new visitor. In a headless browser there's no stored consent, so it appears every time. The fix is to set the ckns_explicit cookie to 1 — this tells the site the user has already made their choice:

Program.cs
using CobaltPdf;

await new CobaltEngine()
    .AddCookie("ckns_explicit", "1")    // dismiss cookie consent
    .RenderUrlAsPdfAsync("https://www.bbc.com")
    .SaveAsAsync("bbc-no-banner.pdf");

Download bbc-no-banner.pdf

Notice we didn't specify a cookie domain. Because bbc.com redirects to bbc.co.uk in the UK, a hardcoded .bbc.com domain wouldn't work. When you omit the domain, CobaltPDF follows all redirects first, then sets the cookie on whatever domain the page actually landed on. You can also set the domain explicitly with .AddCookie("ckns_explicit", "1", ".bbc.co.uk") if you know it ahead of time.

BBC.com with cookie consent banner visible
Before — the cookie consent banner obscures the page content.
BBC.com captured without the cookie consent banner
After — setting ckns_explicit=1 removes the banner completely.

Alternatively, if you don't know the consent cookie name, you can use WithCustomJS to click the banner's accept button directly:

Alternative — click the accept button
await new CobaltEngine()
    .WithCustomJS("document.querySelector('[data-testid=\"accept-button\"]')?.click();")
    .WithWaitStrategy(WaitOptions.ForJavaScript(
        "!document.querySelector('[aria-labelledby=\"consent-banner-title\"]')"))
    .RenderUrlAsPdfAsync("https://www.bbc.com")
    .SaveAsAsync("bbc-js-remove.pdf");

CobaltPDF waits for the page to be fully loaded before running custom JavaScript, so the banner button is in the DOM when the click fires. The cookie approach is still preferred — it's simpler and prevents the banner from rendering at all.

Tip: Most consent platforms (OneTrust, CookieBot, etc.) use a similar cookie. Check DevTools to find the name and value, or use WithCustomJS to click the dismiss button.
Need to wait for dynamic content before capture? Use a wait strategy to poll a JavaScript expression or wait for a CSS selector to appear.

Step 3 — Capturing lazy-loaded content

Modern websites defer loading images and content below the fold until the user scrolls. In a headless browser, no scrolling happens — so those images are never loaded and appear as blank spaces in the PDF.

CobaltPDF's WithLazyLoadPages method solves this by automatically scrolling through the page before capture. You specify how many "pages" (viewport heights) to scroll, and CobaltPDF handles the rest.

Program.cs
using CobaltPdf;

await new CobaltEngine()
    .AddCookie("ckns_explicit", "1")
    .WithLazyLoadPages(5)              // scroll 5 viewport-heights
    .RenderUrlAsPdfAsync("https://www.bbc.com")
    .SaveAsAsync("bbc-lazy-loaded.pdf");

Console.WriteLine("Done — all images loaded");

Download bbc-lazy-loaded.pdf

BBC.com PDF without lazy loading — images below the fold are missing
Without lazy loading — images below the fold are blank placeholders.
BBC.com PDF with lazy loading enabled — all images loaded
With WithLazyLoadPages(5) — every image is loaded and captured.

Putting it all together

Here's the complete, production-ready snippet that combines everything we've covered:

Program.cs — final version
using CobaltPdf;

var pdf = await new CobaltEngine()
    .AddCookie("ckns_explicit", "1")    // dismiss cookie consent banner
    .WithLazyLoadPages(5)              // scroll to load all lazy images
    .WithPrintBackground()              // include background colours and images
    .WithMetadata(m =>
    {
        m.Title  = "BBC Homepage";
        m.Author = "CobaltPDF Capture";
    })
    .RenderUrlAsPdfAsync("https://www.bbc.com");

await pdf.SaveAsAsync("bbc-complete.pdf");

Console.WriteLine($"Saved {pdf.Length / 1024}KB PDF");

Summary

We covered three common challenges when converting websites to PDF, and how CobaltPDF handles each one:

Regional redirects

Omit the domain in AddCookie and CobaltPDF follows redirects automatically, injecting cookies on the final domain.

Cookie consent banners

Set the site's consent cookie (e.g. ckns_explicit=1) to suppress the banner before it renders.

Lazy-loaded images

Use WithLazyLoadPages(n) to scroll through the page and trigger all deferred image loads.

These techniques aren't BBC-specific. The same patterns apply to any website: news sites, e-commerce pages, dashboards, and single-page applications. Adjust the cookie name and scroll depth to suit your target.

Ready to try it yourself?

Install CobaltPDF Read the Docs