wkhtmltopdf vs IronPDF: Technical Comparison Guide
When .NET developers need to convert HTML to PDF, wkhtmltopdf has historically been a popular choice due to its open-source nature and command-line simplicity. However, the project's abandonment and critical security vulnerabilities have prompted many teams to evaluate modern alternatives. This technical comparison examines wkhtmltopdf alongside IronPDF to help architects and developers understand the significant differences in security posture, rendering capabilities, and long-term viability.
Understanding wkhtmltopdf
wkhtmltopdf is a tool that converts HTML to PDF documents, operating directly from the command line and leveraging Qt WebKit to process HTML content. During its years of active development, the library gained popularity for its free LGPLv3 licensing and cross-platform availability.
However, wkhtmltopdf now presents critical challenges that cannot be ignored:
- Project Abandonment: The last meaningful software updates occurred around 2016-2017
- Critical Security Vulnerability: CVE-2022-35583 (CVSS 9.8 severity) is an SSRF vulnerability that remains unpatched
- Outdated Rendering Engine: Relies on Qt WebKit from 2015
- Limited Modern Web Support: No CSS Grid support, broken Flexbox implementation, no ES6+ JavaScript
- Ecosystem Stagnation: All .NET wrapper libraries (DinkToPdf, Rotativa, TuesPechkin, WkHtmlToPdf-DotNet, NReco.PdfGenerator) inherit these vulnerabilities
The CVE-2022-35583 Security Crisis
The Server-Side Request Forgery (SSRF) vulnerability in wkhtmltopdf allows attackers to:
- Access Internal Services: Reach internal APIs, databases, and services behind firewalls
- Steal Credentials: Access cloud metadata endpoints (AWS, GCP, Azure) to steal IAM credentials
- Port Scanning: Scan internal networks from within infrastructure
- Data Exfiltration: Extract sensitive data through crafted HTML/CSS
The attack vector is straightforward—malicious HTML submitted to a PDF generator:
<!-- Malicious HTML submitted to your PDF generator -->
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin"/><!-- Malicious HTML submitted to your PDF generator -->
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin"/>When wkhtmltopdf renders this HTML, it fetches these URLs from the server's network context, bypassing firewalls and security controls. This vulnerability will never be patched because the project has been officially abandoned.
Understanding IronPDF
IronPDF presents a robust alternative that addresses wkhtmltopdf's shortcomings. With active maintenance, regular updates, and reliance on the current Chromium rendering engine, IronPDF provides both security and modern web standards compliance.
Key characteristics include:
- Modern Chromium Engine: Uses the current Chromium rendering engine with full ES2024 JavaScript support
- No Known CVEs: Zero known security vulnerabilities
- Active Development: Regular releases with security updates and feature enhancements
- Complete CSS Support: Full CSS Grid, Flexbox, and modern layout systems
- Comprehensive PDF Features: Digital signatures, PDF/A compliance, PDF manipulation capabilities
- Professional Support: Extensive documentation and dedicated support channels
Feature Comparison
The following table highlights the fundamental differences between wkhtmltopdf and IronPDF:
| Feature | wkhtmltopdf | IronPDF |
|---|---|---|
| Licensing | LGPLv3 (Free) | Commercial |
| Rendering Engine | Qt WebKit (2015) | Current Chromium Engine |
| Security Status | CVE-2022-35583 CRITICAL (9.8) UNPATCHED | No known CVEs |
| Last Meaningful Update | 2016-2017 | Active development |
| CSS Grid | Not supported | Supported |
| Flexbox | Broken | Supported |
| ES6+ JavaScript | Not supported | Supported |
| Async/Await | Not supported | Supported |
| PDF Manipulation | Not supported | Supported |
| Digital Signatures | Not supported | Supported |
| PDF/A Compliance | Not supported | Supported |
| Professional Support | None (abandoned) | Commercial with SLA |
| C# Integration | Via third-party wrappers | Direct, regularly updated |
Affected Wrapper Libraries
All .NET wrappers for wkhtmltopdf inherit the same vulnerabilities:
| Wrapper Library | Status | Security Risk |
|---|---|---|
| DinkToPdf | Abandoned | CRITICAL |
| Rotativa | Abandoned | CRITICAL |
| TuesPechkin | Abandoned | CRITICAL |
| WkHtmlToPdf-DotNet | Abandoned | CRITICAL |
| NReco.PdfGenerator | Uses wkhtmltopdf | CRITICAL |
If your application uses any of these libraries, it is vulnerable to CVE-2022-35583.
API Architecture Differences
The API patterns between wkhtmltopdf wrappers and IronPDF reveal significant differences in complexity and usability.
wkhtmltopdf Configuration Pattern
wkhtmltopdf wrappers require creating document objects with nested settings configurations:
// NuGet: Install-Package WkHtmlToPdf-DotNet
using WkHtmlToPdfDotNet;
using WkHtmlToPdfDotNet.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4
},
Objects = {
new ObjectSettings()
{
HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("output.pdf", pdf);
}
}// NuGet: Install-Package WkHtmlToPdf-DotNet
using WkHtmlToPdfDotNet;
using WkHtmlToPdfDotNet.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4
},
Objects = {
new ObjectSettings()
{
HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("output.pdf", pdf);
}
}This pattern requires creating a SynchronizedConverter with PdfTools, constructing an HtmlToPdfDocument with GlobalSettings and Objects collections, and manually writing byte arrays to files.
IronPDF Simplified Pattern
IronPDF uses a streamlined approach with the ChromePdfRenderer class:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML.</p>");
pdf.SaveAs("output.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML.</p>");
pdf.SaveAs("output.pdf");
}
}The ChromePdfRenderer class eliminates the nested configuration objects, returning a PdfDocument with built-in save methods. For comprehensive HTML conversion guidance, see the HTML to PDF tutorial.
URL to PDF Conversion
Converting web pages to PDF demonstrates the complexity difference between the approaches.
wkhtmltopdf Implementation
wkhtmltopdf uses the Page property within ObjectSettings to specify URLs:
// NuGet: Install-Package WkHtmlToPdf-DotNet
using WkHtmlToPdfDotNet;
using WkHtmlToPdfDotNet.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4
},
Objects = {
new ObjectSettings()
{
Page = "https://www.example.com"
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("webpage.pdf", pdf);
}
}// NuGet: Install-Package WkHtmlToPdf-DotNet
using WkHtmlToPdfDotNet;
using WkHtmlToPdfDotNet.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4
},
Objects = {
new ObjectSettings()
{
Page = "https://www.example.com"
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("webpage.pdf", pdf);
}
}IronPDF Implementation
IronPDF provides a dedicated RenderUrlAsPdf method:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}The RenderUrlAsPdf method leverages the Chromium engine to render pages with full JavaScript execution and modern CSS support—capabilities limited by wkhtmltopdf's 2015 WebKit engine.
Custom PDF Settings
Configuring page dimensions, margins, and orientation reveals the structural differences between the APIs.
wkhtmltopdf Custom Settings
wkhtmltopdf requires nested GlobalSettings with MarginSettings objects:
// NuGet: Install-Package WkHtmlToPdf-DotNet
using WkHtmlToPdfDotNet;
using WkHtmlToPdfDotNet.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Landscape,
PaperSize = PaperKind.A4,
Margins = new MarginSettings() { Top = 10, Bottom = 10, Left = 10, Right = 10 }
},
Objects = {
new ObjectSettings()
{
Page = "input.html",
WebSettings = { DefaultEncoding = "utf-8" }
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("custom-output.pdf", pdf);
}
}// NuGet: Install-Package WkHtmlToPdf-DotNet
using WkHtmlToPdfDotNet;
using WkHtmlToPdfDotNet.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Landscape,
PaperSize = PaperKind.A4,
Margins = new MarginSettings() { Top = 10, Bottom = 10, Left = 10, Right = 10 }
},
Objects = {
new ObjectSettings()
{
Page = "input.html",
WebSettings = { DefaultEncoding = "utf-8" }
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("custom-output.pdf", pdf);
}
}IronPDF Custom Settings
IronPDF uses RenderingOptions properties for direct configuration:
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
var pdf = renderer.RenderHtmlFileAsPdf("input.html");
pdf.SaveAs("custom-output.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
var pdf = renderer.RenderHtmlFileAsPdf("input.html");
pdf.SaveAs("custom-output.pdf");
}
}API Mapping Reference
Teams evaluating a transition from wkhtmltopdf to IronPDF will find this mapping helpful for understanding concept equivalences:
CLI to C# API Mapping
| wkhtmltopdf CLI Option | IronPDF Equivalent |
|---|---|
wkhtmltopdf input.html output.pdf | renderer.RenderHtmlFileAsPdf() |
wkhtmltopdf URL output.pdf | renderer.RenderUrlAsPdf() |
--page-size A4 | RenderingOptions.PaperSize = PdfPaperSize.A4 |
--page-size Letter | RenderingOptions.PaperSize = PdfPaperSize.Letter |
--orientation Landscape | RenderingOptions.PaperOrientation = Landscape |
--margin-top 10mm | RenderingOptions.MarginTop = 10 |
--margin-bottom 10mm | RenderingOptions.MarginBottom = 10 |
--margin-left 10mm | RenderingOptions.MarginLeft = 10 |
--margin-right 10mm | RenderingOptions.MarginRight = 10 |
--header-html header.html | RenderingOptions.HtmlHeader |
--footer-html footer.html | RenderingOptions.HtmlFooter |
--footer-center "[page]" | {page} placeholder |
--footer-center "[toPage]" | {total-pages} placeholder |
--enable-javascript | Enabled by default |
--javascript-delay 500 | RenderingOptions.WaitFor.RenderDelay = 500 |
--print-media-type | RenderingOptions.CssMediaType = Print |
--dpi 300 | RenderingOptions.Dpi = 300 |
--grayscale | RenderingOptions.GrayScale = true |
--zoom 0.8 | RenderingOptions.Zoom = 80 |
C# Wrapper API Mapping
| wkhtmltopdf Wrapper | IronPDF |
|---|---|
SynchronizedConverter | ChromePdfRenderer |
HtmlToPdfDocument | RenderingOptions |
GlobalSettings.Out | pdf.SaveAs() |
GlobalSettings.PaperSize | RenderingOptions.PaperSize |
GlobalSettings.Orientation | RenderingOptions.PaperOrientation |
GlobalSettings.Margins | RenderingOptions.Margin* |
ObjectSettings.Page | RenderHtmlFileAsPdf() |
ObjectSettings.HtmlContent | RenderHtmlAsPdf() |
HeaderSettings.Center | TextHeader.CenterText |
FooterSettings.Center | TextFooter.CenterText |
converter.Convert(doc) | renderer.RenderHtmlAsPdf() |
Placeholder Syntax Mapping
| wkhtmltopdf Placeholder | IronPDF Placeholder |
|---|---|
[page] | {page} |
[toPage] | {total-pages} |
[date] | {date} |
[time] | {time} |
[title] | {html-title} |
[url] | {url} |
When Teams Consider Moving from wkhtmltopdf to IronPDF
Several scenarios commonly prompt development teams to evaluate IronPDF as an alternative to wkhtmltopdf:
Security Compliance Requirements
Organizations with security compliance requirements (SOC 2, PCI DSS, HIPAA) cannot accept applications with known critical vulnerabilities. CVE-2022-35583's 9.8 severity rating triggers immediate remediation requirements in most security frameworks.
Modern CSS Framework Adoption
Teams adopting Bootstrap 5, Tailwind CSS, or custom CSS Grid layouts find that wkhtmltopdf cannot render these correctly. The 2015 WebKit engine lacks CSS Grid support entirely and has broken Flexbox implementation.
JavaScript Application Requirements
Applications using modern JavaScript features—ES6+ syntax including arrow functions, async/await, classes, and template literals—experience failures in wkhtmltopdf. IronPDF's Chromium engine provides complete JavaScript support.
Cloud and Container Deployments
Modern deployment strategies using Docker, Kubernetes, or cloud platforms benefit from IronPDF's container-friendly architecture. Security scans of wkhtmltopdf binaries in containers will flag the CVE vulnerability.
Long-Term Maintenance Concerns
With no future updates expected for wkhtmltopdf, teams face increasing technical debt as web standards evolve. IronPDF's active development ensures continued compatibility with future .NET versions, including .NET 10 expected in 2026.
Additional IronPDF Capabilities
Beyond HTML-to-PDF conversion, IronPDF provides document manipulation features that wkhtmltopdf cannot offer:
- Merging PDFs: Combine multiple documents into single files
- Splitting Documents: Extract page ranges into separate PDFs
- Digital Signatures: Apply cryptographic signatures for document authenticity
- Watermarking: Add text or image watermarks
- PDF/A Compliance: Generate archival-standard documents
- Form Filling: Programmatically populate PDF form fields
- Password Protection: Encrypt PDFs with user and owner passwords
- Headers and Footers: Automatic page numbering and branding with full HTML/CSS support
Async Support
IronPDF provides async/await support for web application performance:
public async Task<byte[]> GeneratePdfAsync(string html)
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}public async Task<byte[]> GeneratePdfAsync(string html)
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}This prevents thread blocking in high-load web applications—a capability not available with wkhtmltopdf's synchronous-only wrappers.
.NET Compatibility and Future Readiness
wkhtmltopdf's abandonment means no compatibility testing or updates for newer .NET versions. IronPDF maintains active development with regular updates, ensuring compatibility with .NET 8, .NET 9, and future releases including .NET 10 expected in 2026. The library's async/await support throughout its API aligns with modern C# development practices, including features anticipated in C# 14.
Conclusion
The divergence between wkhtmltopdf and IronPDF is significant across security, rendering capabilities, and long-term viability. wkhtmltopdf's critical SSRF vulnerability (CVE-2022-35583) combined with project abandonment creates an untenable security posture for production applications. The 2015 WebKit engine cannot handle modern CSS Grid, has broken Flexbox support, and fails on ES6+ JavaScript.
IronPDF's Chromium-based rendering engine provides full support for modern web standards while maintaining zero known CVEs. Its simplified API design—methods like RenderHtmlAsPdf() and SaveAs() instead of nested configuration objects—reduces code complexity while adding capabilities like PDF manipulation, digital signatures, and async support that wkhtmltopdf cannot provide.
For teams currently using wkhtmltopdf or its wrapper libraries (DinkToPdf, Rotativa, TuesPechkin), the security implications demand immediate evaluation of alternatives. The API mapping between wkhtmltopdf CLI options and IronPDF's RenderingOptions is straightforward, and IronPDF consistently requires less code while eliminating the security risks inherent in wkhtmltopdf.
For additional implementation guidance, explore the IronPDF documentation and tutorials covering specific use cases and advanced features.