IRONSOFTWAREHOME
MIGRATION GUIDES

How to Migrate from PuppeteerSharp to IronPDF in C#

Curtis Chau
Curtis Chau
Updated: August 1, 2026

Migrating from PuppeteerSharp to IronPDF moves your PDF generation workflow from a browser automation tool with a 300MB+ Chromium dependency to a purpose-built PDF library with automatic memory management. This guide provides a step-by-step migration path that eliminates the runtime Chromium download, addresses reported memory growth under load, and adds comprehensive PDF manipulation capabilities.

Why Migrate from PuppeteerSharp to IronPDF

Understanding PuppeteerSharp

PuppeteerSharp is a .NET port of Google's Puppeteer, bringing browser automation capabilities to C#. It generates PDFs using Chrome's built-in print-to-PDF functionality - the same as hitting Ctrl+P in a browser. This produces print-ready output optimized for paper, which differs from what you see on screen.

PuppeteerSharp was designed for web testing and scraping, not document generation. While capable, using PuppeteerSharp for PDF generation creates significant production challenges.

The Browser Automation Problem

PuppeteerSharp was designed for browser automation, not document generation. This creates fundamental issues when using it for PDFs:

  1. 300MB+ Chromium downloads required before first use. A significant downside of PuppeteerSharp is its hefty deployment size, mainly due to the Chromium binary it bundles. This substantial size can bloat Docker images and cause cold start issues in serverless environments.
  2. Memory growth reported under load requiring manual browser recycling. Under sustained load, PuppeteerSharp users have reported memory accumulation across browser instances, typically addressed by manual process recycling.
  3. Complex async patterns with browser lifecycle management.
  4. Print-to-PDF output (equivalent to Ctrl+P, not screen capture). Layouts may reflow, backgrounds may be omitted by default, and the output is paginated for printing rather than matching the browser viewport.
  5. No PDF/A or PDF/UA support for compliance requirements. PuppeteerSharp cannot produce PDF/A (archival) or PDF/UA (accessibility) compliant documents.
  6. No PDF manipulation - generation only, no merge/split/edit. While PuppeteerSharp is efficient at generating PDFs, it lacks capabilities for further manipulation such as merging, splitting, securing, or editing PDFs.

PuppeteerSharp vs IronPDF Comparison

AspectPuppeteerSharpIronPDF
Primary PurposeBrowser automationPDF generation
Chromium Dependency300MB+ separate downloadBuilt-in optimized engine
API ComplexityAsync browser/page lifecycleSynchronous one-liners
InitializationBrowserFetcher.DownloadAsync() + LaunchAsyncnew ChromePdfRenderer()
Memory ManagementManual browser recyclingAutomatic
Memory Under LoadGrowth reported on heavy workloadsStable across sustained runs
PDF/A SupportNot availableSupported
PDF/UA AccessibilityNot availableSupported
PDF EditingNot availableMerge, split, stamp, edit
Digital SignaturesNot availableSupported
Thread SafetyLimited (per upstream guidance)Full
LicensingMIT (open source)Commercial license

Platform Support

Library.NET Framework 4.7.2.NET Core 3.1.NET 6-8.NET 10
IronPDFFullFullFullFull
PuppeteerSharpvia netstandard2.0FullFullFull

IronPDF's support across modern .NET targets means it slots into most existing applications without compatibility friction.


Before You Start

Prerequisites

  1. .NET Environment: .NET Framework 4.6.2+ or .NET Core 3.1+ / .NET 5/6/7/8/9+
  2. NuGet Access: Ability to install NuGet packages
  3. IronPDF License: Obtain your license key from ironpdf.com

NuGet Package Changes

# Remove PuppeteerSharp
dotnet remove package PuppeteerSharp

# Remove downloaded Chromium binaries (~300MB recovered)
# Delete the .local-chromium folder

# Add IronPDF
dotnet add package IronPdf
SHELL

No BrowserFetcher.DownloadAsync() required with IronPDF - the rendering engine is bundled automatically.

License Configuration

// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

Complete API Reference

Namespace Changes

// Before: PuppeteerSharp
using PuppeteerSharp;
using PuppeteerSharp.Media;
using System.Threading.Tasks;

// After: IronPDF
using IronPdf;
using IronPdf.Rendering;

Core API Mappings

PuppeteerSharp APIIronPDF APINotes
new BrowserFetcher().DownloadAsync()Not neededNo browser download
Puppeteer.LaunchAsync(options)Not neededNo browser management
browser.NewPageAsync()Not neededNo page context
page.GoToAsync(url)renderer.RenderUrlAsPdf(url)Direct rendering
page.SetContentAsync(html)renderer.RenderHtmlAsPdf(html)Direct rendering
page.PdfAsync(path)pdf.SaveAs(path)After rendering
await page.CloseAsync()Not neededAutomatic cleanup
await browser.CloseAsync()Not neededAutomatic cleanup
PdfOptions.FormatRenderingOptions.PaperSizePaper size
PdfOptions.LandscapeRenderingOptions.PaperOrientationOrientation
PdfOptions.MarginOptionsRenderingOptions.MarginTop/Bottom/Left/RightIndividual margins
PdfOptions.PrintBackgroundRenderingOptions.PrintHtmlBackgroundsBackground printing
PdfOptions.HeaderTemplateRenderingOptions.HtmlHeaderHTML headers
PdfOptions.FooterTemplateRenderingOptions.HtmlFooterHTML footers
page.WaitForSelectorAsync()RenderingOptions.WaitFor.HtmlElementIdWait for element

Code Migration Examples

Example 1: Basic HTML to PDF Conversion

Before (PuppeteerSharp):

// NuGet: Install-Package PuppeteerSharp
using PuppeteerSharp;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var browserFetcher = new BrowserFetcher();
        await browserFetcher.DownloadAsync();
        
        await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
        {
            Headless = true
        });
        
        await using var page = await browser.NewPageAsync();
        await page.SetContentAsync("<h1>Hello World</h1><p>This is a PDF document.</p>");
        await page.PdfAsync("output.pdf");
    }
}

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF document.</p>");
        pdf.SaveAs("output.pdf");
    }
}

This example demonstrates the fundamental architectural difference. PuppeteerSharp requires six async operations: BrowserFetcher.DownloadAsync() (300MB+ Chromium download), Puppeteer.LaunchAsync(), browser.NewPageAsync(), page.SetContentAsync(), and page.PdfAsync(), plus proper disposal with await using.

IronPDF eliminates all this complexity: create a ChromePdfRenderer, call RenderHtmlAsPdf(), and SaveAs(). No async patterns, no browser lifecycle, no Chromium downloads. IronPDF's approach offers cleaner syntax and better integration with modern .NET applications. See the HTML to PDF documentation for comprehensive examples.

Example 2: URL to PDF Conversion

Before (PuppeteerSharp):

// NuGet: Install-Package PuppeteerSharp
using PuppeteerSharp;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var browserFetcher = new BrowserFetcher();
        await browserFetcher.DownloadAsync();
        
        await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
        {
            Headless = true
        });
        
        await using var page = await browser.NewPageAsync();
        await page.GoToAsync("https://www.example.com");
        await page.PdfAsync("webpage.pdf");
    }
}

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
        pdf.SaveAs("webpage.pdf");
    }
}

PuppeteerSharp uses GoToAsync() to navigate to a URL followed by PdfAsync(). IronPDF provides a single RenderUrlAsPdf() method that handles navigation and PDF generation in one call. Learn more in our tutorials.

Example 3: Custom Page Settings with Margins

Before (PuppeteerSharp):

// NuGet: Install-Package PuppeteerSharp
using PuppeteerSharp;
using PuppeteerSharp.Media;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var browserFetcher = new BrowserFetcher();
        await browserFetcher.DownloadAsync();
        
        await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
        {
            Headless = true
        });
        
        await using var page = await browser.NewPageAsync();
        await page.SetContentAsync("<h1>Custom PDF</h1><p>With landscape orientation and margins.</p>");
        
        await page.PdfAsync("custom.pdf", new PdfOptions
        {
            Format = PaperFormat.A4,
            Landscape = true,
            MarginOptions = new MarginOptions
            {
                Top = "20mm",
                Bottom = "20mm",
                Left = "20mm",
                Right = "20mm"
            }
        });
    }
}

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
        renderer.RenderingOptions.MarginTop = 20;
        renderer.RenderingOptions.MarginBottom = 20;
        renderer.RenderingOptions.MarginLeft = 20;
        renderer.RenderingOptions.MarginRight = 20;
        
        var pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>With landscape orientation and margins.</p>");
        pdf.SaveAs("custom.pdf");
    }
}

This example shows how PDF options map between the two libraries. PuppeteerSharp uses PdfOptions with Format, Landscape, and MarginOptions containing string values ("20mm"). IronPDF uses RenderingOptions properties with direct paper size enums, orientation enums, and numeric margin values in millimeters.

Key mappings:

  • Format = PaperFormat.A4PaperSize = PdfPaperSize.A4
  • Landscape = truePaperOrientation = PdfPaperOrientation.Landscape
  • MarginOptions.Top = "20mm"MarginTop = 20 (numeric millimeters)

Memory Growth Under Sustained Load

Users have reported memory accumulation with PuppeteerSharp under sustained load, typically mitigated by manual browser recycling:

// PuppeteerSharp - memory growth typically requires periodic recycling
for (int i = 0; i < 1000; i++)
{
    var page = await browser.NewPageAsync();
    await page.SetContentAsync($"<h1>Document {i}</h1>");
    await page.PdfAsync($"doc_{i}.pdf");
    await page.CloseAsync();
}
// Recommended: await browser.CloseAsync(); and re-launch every N operations

// IronPDF - reuse a single renderer across operations
var renderer = new ChromePdfRenderer();
for (int i = 0; i < 1000; i++)
{
    var pdf = renderer.RenderHtmlAsPdf($"<h1>Document {i}</h1>");
    pdf.SaveAs($"doc_{i}.pdf");
    // Memory managed automatically
}

IronPDF eliminates the need for browser pooling infrastructure that PuppeteerSharp requires:

// Before (PuppeteerSharp - delete entire class)
public class PuppeteerBrowserPool
{
    private readonly ConcurrentBag<IBrowser> _browsers;
    private readonly SemaphoreSlim _semaphore;
    private int _operationCount;
    // ... recycling logic ...
}

// After (IronPDF - simple reuse)
public class PdfService
{
    private readonly ChromePdfRenderer _renderer = new();

    public byte[] Generate(string html)
    {
        return _renderer.RenderHtmlAsPdf(html).BinaryData;
    }
}

Critical Migration Notes

Async to Sync Conversion

PuppeteerSharp requires async/await throughout; IronPDF supports synchronous operations:

// PuppeteerSharp: Async required
public async Task<byte[]> GeneratePdfAsync(string html)
{
    await new BrowserFetcher().DownloadAsync();
    await using var browser = await Puppeteer.LaunchAsync(...);
    await using var page = await browser.NewPageAsync();
    await page.SetContentAsync(html);
    return await page.PdfDataAsync();
}

// IronPDF: Sync default
public byte[] GeneratePdf(string html)
{
    var renderer = new ChromePdfRenderer();
    return renderer.RenderHtmlAsPdf(html).BinaryData;
}

// Or async when needed
public async Task<byte[]> GeneratePdfAsync(string html)
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return pdf.BinaryData;
}

Margin Unit Conversion

PuppeteerSharp uses string units; IronPDF uses numeric millimeters:

// PuppeteerSharp - string units
MarginOptions = new MarginOptions
{
    Top = "1in",      // 25.4mm
    Bottom = "0.75in", // 19mm
    Left = "1cm",     // 10mm
    Right = "20px"    // ~7.5mm at 96dpi
}

// IronPDF - numeric millimeters
renderer.RenderingOptions.MarginTop = 25;    // mm
renderer.RenderingOptions.MarginBottom = 19;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 8;

Header/Footer Placeholder Conversion

PuppeteerSharp ClassIronPDF Placeholder
<span class='pageNumber'>{page}
<span class='totalPages'>{total-pages}
<span class='date'>{date}
<span class='title'>{html-title}

New Capabilities After Migration

After migrating to IronPDF, you gain capabilities that PuppeteerSharp cannot provide:

PDF Merging

var pdf1 = renderer.RenderHtmlAsPdf(html1);
var pdf2 = renderer.RenderHtmlAsPdf(html2);
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");

Watermarks

var watermark = new TextStamper
{
    Text = "CONFIDENTIAL",
    FontSize = 48,
    Opacity = 30,
    Rotation = -45
};
pdf.ApplyStamp(watermark);

Password Protection

pdf.SecuritySettings.OwnerPassword = "admin";
pdf.SecuritySettings.UserPassword = "readonly";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;

Digital Signatures

var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);

PDF/A Compliance

pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);

Performance Comparison Summary

MetricPuppeteerSharpIronPDFImprovement
First PDF (Cold Start)45s+~20s55%+ faster
Subsequent PDFsVariableConsistentPredictable
Memory Usage500MB+ (grows)~50MB (stable)90% less memory
Disk Space (Chromium)300MB+0Eliminate downloads
Browser DownloadRequiredNot neededZero setup
Thread SafetyLimitedFullReliable concurrency
PDF Generation Time45s20s55% faster

Migration Checklist

Pre-Migration

  • Identify all PuppeteerSharp usages in codebase
  • Document margin values (convert strings to millimeters)
  • Note header/footer placeholder syntax for conversion
  • Delete browser pooling/recycling infrastructure
  • Obtain IronPDF license key from ironpdf.com

Package Changes

  • Remove PuppeteerSharp NuGet package
  • Delete .local-chromium folder to reclaim ~300MB disk space
  • Install IronPdf NuGet package: dotnet add package IronPdf

Code Changes

  • Update namespace imports
  • Remove BrowserFetcher.DownloadAsync() calls
  • Remove Puppeteer.LaunchAsync() and browser management
  • Replace page.SetContentAsync() + page.PdfAsync() with RenderHtmlAsPdf()
  • Replace page.GoToAsync() + page.PdfAsync() with RenderUrlAsPdf()
  • Convert margin strings to millimeter values
  • Convert header/footer placeholder syntax
  • Remove all browser/page disposal code
  • Delete browser pooling infrastructure
  • Add license initialization at application startup

Post-Migration

  • Visual comparison of PDF output
  • Load test for memory stability (should stay stable without recycling)
  • Verify header/footer rendering with page numbers
  • Add new capabilities (security, watermarks, merging) as needed

Please note: PuppeteerSharp is a registered trademark of its respective owner. This site is not affiliated with, endorsed by, or sponsored by PuppeteerSharp. All product names, logos, and brands are property of their respective owners. Comparisons are for informational purposes only and reflect publicly available information at the time of writing.
Curtis Chau
Technical Writer

Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.

...
Read More

Related Articles

Key in blue circle

Get your free 30-day Trial Key instantly.

Your trial license will be sent to your email address

No limitations. 100% unlocked. No credit card.

bullet_checkedNo credit card or account creation requiredNo limitations. 100% unlocked. No credit card.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Book your free Live Demo
Booking Badge

Trusted by Millions of Engineers Worldwide

Iron Software's customer logos
Get Your No-Obligation Consult
Complete the form below or email sales@ironsoftware.com
Your details will always be kept confidential.
Trusted by Millions of Engineers Worldwide
Iron Software's customer logos
Get your free 30-day Trial Key instantly.
No credit card or account creation required