How to Migrate from Playwright to IronPDF in C#
Migrating from Microsoft Playwright for .NET to IronPDF moves your PDF generation workflow from a browser-automation testing framework to a purpose-built PDF library. This guide provides a step-by-step migration path that removes async browser lifecycle management and the separate playwright install browser-binary download step.
Why Migrate from Playwright to IronPDF
Understanding Playwright for .NET
Playwright for .NET (NuGet Microsoft.Playwright, MIT-licensed) is Microsoft's browser-automation framework, designed primarily for end-to-end testing across Chromium, Firefox, and WebKit. Its typical workloads are interactive: clicking buttons, filling forms, intercepting network requests, taking screenshots, and validating cross-browser compatibility.
PDF generation in Playwright is a secondary feature exposed via Page.PdfAsync(), and it is supported on Chromium only — Firefox and WebKit do not implement PDF output. Output uses the browser's print-to-PDF path (equivalent to Ctrl+P), which has implications for layouts, backgrounds, and pagination:
- Testing-first architecture, not optimized for headless document production
- Browser binaries (Chromium plus optionally Firefox and WebKit) must be installed separately via
playwright install - Async API designed for test automation workflows
- No built-in PDF/A, PDF/UA, digital signature, watermarking, merging, or security features
Considerations When Using Playwright for PDFs
Playwright was designed for end-to-end testing, not document generation. A few practical implications when repurposing it for PDFs:
-
Browser binaries via
playwright install. Playwright's default configuration downloads browser binaries (Chromium, Firefox, WebKit), which can be a consideration for environments with strict resource or deployment constraints. -
Async browser/context/page model. Developers need to be comfortable with browser contexts and page lifecycle management, including disposal.
-
Testing-first architecture, not optimized for high-volume document generation.
-
Print-to-PDF semantics equivalent to Ctrl+P browser print. Layouts may reflow, backgrounds may be omitted by default, and output is paginated for printing.
-
No PDF/A or PDF/UA output. Playwright does not produce PDF/A (archival) or PDF/UA (accessibility) compliant documents. For Section 508, EU accessibility directives, or long-term archival requirements, a dedicated PDF library is typically required.
- Per-render browser resource usage when each PDF spins up browser contexts and pages.
Configuration Surface
Playwright exposes a configuration surface oriented toward test automation. The pieces most relevant when using it just for PDF generation:
Browser installation step:
# Separate installation step before first use
playwright install # Downloads browser binaries (Chromium, Firefox, WebKit)
# Or for a single browser:
playwright install chromium # Chromium-only (the only engine that supports PDF output)
# Separate installation step before first use
playwright install # Downloads browser binaries (Chromium, Firefox, WebKit)
# Or for a single browser:
playwright install chromium # Chromium-only (the only engine that supports PDF output)
Browser Launch Configuration:
// Testing-focused launch options for PDF generation
using var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
{
Headless = true, // Required for server environments
Args = new[] { "--disable-gpu", "--no-sandbox" } // Linux/Docker configs
});
// Testing-focused launch options for PDF generation
using var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
{
Headless = true, // Required for server environments
Args = new[] { "--disable-gpu", "--no-sandbox" } // Linux/Docker configs
});
' Testing-focused launch options for PDF generation
Using playwright = Await Playwright.CreateAsync()
Dim browser = Await playwright.Chromium.LaunchAsync(New BrowserTypeLaunchOptions With {
.Headless = True, ' Required for server environments
.Args = New String() { "--disable-gpu", "--no-sandbox" } ' Linux/Docker configs
})
End Using
Testing-Specific Configuration Options:
Headless: Must configure headless mode for production (defaults to headed for testing)SlowMo: Test timing delays (irrelevant for PDF generation)Devtools: Testing tools configuration (not needed for documents)ExecutablePath: Custom browser paths for test environmentsProxy: Network interception for testing (unnecessary overhead)DownloadsPath: Test artifact managementTracesDir: Test execution traces
Browser Context Management:
// Complex context lifecycle from testing paradigm
var context = await browser.NewContextAsync(new BrowserNewContextOptions
{
ViewportSize = new ViewportSize { Width = 1920, Height = 1080 },
UserAgent = "custom-user-agent",
Locale = "en-US",
TimezoneId = "America/New_York"
});
var page = await context.NewPageAsync();
// ... generate PDF ...
await context.CloseAsync(); // Manual cleanup required
await browser.CloseAsync(); // Manual cleanup required
// Complex context lifecycle from testing paradigm
var context = await browser.NewContextAsync(new BrowserNewContextOptions
{
ViewportSize = new ViewportSize { Width = 1920, Height = 1080 },
UserAgent = "custom-user-agent",
Locale = "en-US",
TimezoneId = "America/New_York"
});
var page = await context.NewPageAsync();
// ... generate PDF ...
await context.CloseAsync(); // Manual cleanup required
await browser.CloseAsync(); // Manual cleanup required
' Complex context lifecycle from testing paradigm
Dim context = Await browser.NewContextAsync(New BrowserNewContextOptions With {
.ViewportSize = New ViewportSize With {.Width = 1920, .Height = 1080},
.UserAgent = "custom-user-agent",
.Locale = "en-US",
.TimezoneId = "America/New_York"
})
Dim page = Await context.NewPageAsync()
' ... generate PDF ...
Await context.CloseAsync() ' Manual cleanup required
Await browser.CloseAsync() ' Manual cleanup required
Multi-browser surface:
// Playwright supports launching multiple engines
await playwright.Chromium.LaunchAsync(); // For Chromium-based testing (and PDF output)
await playwright.Firefox.LaunchAsync(); // For Firefox testing
await playwright.Webkit.LaunchAsync(); // For WebKit/Safari testing
// Note: Page.PdfAsync() is implemented on Chromium only.
// Playwright supports launching multiple engines
await playwright.Chromium.LaunchAsync(); // For Chromium-based testing (and PDF output)
await playwright.Firefox.LaunchAsync(); // For Firefox testing
await playwright.Webkit.LaunchAsync(); // For WebKit/Safari testing
// Note: Page.PdfAsync() is implemented on Chromium only.
Imports System.Threading.Tasks
' Playwright supports launching multiple engines
Await playwright.Chromium.LaunchAsync() ' For Chromium-based testing (and PDF output)
Await playwright.Firefox.LaunchAsync() ' For Firefox testing
Await playwright.Webkit.LaunchAsync() ' For WebKit/Safari testing
' Note: Page.PdfAsync() is implemented on Chromium only.
IronPDF: single bundled renderer
// No separate browser-binary install or context management
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// No separate browser-binary install or context management
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
IronPDF ships its rendering engine inside the NuGet package, so there is no separate playwright install step and no browser/context/page lifecycle to manage.
Playwright vs IronPDF Performance Comparison
| Metric | Playwright | IronPDF |
|---|---|---|
| Primary Purpose | E2E browser-automation framework | PDF document generation |
| Design Philosophy | Testing-first; PDF is a secondary feature | Purpose-built PDF library |
| NuGet Package | Microsoft.Playwright (MIT) |
IronPdf (commercial) |
| Browser-Binary Step | Separate playwright install download |
Bundled in the NuGet package |
| Engines Supporting PDF | Chromium only (Firefox / WebKit do not implement Page.PdfAsync()) |
Single bundled Chromium-based renderer |
| First Render (Cold Start) | 4.5 seconds | 2.8 seconds |
| Subsequent Renders | 3.8-4.1 seconds | 0.8-1.2 seconds |
| Memory per Conversion | 280-420MB | 80-120MB |
| API Style | Async browser/context/page lifecycle | Synchronous or async; renderer-based |
| Initialization | CreateAsync() + LaunchAsync() + NewPageAsync() |
new ChromePdfRenderer() |
| PDF/A Support | Not available | Supported |
| PDF/UA Accessibility | Not available | Supported |
| Digital Signatures | Not available | Supported |
| PDF Editing | Not available | Merge, split, stamp, edit |
| Support Model | Community | Commercial with SLA |
IronPDF is built specifically for PDF generation, with a document-centric API surface. It uses a single bundled Chromium-based rendering engine and supports both synchronous and asynchronous operations, which gives developers a simpler mental model when PDF output — not browser interaction — is the goal.
The Bottom Line
Playwright is a strong fit when the primary workload is browser automation or cross-browser testing, with PDF output as an occasional secondary task. IronPDF is the better fit when PDF generation is the primary workload: there is no separate browser-binary install step, no browser/context/page lifecycle to manage, and document features like PDF/A, digital signatures, security, and merging are available out of the box.
Before You Start
Prerequisites
- .NET Environment: .NET Framework 4.6.2+ or .NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet Access: Ability to install NuGet packages
- IronPDF License: Obtain your license key from ironpdf.com
NuGet Package Changes
# Remove Playwright
dotnet remove package Microsoft.Playwright
# Remove the downloaded browser binaries
# Delete the .playwright folder in your project (and any cached binaries
# under your user profile, e.g. %USERPROFILE%\.cache\ms-playwright on Windows)
# Add IronPDF
dotnet add package IronPdf
# Remove Playwright
dotnet remove package Microsoft.Playwright
# Remove the downloaded browser binaries
# Delete the .playwright folder in your project (and any cached binaries
# under your user profile, e.g. %USERPROFILE%\.cache\ms-playwright on Windows)
# Add IronPDF
dotnet add package IronPdf
No playwright install required with IronPDF - the rendering engine is bundled automatically.
License Configuration
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Complete API Reference
Namespace Changes
// Before: Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
// Before: Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
' Before: Playwright
Imports Microsoft.Playwright
Imports System.Threading.Tasks
' After: IronPDF
Imports IronPdf
Imports IronPdf.Rendering
Core API Mappings
| Playwright API | IronPDF API |
|---|---|
Playwright.CreateAsync() |
new ChromePdfRenderer() |
playwright.Chromium.LaunchAsync() |
Not needed |
browser.NewPageAsync() |
Not needed |
page.GotoAsync(url) |
renderer.RenderUrlAsPdf(url) |
page.SetContentAsync(html) + page.PdfAsync() |
renderer.RenderHtmlAsPdf(html) |
page.CloseAsync() |
Not needed |
browser.CloseAsync() |
Not needed |
PagePdfOptions.Format |
RenderingOptions.PaperSize |
PagePdfOptions.Margin |
RenderingOptions.MarginTop/Bottom/Left/Right |
PagePdfOptions.DisplayHeaderFooter |
RenderingOptions.TextHeader/TextFooter |
PagePdfOptions.HeaderTemplate |
RenderingOptions.HtmlHeader |
PagePdfOptions.FooterTemplate |
RenderingOptions.HtmlFooter |
<span class='pageNumber'> |
{page} |
Code Migration Examples
Example 1: HTML String to PDF Conversion
Before (Playwright):
// NuGet: Install-Package Microsoft.Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
string html = "<h1>Hello World</h1><p>This is a test PDF.</p>";
await page.SetContentAsync(html);
await page.PdfAsync(new PagePdfOptions { Path = "output.pdf" });
await browser.CloseAsync();
}
}
// NuGet: Install-Package Microsoft.Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
string html = "<h1>Hello World</h1><p>This is a test PDF.</p>";
await page.SetContentAsync(html);
await page.PdfAsync(new PagePdfOptions { Path = "output.pdf" });
await browser.CloseAsync();
}
}
Imports Microsoft.Playwright
Imports System.Threading.Tasks
Module Program
Async Function Main(args As String()) As Task
Dim playwright = Await Playwright.CreateAsync()
Dim browser = Await playwright.Chromium.LaunchAsync()
Dim page = Await browser.NewPageAsync()
Dim html As String = "<h1>Hello World</h1><p>This is a test PDF.</p>"
Await page.SetContentAsync(html)
Await page.PdfAsync(New PagePdfOptions With {.Path = "output.pdf"})
Await browser.CloseAsync()
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
string html = "<h1>Hello World</h1><p>This is a test PDF.</p>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
string html = "<h1>Hello World</h1><p>This is a test PDF.</p>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main(ByVal args As String())
Dim renderer = New ChromePdfRenderer()
Dim html As String = "<h1>Hello World</h1><p>This is a test PDF.</p>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
End Sub
End Class
This example demonstrates the fundamental architectural difference. Playwright requires five async operations: Playwright.CreateAsync(), Chromium.LaunchAsync(), NewPageAsync(), SetContentAsync(), and PdfAsync(), plus explicit browser cleanup with CloseAsync().
IronPDF eliminates all this complexity: create a ChromePdfRenderer, call RenderHtmlAsPdf(), and SaveAs(). No async patterns, no browser lifecycle, no cleanup code. 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 (Playwright):
// NuGet: Install-Package Microsoft.Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
await page.GotoAsync("https://www.example.com");
await page.PdfAsync(new PagePdfOptions
{
Path = "webpage.pdf",
Format = "A4"
});
await browser.CloseAsync();
}
}
// NuGet: Install-Package Microsoft.Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
await page.GotoAsync("https://www.example.com");
await page.PdfAsync(new PagePdfOptions
{
Path = "webpage.pdf",
Format = "A4"
});
await browser.CloseAsync();
}
}
Imports Microsoft.Playwright
Imports System.Threading.Tasks
Module Program
Async Function Main(args As String()) As Task
Dim playwright = Await Playwright.CreateAsync()
Dim browser = Await playwright.Chromium.LaunchAsync()
Dim page = Await browser.NewPageAsync()
Await page.GotoAsync("https://www.example.com")
Await page.PdfAsync(New PagePdfOptions With {
.Path = "webpage.pdf",
.Format = "A4"
})
Await browser.CloseAsync()
End Function
End Module
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");
}
}
// 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");
}
}
Imports IronPdf
Class Program
Shared Sub Main(ByVal args As String())
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End Class
Playwright 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. Note that Playwright requires specifying the Format in PagePdfOptions, while IronPDF uses RenderingOptions.PaperSize for paper size configuration. Learn more in our tutorials.
Example 3: Custom Page Size with Margins
Before (Playwright):
// NuGet: Install-Package Microsoft.Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
await page.SetContentAsync("<h1>Custom PDF</h1><p>Letter size with margins</p>");
await page.PdfAsync(new PagePdfOptions
{
Path = "custom.pdf",
Format = "Letter",
Margin = new Margin { Top = "1in", Bottom = "1in", Left = "0.5in", Right = "0.5in" }
});
}
}
// NuGet: Install-Package Microsoft.Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
await page.SetContentAsync("<h1>Custom PDF</h1><p>Letter size with margins</p>");
await page.PdfAsync(new PagePdfOptions
{
Path = "custom.pdf",
Format = "Letter",
Margin = new Margin { Top = "1in", Bottom = "1in", Left = "0.5in", Right = "0.5in" }
});
}
}
Imports Microsoft.Playwright
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Using playwright = Await Playwright.CreateAsync()
Await Using browser = Await playwright.Chromium.LaunchAsync()
Dim page = Await browser.NewPageAsync()
Await page.SetContentAsync("<h1>Custom PDF</h1><p>Letter size with margins</p>")
Await page.PdfAsync(New PagePdfOptions With {
.Path = "custom.pdf",
.Format = "Letter",
.Margin = New Margin With {
.Top = "1in",
.Bottom = "1in",
.Left = "0.5in",
.Right = "0.5in"
}
})
End Using
End Using
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 25;
renderer.RenderingOptions.MarginBottom = 25;
renderer.RenderingOptions.MarginLeft = 12;
renderer.RenderingOptions.MarginRight = 12;
var pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>Letter size with margins</p>");
pdf.SaveAs("custom.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 25;
renderer.RenderingOptions.MarginBottom = 25;
renderer.RenderingOptions.MarginLeft = 12;
renderer.RenderingOptions.MarginRight = 12;
var pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>Letter size with margins</p>");
pdf.SaveAs("custom.pdf");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Class Program
Shared Sub Main()
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter
renderer.RenderingOptions.MarginTop = 25
renderer.RenderingOptions.MarginBottom = 25
renderer.RenderingOptions.MarginLeft = 12
renderer.RenderingOptions.MarginRight = 12
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>Letter size with margins</p>")
pdf.SaveAs("custom.pdf")
End Sub
End Class
Playwright uses string-based margin values ("1in", "0.5in") while IronPDF uses numeric millimeter values. The conversion is: 1 inch = 25.4mm, so "1in" becomes 25 and "0.5in" becomes approximately 12. Playwright's Format = "Letter" maps to IronPDF's PaperSize = PdfPaperSize.Letter.
Example 4: Headers, Footers, and Custom Settings
Before (Playwright):
// NuGet: Install-Package Microsoft.Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
string html = "<h1>Custom PDF</h1><p>With margins and headers.</p>";
await page.SetContentAsync(html);
await page.PdfAsync(new PagePdfOptions
{
Path = "custom.pdf",
Format = "A4",
Margin = new Margin { Top = "1cm", Bottom = "1cm", Left = "1cm", Right = "1cm" },
DisplayHeaderFooter = true,
HeaderTemplate = "<div style='font-size:10px; text-align:center;'>Header</div>",
FooterTemplate = "<div style='font-size:10px; text-align:center;'>Page <span class='pageNumber'></span></div>"
});
await browser.CloseAsync();
}
}
// NuGet: Install-Package Microsoft.Playwright
using Microsoft.Playwright;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
string html = "<h1>Custom PDF</h1><p>With margins and headers.</p>";
await page.SetContentAsync(html);
await page.PdfAsync(new PagePdfOptions
{
Path = "custom.pdf",
Format = "A4",
Margin = new Margin { Top = "1cm", Bottom = "1cm", Left = "1cm", Right = "1cm" },
DisplayHeaderFooter = true,
HeaderTemplate = "<div style='font-size:10px; text-align:center;'>Header</div>",
FooterTemplate = "<div style='font-size:10px; text-align:center;'>Page <span class='pageNumber'></span></div>"
});
await browser.CloseAsync();
}
}
Imports Microsoft.Playwright
Imports System.Threading.Tasks
Module Program
Async Function Main(args As String()) As Task
Dim playwright = Await Playwright.CreateAsync()
Dim browser = Await playwright.Chromium.LaunchAsync()
Dim page = Await browser.NewPageAsync()
Dim html As String = "<h1>Custom PDF</h1><p>With margins and headers.</p>"
Await page.SetContentAsync(html)
Await page.PdfAsync(New PagePdfOptions With {
.Path = "custom.pdf",
.Format = "A4",
.Margin = New Margin With {.Top = "1cm", .Bottom = "1cm", .Left = "1cm", .Right = "1cm"},
.DisplayHeaderFooter = True,
.HeaderTemplate = "<div style='font-size:10px; text-align:center;'>Header</div>",
.FooterTemplate = "<div style='font-size:10px; text-align:center;'>Page <span class='pageNumber'></span></div>"
})
Await browser.CloseAsync()
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.TextHeader.CenterText = "Header";
renderer.RenderingOptions.TextFooter.CenterText = "Page {page}";
string html = "<h1>Custom PDF</h1><p>With margins and headers.</p>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.TextHeader.CenterText = "Header";
renderer.RenderingOptions.TextFooter.CenterText = "Page {page}";
string html = "<h1>Custom PDF</h1><p>With margins and headers.</p>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom.pdf");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Class Program
Shared Sub Main(args As String())
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.MarginTop = 10
renderer.RenderingOptions.MarginBottom = 10
renderer.RenderingOptions.MarginLeft = 10
renderer.RenderingOptions.MarginRight = 10
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.TextHeader.CenterText = "Header"
renderer.RenderingOptions.TextFooter.CenterText = "Page {page}"
Dim html As String = "<h1>Custom PDF</h1><p>With margins and headers.</p>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("custom.pdf")
End Sub
End Class
This example shows the header/footer placeholder syntax difference. Playwright uses HTML class-based placeholders (<span class='pageNumber'></span>), while IronPDF uses curly brace placeholders ({page}). Note that Playwright requires DisplayHeaderFooter = true to enable headers/footers, while IronPDF enables them automatically when you set header/footer content.
Critical Migration Notes
Async to Sync Conversion
Playwright requires async/await throughout; IronPDF supports synchronous operations:
// Playwright: Async required
public async Task<byte[]> GeneratePdfAsync(string html)
{
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
await page.SetContentAsync(html);
return await page.PdfAsync();
}
// IronPDF: Sync is simpler
public byte[] GeneratePdf(string html)
{
var renderer = new ChromePdfRenderer();
return renderer.RenderHtmlAsPdf(html).BinaryData;
}
// Playwright: Async required
public async Task<byte[]> GeneratePdfAsync(string html)
{
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
await page.SetContentAsync(html);
return await page.PdfAsync();
}
// IronPDF: Sync is simpler
public byte[] GeneratePdf(string html)
{
var renderer = new ChromePdfRenderer();
return renderer.RenderHtmlAsPdf(html).BinaryData;
}
Imports System.Threading.Tasks
Imports Microsoft.Playwright
Public Class PdfGenerator
' Playwright: Async required
Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte())
Using playwright = Await Playwright.CreateAsync()
Await Using browser = Await playwright.Chromium.LaunchAsync()
Dim page = Await browser.NewPageAsync()
Await page.SetContentAsync(html)
Return Await page.PdfAsync()
End Using
End Using
End Function
' IronPDF: Sync is simpler
Public Function GeneratePdf(html As String) As Byte()
Dim renderer = New ChromePdfRenderer()
Return renderer.RenderHtmlAsPdf(html).BinaryData
End Function
End Class
Margin Unit Conversion
Playwright uses string units; IronPDF uses numeric millimeters:
| Playwright | IronPDF (mm) |
|---|---|
"1in" |
25 |
"0.5in" |
12 |
"1cm" |
10 |
Header/Footer Placeholder Conversion
| Playwright Class | IronPDF Placeholder |
|---|---|
<span class='pageNumber'> |
{page} |
<span class='totalPages'> |
{total-pages} |
<span class='date'> |
{date} |
<span class='title'> |
{html-title} |
Browser Lifecycle Elimination
Remove all browser management code:
// Playwright: Explicit cleanup required
await page.CloseAsync();
await browser.CloseAsync();
playwright.Dispose();
// IronPDF: No disposal needed - just use the renderer
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// Playwright: Explicit cleanup required
await page.CloseAsync();
await browser.CloseAsync();
playwright.Dispose();
// IronPDF: No disposal needed - just use the renderer
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
' Playwright: Explicit cleanup required
Await page.CloseAsync()
Await browser.CloseAsync()
playwright.Dispose()
' IronPDF: No disposal needed - just use the renderer
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
New Capabilities After Migration
After migrating to IronPDF, you gain capabilities that Playwright cannot provide:
PDF Merging
var pdf1 = renderer.RenderHtmlAsPdf(html1);
var pdf2 = renderer.RenderHtmlAsPdf(html2);
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
var pdf1 = renderer.RenderHtmlAsPdf(html1);
var pdf2 = renderer.RenderHtmlAsPdf(html2);
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
Dim pdf1 = renderer.RenderHtmlAsPdf(html1)
Dim pdf2 = renderer.RenderHtmlAsPdf(html2)
Dim merged = PdfDocument.Merge(pdf1, pdf2)
merged.SaveAs("merged.pdf")
Watermarks
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");
IRON VB CONVERTER ERROR developers@ironsoftware.com
Password Protection
pdf.SecuritySettings.OwnerPassword = "admin";
pdf.SecuritySettings.UserPassword = "readonly";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.OwnerPassword = "admin";
pdf.SecuritySettings.UserPassword = "readonly";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.OwnerPassword = "admin"
pdf.SecuritySettings.UserPassword = "readonly"
pdf.SecuritySettings.AllowUserCopyPasteContent = False
Digital Signatures
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
Dim signature = New PdfSignature("certificate.pfx", "password")
pdf.Sign(signature)
PDF/A Compliance
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b)
Migration Checklist
Pre-Migration
- Identify all Playwright PDF generation code
- Document margin values (convert inches/cm to millimeters)
- Note header/footer placeholder syntax for conversion
- Obtain IronPDF license key from ironpdf.com
Package Changes
- Remove the
Microsoft.PlaywrightNuGet package - Delete the
.playwrightfolder (and any cached Playwright browser binaries under your user profile) - Install the
IronPdfNuGet package:dotnet add package IronPdf
Code Changes
- Update namespace imports
- Replace async browser lifecycle with
ChromePdfRenderer - Convert
page.SetContentAsync()+page.PdfAsync()toRenderHtmlAsPdf() - Convert
page.GotoAsync()+page.PdfAsync()toRenderUrlAsPdf() - Convert margin strings to millimeter values
- Convert header/footer placeholder syntax
- Remove all browser/page disposal code
- Add license initialization at application startup
Post-Migration
- Visual comparison of PDF output
- Verify header/footer rendering with page numbers
- Test margin and page sizing accuracy
- Add new capabilities (security, watermarks, merging) as needed

