PDFSharp HTML to PDF: what works, what breaks, and what to use instead
PDFSharp cannot convert HTML to PDF natively; it's a PDF drawing and manipulation library, and its own FAQ says so. The common workaround, the HtmlRenderer.PdfSharp package, handles roughly CSS 2.1-era markup; after a decade dormant it was revived in late 2025 (v1.6.0, July 2026, now targets .NET 8), but the revival modernized the packaging, not the rendering ceiling. For modern HTML, render with PuppeteerSharp or an HTML to PDF API, then use PDFSharp for what it's genuinely great at: manipulating the finished file.
That's the answer most tutorials bury. They show HtmlRenderer.PdfSharp converting a heading and a paragraph, call it done, and leave you to discover on your own template that flexbox collapses, grid doesn't exist, and your webfont never loads. Meanwhile the commercial-library vendors run the same search result in the other direction, spinning the limitation into a hard sell.
This guide does both halves honestly: the workaround with its real boundary marked, and the two routes that handle 2026 HTML, including a pattern where PDFSharp stays in your stack doing the part it's best at.
Key TakeawaysPDFSharp has no HTML support: the official FAQ confirms there's no HTML-to-PDF converter in PDFsharp or MigraDoc.The HtmlRenderer.PdfSharp workaround is stuck in the CSS 2.1 era: dormant for a decade, revived in late 2025 (v1.6.0 shipped July 2026 for .NET 8), but its rendering still targets HTML 4.01 and CSS level 2: no flexbox, no grid, no JavaScript, unreliable webfonts.It still works for simple markup: tables, inline styles, and basic formatting convert fine, fast, and with zero native dependencies.For modern HTML in .NET: PuppeteerSharp (self-hosted headless Chrome) or an HTML to PDF API (one HttpClient call).The combo pattern is underrated: render with a Chrome engine, then merge, stamp, or encrypt the result with PDFSharp. The two tools compose.
Can PDFSharp convert HTML to PDF?
No, not natively. PDFSharp draws PDFs from code (text, shapes, images at coordinates) and manipulates existing files; it has no HTML or CSS parser. Converting HTML requires pairing it with a renderer: historically the HtmlRenderer.PdfSharp package for simple markup, or a real browser engine (PuppeteerSharp, or a rendering API) for anything styled like the modern web.
Knowing that up front reframes the whole search: the question isn't "how do I make PDFSharp do this" but "which renderer do I put in front of it, if any."
The HtmlRenderer.PdfSharp recipe
For completeness, and because it genuinely suits simple documents, here's the standard workaround:
// dotnet add package PdfSharp
// dotnet add package HtmlRenderer.PdfSharp
using PdfSharp.Pdf;
using TheArtOfDev.HtmlRenderer.PdfSharp;
var html = """
<h1>Invoice #1042</h1>
<table style="width:100%; border-collapse:collapse">
<tr><td>Rendering service</td><td style="text-align:right">$1,280.00</td></tr>
</table>
""";
PdfDocument pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.A4);
pdf.Save("invoice.pdf");
Four lines of real code, no browser, no native binaries, milliseconds to run. For markup like the above (headings, tables, inline styles), it's perfectly serviceable.
Where it breaks
HtmlRenderer.PdfSharp sat dormant for roughly a decade before its author revived it in late 2025; the current 1.6.0 (July 2026) modernizes the target frameworks, but the package still describes its own support as HTML 4.01 and CSS level 2, a landscape that predates the modern layout era. Concretely:
- Flexbox and grid: not implemented. Layouts silently collapse into stacked blocks; nothing errors.
- JavaScript: never executed. Client-rendered content simply isn't there.
- Webfonts:
@font-faceloading is unreliable; expect system-font fallbacks. - Modern CSS generally: custom properties,
calc(), transforms: outside its era.
The failure mode is the dangerous kind: silent. The PDF generates successfully and looks wrong. If your templates come from a designer or share CSS with your web app, this route will eventually ship a broken document without telling you.
What PDFSharp is actually good at
None of this makes PDFSharp a bad library; it makes it a mis-searched one. Where it shines:
- Drawing programmatic PDFs: coordinates, fonts, shapes, precise control (with MigraDoc on top for document flow).
- Manipulation: merging files, splitting pages, rotating, extracting.
- Post-processing: stamping watermarks, filling metadata, encrypting, setting permissions.
Keep it for those jobs. The current 6.x line is actively maintained (a 7.0 preview is already on NuGet), MIT-licensed, and dependency-light. The trick is not asking it to be a browser.
Route 1: PuppeteerSharp for real Chrome rendering
PuppeteerSharp (v25 as of July 2026, tracking Puppeteer's versioning) drives headless Chromium from .NET:
// dotnet add package PuppeteerSharp
using PuppeteerSharp;
await new BrowserFetcher().DownloadAsync();
await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
await using var page = await browser.NewPageAsync();
await page.SetContentAsync(html, new NavigationOptions
{ WaitUntil = new[] { WaitUntilNavigation.Networkidle0 } });
await page.PdfAsync("invoice.pdf", new PdfOptions { Format = PuppeteerSharp.Media.PaperFormat.A4, PrintBackground = true });
Fidelity is total: it's Chrome. The cost is operational: a ~170 MB browser download, memory-hungry processes to pool and recycle in production, and container images that need Chromium's native dependencies. Our PuppeteerSharp guide covers the production side properly.
Route 2: an HTML to PDF API from C
When you'd rather not operate a browser, the render becomes one HttpClient call:
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new("Bearer", Environment.GetEnvironmentVariable("TRANSFORMY_API_KEY"));
var response = await client.PostAsJsonAsync("https://api.transformy.io/v1/pdf/chrome", new
{
html,
page_size = "A4",
margin = "20mm 15mm",
footer = new { html = "<span style=\"font-size:9px\">Page {{page}} of {{pages}}</span>" }
});
response.EnsureSuccessStatusCode();
await File.WriteAllBytesAsync("invoice.pdf",
await response.Content.ReadAsByteArrayAsync());
Rendering runs on real headless Chromium server-side, so the fidelity matches Route 1 without the Chromium in your deployment; page numbers and repeating headers come from the footer/header parameters, and the HTML to PDF API docs list the rest (URL mode, async jobs, delivery straight to your own storage).
The combo pattern: Chrome renders, PDFSharp finishes
Here's the framing that resolves the whole search: these tools compose. Render the styled document with a Chrome engine (either route above), then hand the bytes to PDFSharp for the parts it owns:
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
var rendered = PdfReader.Open("invoice.pdf", PdfDocumentOpenMode.Modify);
var terms = PdfReader.Open("terms.pdf", PdfDocumentOpenMode.Import);
foreach (var page in terms.Pages) rendered.AddPage(page);
rendered.SecuritySettings.UserPassword = "customer-password";
rendered.Save("invoice-final.pdf");
Browser-grade rendering plus merge-and-encrypt post-processing: each library doing the job it was built for. This is the architecture the "PDFSharp HTML to PDF" search usually wants and never gets shown.
FAQ
Does PDFSharp support HTML to PDF natively?
No. PDFSharp's own FAQ states there is no HTML-to-PDF converter in PDFsharp or MigraDoc. HTML conversion always involves a second component: the dated HtmlRenderer package for simple markup, or a Chrome-based renderer for modern pages.
Is HtmlRenderer.PdfSharp still maintained?
Yes, again: after roughly a ten-year gap, its author resumed releases in late 2025, and v1.6.0 (July 2026) targets .NET 8. The rendering engine's scope is unchanged though: the package itself advertises HTML 4.01 and CSS level 2 support, so the modern-layout limitations stand.
PDFSharp vs iTextSharp for HTML: which is better?
Different tradeoffs, same category. iText has an official HTML module (pdfHTML) with broader CSS support than HtmlRenderer, but its free edition is AGPL-licensed, which most commercial teams can't ship; see our iTextSharp guide. Neither renders like a browser; for that, use PuppeteerSharp or a rendering API.
What's the best way to convert HTML to PDF in C#?
For modern HTML: PuppeteerSharp if you'll operate headless Chrome yourself, or an HTML to PDF API for one HttpClient call and no browser in your stack. Our C# HTML-to-PDF guide compares the full landscape.
Conclusion
The honest routing for "PDFSharp HTML to PDF":
- Simple, table-based markup you control → the HtmlRenderer recipe works; know its silent-failure boundary.
- Modern HTML, self-hosted → PuppeteerSharp.
- Modern HTML, no browser ops → a rendering API, one HttpClient call.
- Merging, stamping, encrypting → PDFSharp, always: on whichever PDF the render produced.
If the API route fits, Transformy's HTML to PDF API renders on real headless Chrome with a free tier of 100 documents a month and unlimited watermarked test renders: enough to run your actual invoice template through the combo pattern today, no credit card involved.