Converting HTML to PDF in C# is a common requirement, but choosing the right library can be challenging. I've used all three major approaches in production, and they each solve different problems—sometimes poorly.
In this article, I'll compare IronPDF, wkhtmltopdf, and Playwright for HTML-to-PDF conversion in C#, covering real-world pain points I've encountered with each.
What's the Best Way to Convert HTML to PDF in C#?
The short answer: it depends on your constraints.
If you need modern CSS support, reliable deployment, and you're building a commercial application, IronPDF wins. If you're maintaining legacy code that already uses wkhtmltopdf, start planning your migration—it's officially abandoned. If you're rendering complex JavaScript-heavy SPAs and don't mind managing browser binaries, Playwright works but comes with overhead.
Here's a minimal example with IronPDF:
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var renderer = new [ChromePdfRenderer](https://ironpdf.com/blog/videos/how-to-render-webgl-sites-to-pdf-in-csharp-ironpdf/)();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello from C#</h1>");
pdf.SaveAs("output.pdf");
That's it. No external binaries, no process management, no headaches.
Why Did wkhtmltopdf Get Abandoned?
In 2024, wkhtmltopdf was officially abandoned. The project relied on a Qt WebKit snapshot from 2015—frozen in time with no security patches, no modern browser features, and no bug fixes.
I used wkhtmltopdf in production for years. The pain points were real:
- Deployment nightmares: Copy a binary onto the server, hope native dependencies are installed, watch it crash unpredictably
- Memory leaks: Required periodic process restarts to avoid memory exhaustion
- CSS limitations: No flexbox support, which means Bootstrap 4/5 layouts break silently
- Known CVEs: Security vulnerabilities that will never be patched
- Process overhead: Spawning external processes for every conversion adds latency
Every C# library built on wkhtmltopdf—TuesPechkin, Rotativa, DinkToPdf—became instant technical debt the moment the project was abandoned.
If you're still using wkhtmltopdf, you're running a security risk and missing out on a decade of web standards improvements.
How Does IronPDF Compare to wkhtmltopdf?
IronPDF uses a modern Chromium rendering engine, the same engine that powers Google Chrome. This means full support for HTML5, CSS3, JavaScript, flexbox, CSS Grid, and modern web fonts.
Here's what I appreciate about IronPDF after migrating from wkhtmltopdf:
Modern CSS just works:
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var html = @"
<div style='display: flex; justify-content: space-between;'>
<div>Left column</div>
<div>Right column</div>
</div>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("flexbox-layout.pdf");
wkhtmltopdf would silently break that flexbox layout. IronPDF renders it pixel-perfect.
No external binaries:
IronPDF is a managed .NET library. You install it via NuGet, and it just works on Windows, Linux, macOS, Docker, and Azure. No copying binaries, no native dependencies, no platform-specific quirks.
Better performance:
Once warmed up, IronPDF is faster than wkhtmltopdf for batch processing. The Chromium engine is heavily optimized, and you're not paying the cost of spawning external processes for every conversion.
Security:
IronPDF runs within your application's security context as a managed library. wkhtmltopdf is an external executable with known CVEs that will never be fixed.
The trade-off:
IronPDF is a commercial library with licensing fees. wkhtmltopdf was free. But "free" software with security holes and no maintenance isn't actually free—it's a liability.
What About Playwright for HTML to PDF in C#?
Playwright is Microsoft's browser automation library, similar to Puppeteer. It's powerful for testing and web scraping, but using it for HTML-to-PDF conversion has significant overhead.
Here's what a Playwright conversion looks like:
using Microsoft.Playwright;
// Install via NuGet: Install-Package Microsoft.Playwright
var playwright = await Playwright.CreateAsync();
var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
await page.SetContentAsync("<h1>Hello from Playwright</h1>");
await page.PdfAsync(new() { Path = "output.pdf" });
await browser.CloseAsync();
That's more verbose than IronPDF, and it hides complexity.
Why Is Playwright Slower Than IronPDF for PDF Generation?
Playwright spawns fresh browser processes for each conversion (or maintains heavy browser contexts). This works great for testing and automation, but for high-throughput PDF generation, it's inefficient.
Resource overhead:
Playwright manages 300MB+ of Chromium browser binaries. IronPDF embeds the rendering engine more efficiently.
Process management:
You're responsible for managing browser lifecycles, handling crashes, and cleaning up processes. IronPDF handles this internally.
Deployment complexity:
Playwright requires installing browser binaries separately. In Docker, that's extra steps. In serverless environments, it's often impractical.
When Playwright makes sense:
If you're already using Playwright for end-to-end testing and need occasional PDF generation, reusing the infrastructure makes sense. But if PDF generation is your primary use case, IronPDF is purpose-built for it.
Does IronPDF Support JavaScript-Rendered Content?
Yes. IronPDF uses Chromium, so JavaScript executes before rendering.
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var html = @"
<div id='content'></div>
<script>
document.getElementById('content').innerText = 'Rendered by JavaScript';
</script>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("js-rendered.pdf");
Playwright handles this too, but wkhtmltopdf often fails with modern JavaScript frameworks.
Which Library Should I Choose for Production?
Here's my decision framework after using all three in production:
Choose IronPDF if:
- You need modern CSS/JavaScript support
- You're building a commercial application (licensing cost is acceptable)
- You want simple deployment (NuGet package, no external binaries)
- You need cross-platform support (Windows/Linux/macOS/Docker)
- You value reliability and support
Avoid wkhtmltopdf because:
- It's officially abandoned (as of 2024)
- Known security vulnerabilities will never be patched
- No support for modern CSS (flexbox, Grid, etc.)
- Deployment is painful
- Memory leaks require process restarts
Consider Playwright if:
- You're already using it for testing/automation
- You need occasional PDF generation (not high throughput)
- You're okay managing browser binaries and processes
- Licensing cost is a blocker (Playwright is open source)
- You're okay with printer quality PDFs that don't look The HTML source code you have given it
How Do I Migrate from wkhtmltopdf to IronPDF?
The migration is straightforward. Where you were invoking wkhtmltopdf as an external process, replace it with IronPDF's API.
Before (wkhtmltopdf via Process):
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "wkhtmltopdf.exe",
Arguments = "input.html output.pdf"
}
};
process.Start();
process.WaitForExit();
After (IronPDF):
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlFileAsPdf("input.html");
pdf.SaveAs("output.pdf");
Simpler code, better CSS support, no process management.
What Are the Licensing Costs?
This is where the comparison gets practical:
- wkhtmltopdf: Free (LGPL), but abandoned and insecure
- Playwright: Free (Apache 2.0), but high operational overhead
- IronPDF: Commercial licensing required (starts around $749 for a single developer, with deployment licenses available)
For a commercial application, IronPDF's licensing cost is negligible compared to the engineering time saved on deployment, debugging, and maintenance.
For open-source projects or tight budgets, Playwright is viable if you're willing to manage the complexity.
Can I Handle CSS Media Queries and Print Styles?
All three libraries support CSS @media print rules, but IronPDF handles them most reliably because it uses a modern Chromium engine.
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var html = @"
<style>
@media print {
.no-print { display: none; }
}
</style>
<div class='no-print'>This won't appear in the PDF</div>
<div>This will appear</div>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("print-styles.pdf");
wkhtmltopdf supports this but inconsistently. Playwright handles it well but with more boilerplate.
What About Performance Benchmarks?
I've run batch conversions with all three libraries in production. Here's what I've observed:
IronPDF:
- Warm-up time: ~1-2 seconds (first conversion initializes Chromium)
- Throughput: 50-100+ PDFs per minute (depends on HTML complexity)
- Memory: Stable, no leaks
wkhtmltopdf:
- Process spawn overhead: ~200-500ms per conversion
- Throughput: 30-60 PDFs per minute
- Memory: Leaks over time, requires periodic restarts
Playwright:
- Process spawn overhead: ~500ms-1s per conversion (if launching fresh browser)
- Throughput: 20-40 PDFs per minute
- Memory: High (300MB+ for browser binaries)
For high-volume PDF generation, IronPDF scales best.
How Do I Handle Headers, Footers, and Page Numbers?
IronPDF makes this trivial:
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
HtmlFragment = "<div style='text-align: center;'>Page Header</div>"
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
HtmlFragment = "<div style='text-align: center;'>Page {page} of {total-pages}</div>"
};
var pdf = renderer.RenderHtmlAsPdf("<h1>Document with Headers/Footers</h1>");
pdf.SaveAs("headers-footers.pdf");
wkhtmltopdf supports this via command-line flags, but it's clunky. Playwright requires manual CSS for headers/footers.
Final Recommendation
After years of using all three approaches, here's my take:
For new projects in 2025, use IronPDF. The licensing cost is worth the reliability, deployment simplicity, and modern CSS support. wkhtmltopdf is dead—don't start new projects with it. Playwright is powerful but overengineered for PDF generation unless you're already invested in it for other purposes.
If you're maintaining legacy wkhtmltopdf code, prioritize migrating to IronPDF. The technical debt and security risks aren't worth the "free" license.
Written by Jacob Mellor, CTO at Iron Software. Jacob created IronPDF and leads a team of 50+ engineers building .NET document processing libraries.
Top comments (0)