How to Migrate from PeachPDF to IronPDF in C#
Migrating from PeachPDF to IronPDF provides access to enterprise-grade PDF generation with comprehensive features, active development, and professional support. This guide provides a step-by-step migration path that takes you from PeachPDF's pre-1.0 async HTML-to-PDF workflow to a fuller-featured PDF solution with Chromium rendering, security settings, and document manipulation APIs.
Why Migrate from PeachPDF to IronPDF
Understanding PeachPDF
PeachPDF is a relatively new entrant in the .NET ecosystem designed for developers who need to convert HTML to PDF. As a library, PeachPDF promises a pure .NET implementation, setting itself apart by not relying on external processes, ensuring it can be seamlessly integrated across platforms where .NET is supported. This characteristic positions PeachPDF as an appealing choice for projects looking for a lightweight, managed library solution.
Despite its potential, PeachPDF is still in development, highlighting both exciting possibilities and notable limitations. PeachPDF remains enticing because of its pure .NET core, which promises straightforward deployment in diverse environments. However, it also translates into limited adoption, with a smaller user base and community-driven support.
The Limitations of PeachPDF
PeachPDF is a single-maintainer, pre-1.0 .NET library (latest 0.7.26, October 2025) released under BSD-3-Clause by jhaygood86. It lacks the maturity, features, and support of established solutions. Key reasons to migrate:
-
Pre-1.0 Feature Set: PeachPDF has no built-in digital signatures, PDF/A compliance, OCR, form filling, or page-level header/footer API.
-
No JavaScript engine: PeachPDF is a layout renderer built on
PeachPDF.PdfSharpCore, not a browser; scripts and complex Grid/Flexbox layouts do not execute. -
net8.0only: the package targetsnet8.0; older .NET Framework / .NET 6 projects need to upgrade or pick a different library. -
Small Community: a single GitHub maintainer, limited documentation, limited examples.
- No Enterprise Support: no commercial support or SLA options.
PeachPDF vs IronPDF Comparison
| Feature/Characteristic | PeachPDF | IronPDF |
|---|---|---|
| Implementation | Pure managed .NET (on PeachPDF.PdfSharpCore + SixLabors) |
Managed with embedded Chromium runtime |
| License | BSD-3-Clause | Commercial |
| Target Framework | net8.0 only |
.NET Framework 4.6.2+, .NET 6/7/8 |
| User Base | Small (pre-1.0, 0.7.26 released Oct 2025) |
Large |
| Support | Community-driven (single maintainer, jhaygood86) |
Professional with dedicated support |
| HTML Rendering | HTML+CSS layout engine on PdfSharpCore | Full Chromium |
| CSS Support | HTML+CSS subset, web fonts, @font-face |
Full CSS3 |
| JavaScript | Not executed | Full ES2024 |
| Digital Signatures | No | Yes |
| PDF/A Compliance | No | Yes |
| Documentation | Limited (single README) | Extensive |
| Development Status | Pre-1.0 (0.7.26, Oct 2025) |
Mature, stable release |
IronPDF stands out with broader functionality, supporting not just HTML-to-PDF conversions but also OCR, watermarking, and other advanced features. Its professional support structure offers quick resolution paths for issues developers run into.
For teams adopting modern .NET, IronPDF provides comprehensive features and active maintenance to support long-term stability across current .NET versions.
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 PeachPDF
dotnet remove package PeachPDF
# Install IronPDF
dotnet add package IronPdf
# Remove PeachPDF
dotnet remove package PeachPDF
# Install IronPDF
dotnet add package IronPdf
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"
Identify PeachPDF Usage
# Audit PeachPDF usage in codebase
grep -r "using PeachPDF" --include="*.cs" .
grep -r "PdfGenerator\|PdfGenerateConfig\|GeneratePdf" --include="*.cs" .
# Audit PeachPDF usage in codebase
grep -r "using PeachPDF" --include="*.cs" .
grep -r "PdfGenerator\|PdfGenerateConfig\|GeneratePdf" --include="*.cs" .
Complete API Reference
Namespace Changes
// Before: PeachPDF
using PeachPDF;
using PeachPDF.PdfSharpCore;
using System.IO;
using System.Threading.Tasks;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
// Before: PeachPDF
using PeachPDF;
using PeachPDF.PdfSharpCore;
using System.IO;
using System.Threading.Tasks;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
Imports IronPdf
Imports IronPdf.Rendering
Imports System.IO
Imports System.Threading.Tasks
Core API Mappings
| PeachPDF | IronPDF |
|---|---|
new PdfGenerator() |
new ChromePdfRenderer() |
await generator.GeneratePdf(html, config) |
renderer.RenderHtmlAsPdf(html) |
document.Save(stream) |
pdf.SaveAs(path) |
document.Save(memStream) then memStream.ToArray() |
pdf.BinaryData |
new PdfGenerateConfig { NetworkAdapter = new HttpClientNetworkAdapter(...) } |
renderer.RenderUrlAsPdf(url) |
config.PageSize, config.PageOrientation |
renderer.RenderingOptions.PaperSize, .PaperOrientation |
Embed in source HTML (CSS position: fixed) |
RenderingOptions.HtmlHeader / HtmlFooter |
| Not supported | PdfDocument.FromFile(path) |
| Not supported | PdfDocument.Merge(pdfs) / pdf.AppendPdf(...) |
Code Migration Examples
Example 1: HTML String to PDF Conversion
Before (PeachPDF):
using PeachPDF;
using PeachPDF.PdfSharpCore;
using System.IO;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var html = "<html><body><h1>Hello World</h1></body></html>";
var config = new PdfGenerateConfig
{
PageSize = PageSize.Letter,
PageOrientation = PageOrientation.Portrait
};
var generator = new PdfGenerator();
var document = await generator.GeneratePdf(html, config);
using var stream = File.Create("output.pdf");
document.Save(stream);
}
}
using PeachPDF;
using PeachPDF.PdfSharpCore;
using System.IO;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var html = "<html><body><h1>Hello World</h1></body></html>";
var config = new PdfGenerateConfig
{
PageSize = PageSize.Letter,
PageOrientation = PageOrientation.Portrait
};
var generator = new PdfGenerator();
var document = await generator.GeneratePdf(html, config);
using var stream = File.Create("output.pdf");
document.Save(stream);
}
}
Imports PeachPDF
Imports PeachPDF.PdfSharpCore
Imports System.IO
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Dim html As String = "<html><body><h1>Hello World</h1></body></html>"
Dim config As New PdfGenerateConfig With {
.PageSize = PageSize.Letter,
.PageOrientation = PageOrientation.Portrait
}
Dim generator As New PdfGenerator()
Dim document = Await generator.GeneratePdf(html, config)
Using stream As FileStream = File.Create("output.pdf")
document.Save(stream)
End Using
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var html = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var html = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html = "<html><body><h1>Hello World</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
End Sub
End Class
This example shows the fundamental difference between the two libraries. PeachPDF separates a PdfGenerator (engine) from a PdfGenerateConfig (settings), exposes an async GeneratePdf method, and returns a document whose Save method writes to a Stream. IronPDF uses ChromePdfRenderer with RenderHtmlAsPdf(), which returns a PdfDocument object with a built-in SaveAs() method.
A practical advantage of IronPDF's approach: the PdfDocument object can be further manipulated (adding watermarks, merging, security settings) before saving, and SaveAs takes a file path directly without an intermediate FileStream. See the HTML to PDF documentation for further examples.
Example 2: URL to PDF Conversion
Before (PeachPDF):
// PeachPDF has no ConvertUrl-style helper; URL fetching is wired via
// HttpClientNetworkAdapter and passing null HTML so the engine fetches the page.
using PeachPDF;
using PeachPDF.Network;
using PeachPDF.PdfSharpCore;
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var http = new HttpClient();
var config = new PdfGenerateConfig
{
PageSize = PageSize.Letter,
NetworkAdapter = new HttpClientNetworkAdapter(http, new Uri("https://www.example.com"))
};
var generator = new PdfGenerator();
var document = await generator.GeneratePdf(null, config);
using var stream = File.Create("webpage.pdf");
document.Save(stream);
}
}
// PeachPDF has no ConvertUrl-style helper; URL fetching is wired via
// HttpClientNetworkAdapter and passing null HTML so the engine fetches the page.
using PeachPDF;
using PeachPDF.Network;
using PeachPDF.PdfSharpCore;
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var http = new HttpClient();
var config = new PdfGenerateConfig
{
PageSize = PageSize.Letter,
NetworkAdapter = new HttpClientNetworkAdapter(http, new Uri("https://www.example.com"))
};
var generator = new PdfGenerator();
var document = await generator.GeneratePdf(null, config);
using var stream = File.Create("webpage.pdf");
document.Save(stream);
}
}
Imports PeachPDF
Imports PeachPDF.Network
Imports PeachPDF.PdfSharpCore
Imports System
Imports System.IO
Imports System.Net.Http
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Dim http As New HttpClient()
Dim config As New PdfGenerateConfig With {
.PageSize = PageSize.Letter,
.NetworkAdapter = New HttpClientNetworkAdapter(http, New Uri("https://www.example.com"))
}
Dim generator As New PdfGenerator()
Dim document = Await generator.GeneratePdf(Nothing, config)
Using stream = File.Create("webpage.pdf")
document.Save(stream)
End Using
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var url = "https://www.example.com";
var pdf = renderer.RenderUrlAsPdf(url);
pdf.SaveAs("webpage.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var url = "https://www.example.com";
var pdf = renderer.RenderUrlAsPdf(url);
pdf.SaveAs("webpage.pdf");
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim url = "https://www.example.com"
Dim pdf = renderer.RenderUrlAsPdf(url)
pdf.SaveAs("webpage.pdf")
End Sub
End Class
PeachPDF has no first-class URL-to-PDF helper; you set NetworkAdapter on the config to an HttpClientNetworkAdapter and pass null HTML so the engine fetches the page. IronPDF exposes RenderUrlAsPdf(url) directly. Because PeachPDF does not execute JavaScript, single-page apps and dynamic content typically will not render correctly via the network adapter route; IronPDF's Chromium engine handles modern CSS and JavaScript. Learn more in our tutorials.
Example 3: Adding Headers and Footers
Before (PeachPDF):
// PeachPDF v0.7.x has no header/footer API. The closest approach is
// to embed the header/footer markup directly inside the source HTML
// using CSS positioning.
using PeachPDF;
using PeachPDF.PdfSharpCore;
using System.IO;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var html = @"
<html><head><style>
.header { position: fixed; top: 0; left: 0; right: 0; text-align:center; }
.footer { position: fixed; bottom: 0; left: 0; right: 0; text-align:center; }
</style></head>
<body>
<div class='header'>My Header</div>
<h1>Document Content</h1>
<div class='footer'>Footer text</div>
</body></html>";
var config = new PdfGenerateConfig { PageSize = PageSize.Letter };
var generator = new PdfGenerator();
var document = await generator.GeneratePdf(html, config);
using var stream = File.Create("document.pdf");
document.Save(stream);
}
}
// PeachPDF v0.7.x has no header/footer API. The closest approach is
// to embed the header/footer markup directly inside the source HTML
// using CSS positioning.
using PeachPDF;
using PeachPDF.PdfSharpCore;
using System.IO;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var html = @"
<html><head><style>
.header { position: fixed; top: 0; left: 0; right: 0; text-align:center; }
.footer { position: fixed; bottom: 0; left: 0; right: 0; text-align:center; }
</style></head>
<body>
<div class='header'>My Header</div>
<h1>Document Content</h1>
<div class='footer'>Footer text</div>
</body></html>";
var config = new PdfGenerateConfig { PageSize = PageSize.Letter };
var generator = new PdfGenerator();
var document = await generator.GeneratePdf(html, config);
using var stream = File.Create("document.pdf");
document.Save(stream);
}
}
Imports PeachPDF
Imports PeachPDF.PdfSharpCore
Imports System.IO
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Dim html As String = "
<html><head><style>
.header { position: fixed; top: 0; left: 0; right: 0; text-align:center; }
.footer { position: fixed; bottom: 0; left: 0; right: 0; text-align:center; }
</style></head>
<body>
<div class='header'>My Header</div>
<h1>Document Content</h1>
<div class='footer'>Footer text</div>
</body></html>"
Dim config As New PdfGenerateConfig With {.PageSize = PageSize.Letter}
Dim generator As New PdfGenerator()
Dim document = Await generator.GeneratePdf(html, config)
Using stream = File.Create("document.pdf")
document.Save(stream)
End Using
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter() { HtmlFragment = "<div style='text-align:center'>My Header</div>" };
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter() { HtmlFragment = "<div style='text-align:center'>Page {page}</div>" };
var html = "<html><body><h1>Document Content</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("document.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter() { HtmlFragment = "<div style='text-align:center'>My Header</div>" };
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter() { HtmlFragment = "<div style='text-align:center'>Page {page}</div>" };
var html = "<html><body><h1>Document Content</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("document.pdf");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Imports System
Module Program
Sub Main()
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.HtmlHeader = New HtmlHeaderFooter() With {.HtmlFragment = "<div style='text-align:center'>My Header</div>"}
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter() With {.HtmlFragment = "<div style='text-align:center'>Page {page}</div>"}
Dim html As String = "<html><body><h1>Document Content</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("document.pdf")
End Sub
End Module
This example shows a key architectural difference. PeachPDF does not expose a header/footer API on PdfGenerator or PdfGenerateConfig, so the page chrome has to live inside the source HTML using CSS positioning. IronPDF uses HtmlHeaderFooter objects assigned to RenderingOptions.HtmlHeader and RenderingOptions.HtmlFooter, separating page chrome from document content.
The IronPDF approach also exposes properties like MaxHeight for controlling header/footer size, and supports the {page} and {total-pages} placeholders for page numbering.
Note the additional namespace required for IronPDF: using IronPdf.Rendering; is needed for the HtmlHeaderFooter class.
Critical Migration Notes
Generator/Renderer Class Change
PeachPDF uses a PdfGenerator + PdfGenerateConfig pair; IronPDF uses a single ChromePdfRenderer:
// PeachPDF
var config = new PdfGenerateConfig { PageSize = PageSize.Letter };
var generator = new PdfGenerator();
// IronPDF
var renderer = new ChromePdfRenderer();
// PeachPDF
var config = new PdfGenerateConfig { PageSize = PageSize.Letter };
var generator = new PdfGenerator();
// IronPDF
var renderer = new ChromePdfRenderer();
' PeachPDF
Dim config As New PdfGenerateConfig With {.PageSize = PageSize.Letter}
Dim generator As New PdfGenerator()
' IronPDF
Dim renderer As New ChromePdfRenderer()
Async vs Sync, and Return Type
PeachPDF's GeneratePdf is async-only and returns a document whose Save method takes a Stream. IronPDF's RenderHtmlAsPdf is synchronous (an async variant RenderHtmlAsPdfAsync is also available) and returns a PdfDocument:
// PeachPDF: async, save to a Stream
var document = await generator.GeneratePdf(html, config);
using var fs = File.Create("output.pdf");
document.Save(fs);
// IronPDF: synchronous PdfDocument object
PdfDocument pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// Or get bytes: byte[] bytes = pdf.BinaryData;
// PeachPDF: async, save to a Stream
var document = await generator.GeneratePdf(html, config);
using var fs = File.Create("output.pdf");
document.Save(fs);
// IronPDF: synchronous PdfDocument object
PdfDocument pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// Or get bytes: byte[] bytes = pdf.BinaryData;
Imports System.IO
' PeachPDF: async, save to a Stream
Dim document = Await generator.GeneratePdf(html, config)
Using fs As FileStream = File.Create("output.pdf")
document.Save(fs)
End Using
' IronPDF: synchronous PdfDocument object
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
' Or get bytes: Dim bytes As Byte() = pdf.BinaryData
Header/Footer Property Change
// PeachPDF: no header/footer API -- embed in source HTML
// (e.g. via CSS position:fixed)
// IronPDF: HtmlHeaderFooter objects
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter()
{
HtmlFragment = "<div>Header</div>"
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter()
{
HtmlFragment = "<div>Footer</div>"
};
// PeachPDF: no header/footer API -- embed in source HTML
// (e.g. via CSS position:fixed)
// IronPDF: HtmlHeaderFooter objects
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter()
{
HtmlFragment = "<div>Header</div>"
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter()
{
HtmlFragment = "<div>Footer</div>"
};
' PeachPDF: no header/footer API -- embed in source HTML
' (e.g. via CSS position:fixed)
' IronPDF: HtmlHeaderFooter objects
renderer.RenderingOptions.HtmlHeader = New HtmlHeaderFooter() With {
.HtmlFragment = "<div>Header</div>"
}
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter() With {
.HtmlFragment = "<div>Footer</div>"
}
Method Name Changes
| PeachPDF | IronPDF |
|---|---|
await generator.GeneratePdf(html, config) |
renderer.RenderHtmlAsPdf(html) |
NetworkAdapter = new HttpClientNetworkAdapter(...) + GeneratePdf(null, config) |
renderer.RenderUrlAsPdf(url) |
document.Save(stream) |
pdf.SaveAs(path) |
New Capabilities After Migration
After migrating to IronPDF, you gain capabilities that PeachPDF cannot provide:
PDF Merging
var pdf1 = PdfDocument.FromFile("doc1.pdf");
var pdf2 = PdfDocument.FromFile("doc2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
var pdf1 = PdfDocument.FromFile("doc1.pdf");
var pdf2 = PdfDocument.FromFile("doc2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
CONVERTER NOT RUNNING
Watermarks with HTML
var pdf = PdfDocument.FromFile("document.pdf");
pdf.ApplyWatermark("<div style='color: red; font-size: 48pt;'>DRAFT</div>");
pdf.SaveAs("watermarked.pdf");
var pdf = PdfDocument.FromFile("document.pdf");
pdf.ApplyWatermark("<div style='color: red; font-size: 48pt;'>DRAFT</div>");
pdf.SaveAs("watermarked.pdf");
Dim pdf = PdfDocument.FromFile("document.pdf")
pdf.ApplyWatermark("<div style='color: red; font-size: 48pt;'>DRAFT</div>")
pdf.SaveAs("watermarked.pdf")
Password Protection
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>");
pdf.SecuritySettings.OwnerPassword = "owner123";
pdf.SecuritySettings.UserPassword = "user123";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint;
pdf.SaveAs("protected.pdf");
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>");
pdf.SecuritySettings.OwnerPassword = "owner123";
pdf.SecuritySettings.UserPassword = "user123";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint;
pdf.SaveAs("protected.pdf");
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>")
pdf.SecuritySettings.OwnerPassword = "owner123"
pdf.SecuritySettings.UserPassword = "user123"
pdf.SecuritySettings.AllowUserCopyPasteContent = False
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint
pdf.SaveAs("protected.pdf")
Digital Signatures
using IronPdf.Signing;
var pdf = PdfDocument.FromFile("document.pdf");
var signature = new PdfSignature("certificate.pfx", "password")
{
SigningReason = "Document Approval",
SigningLocation = "New York"
};
pdf.Sign(signature);
pdf.SaveAs("signed.pdf");
using IronPdf.Signing;
var pdf = PdfDocument.FromFile("document.pdf");
var signature = new PdfSignature("certificate.pfx", "password")
{
SigningReason = "Document Approval",
SigningLocation = "New York"
};
pdf.Sign(signature);
pdf.SaveAs("signed.pdf");
Imports IronPdf.Signing
Dim pdf = PdfDocument.FromFile("document.pdf")
Dim signature = New PdfSignature("certificate.pfx", "password") With {
.SigningReason = "Document Approval",
.SigningLocation = "New York"
}
pdf.Sign(signature)
pdf.SaveAs("signed.pdf")
Async Operations
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Async PDF</h1>");
pdf.SaveAs("async_output.pdf");
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Async PDF</h1>");
pdf.SaveAs("async_output.pdf");
Dim renderer As New ChromePdfRenderer()
Dim pdf = Await renderer.RenderHtmlAsPdfAsync("<h1>Async PDF</h1>")
pdf.SaveAs("async_output.pdf")
Feature Comparison Summary
| Feature | PeachPDF | IronPDF |
|---|---|---|
| HTML to PDF | PdfSharpCore-based layout | Full Chromium |
| URL to PDF | Via HttpClientNetworkAdapter (no JS) |
Yes |
| CSS Grid/Flexbox | Partial / not guaranteed | Yes |
| JavaScript | Not executed | Full ES2024 |
| Merge PDFs | No (HTML->PDF only) | Yes |
| Split PDFs | No | Yes |
| Watermarks | Manual via HTML | Full HTML |
| Headers/Footers | Manual via HTML/CSS | Full HTML |
| Digital Signatures | No | Yes |
| PDF/A | No | Yes |
| Form Filling | No | Yes |
| Text Extraction | No | Yes |
| Image Extraction | No | Yes |
| Async Support | Async-only API | Yes |
| Cross-Platform | net8.0 (Windows / Linux / macOS) |
Yes |
Common Migration Issues
Issue 1: Different API Pattern
Problem: PeachPDF separates PdfGenerator (engine) from PdfGenerateConfig (settings) and is async; IronPDF uses one ChromePdfRenderer that returns a PdfDocument synchronously.
Solution:
// PeachPDF pattern (async, stream-out)
var config = new PdfGenerateConfig { PageSize = PageSize.Letter };
var generator = new PdfGenerator();
var document = await generator.GeneratePdf(html, config);
using var fs = File.Create(path);
document.Save(fs);
// IronPDF pattern
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(path);
// PeachPDF pattern (async, stream-out)
var config = new PdfGenerateConfig { PageSize = PageSize.Letter };
var generator = new PdfGenerator();
var document = await generator.GeneratePdf(html, config);
using var fs = File.Create(path);
document.Save(fs);
// IronPDF pattern
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(path);
Imports System.IO
' PeachPDF pattern (async, stream-out)
Dim config As New PdfGenerateConfig With {.PageSize = PageSize.Letter}
Dim generator As New PdfGenerator()
Dim document = Await generator.GeneratePdf(html, config)
Using fs As FileStream = File.Create(path)
document.Save(fs)
End Using
' IronPDF pattern
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs(path)
Issue 2: Save Targets a Stream, Not a Path
Problem: PeachPDF's document.Save(stream) only takes a Stream; IronPDF's pdf.SaveAs(path) takes a path string.
Solution: Use pdf.SaveAs("file.pdf") directly in IronPDF instead of opening a FileStream.
Issue 3: No Existing-PDF Operations
Problem: PeachPDF is HTML-to-PDF only; it cannot load, merge, split, or edit existing PDFs.
Solution: Replace those operations with IronPDF's PdfDocument.FromFile, PdfDocument.Merge, and pdf.AppendPdf once migrated.
Migration Checklist
Pre-Migration
- Audit PeachPDF usage in codebase
- Document custom configurations
- Note all header/footer implementations
- Obtain IronPDF license key from ironpdf.com
- Test with IronPDF trial license first
Package Changes
- Remove
PeachPDFNuGet package - Install
IronPdfNuGet package:dotnet add package IronPdf
Code Changes
- Update namespace imports (
using PeachPDF;→using IronPdf;) - Add
using IronPdf.Rendering;for header/footer functionality - Replace
PdfGenerator+PdfGenerateConfigwithChromePdfRenderer - Replace
await generator.GeneratePdf(html, config)withrenderer.RenderHtmlAsPdf(html)(orRenderHtmlAsPdfAsyncto stay async) - Replace
HttpClientNetworkAdapter+GeneratePdf(null, config)withrenderer.RenderUrlAsPdf(url) - Replace
document.Save(stream)withpdf.SaveAs(path) - Replace HTML-embedded headers/footers with
RenderingOptions.HtmlHeader/HtmlFooterobjects - Add license initialization at application startup
Post-Migration
- Test HTML rendering quality
- Verify PDF output matches expectations
- Test header/footer rendering with page numbers
- Add new capabilities (security, watermarks, merging) as needed

