PDFsharp
| Language | C# (.NET 8+, .NET Standard 2.0, .NET Framework 4.6.2+) |
|---|---|
| License | AGPL-3.0 or commercial since 6.5.0; versions up to 6.2.4 are MIT |
| Repository | github.com/empira/PDFsharp |
| Documentation | docs.pdfsharp.net |
| Depends on | nothing for the Core build; GDI+ or WPF for the PDFsharp-gdi and PDFsharp-wpf builds |
| Read / write | yes / yes: create, import pages, merge, split, rotate, metadata, encryption, AcroForms; no text extraction or rendering |
PDFsharp creates PDF documents with XGraphics, a drawing API modeled on GDI+ (strings, lines, shapes, images, transformations), and opens existing PDFs to modify them: import pages from other files, change page rotation and metadata, add content on top of existing pages, and encrypt with RC4 or AES-256. Version 6 is fully managed and cross-platform. MigraDoc, in the same repository, adds a document model with paragraphs, tables and automatic page breaks on top of PDFsharp.
License change: PDFsharp 6.5.0 moved from MIT to a dual AGPL-3.0 / commercial license, and your code must select the license at startup (PdfSharpLicense.SetAgplLicense() or PdfSharpLicense.LoadLicense(key)); otherwise PDFsharp throws a PdfSharpLicenseException. If you need a permissive license, stay on 6.2.4 (MIT), which has the same API as the examples below minus the license call.
PDFsharp can’t extract text or render pages. In the cross-platform Core build, fonts aren’t found automatically: on Windows set GlobalFontSettings.UseWindowsFontsUnderWindows = true, elsewhere implement an IFontResolver that returns font files.
Installation#
dotnet add package PDFsharp
# last MIT-licensed version
dotnet add package PDFsharp --version 6.2.4
# with MigraDoc for documents with paragraphs and tables
dotnet add package PDFsharp-MigraDoc
Basic usage: create a PDF with text#
using PdfSharp;
using PdfSharp.Drawing;
using PdfSharp.Fonts;
using PdfSharp.Pdf;
PdfSharpLicense.SetAgplLicense(); // 6.5+: or PdfSharpLicense.LoadLicense(key) for a commercial license
// Core build: tell PDFsharp where fonts are (Windows only; use an IFontResolver elsewhere)
GlobalFontSettings.UseWindowsFontsUnderWindows = true;
var document = new PdfDocument();
document.Info.Title = "Hello";
PdfPage page = document.AddPage(); // A4 by default
XGraphics gfx = XGraphics.FromPdfPage(page);
var font = new XFont("Arial", 24, XFontStyleEx.Bold);
gfx.DrawString("Hello, PDF!", font, XBrushes.Black,
new XRect(0, 0, page.Width.Point, page.Height.Point), XStringFormats.Center);
gfx.DrawLine(XPens.DarkBlue, 72, 100, 300, 100); // origin is top-left, units are points
document.Save("hello.pdf");
How to merge PDF files#
Open the sources in Import mode and add their pages to a new document:
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
using var output = new PdfDocument();
foreach (string path in new[] { "a.pdf", "b.pdf" })
{
using PdfDocument input = PdfReader.Open(path, PdfDocumentOpenMode.Import);
foreach (PdfPage page in input.Pages)
output.AddPage(page);
}
output.Save("merged.pdf");
How to split a PDF into pages#
using PdfDocument input = PdfReader.Open("in.pdf", PdfDocumentOpenMode.Import);
for (int i = 0; i < input.PageCount; i++)
{
using var single = new PdfDocument();
single.AddPage(input.Pages[i]);
single.Save($"page-{i + 1}.pdf");
}
How to rotate pages#
using PdfDocument doc = PdfReader.Open("in.pdf", PdfDocumentOpenMode.Modify);
foreach (PdfPage page in doc.Pages)
page.Rotate = (page.Rotate + 90) % 360;
doc.Save("rotated.pdf");
How to read PDF metadata#
using PdfDocument doc = PdfReader.Open("in.pdf", PdfDocumentOpenMode.Import);
Console.WriteLine($"Pages: {doc.PageCount}, PDF {doc.Version / 10.0:F1}");
Console.WriteLine($"Title: {doc.Info.Title}");
Console.WriteLine($"Author: {doc.Info.Author}");
Console.WriteLine($"Producer: {doc.Info.Producer}");
Console.WriteLine($"Created: {doc.Info.CreationDate}");
How to encrypt and decrypt a PDF#
using PdfDocument doc = PdfReader.Open("in.pdf", PdfDocumentOpenMode.Modify);
doc.SecuritySettings.UserPassword = "user";
doc.SecuritySettings.OwnerPassword = "owner";
doc.SecuritySettings.PermitModifyDocument = false;
doc.SecurityHandler.SetEncryptionToV5(); // AES-256
doc.Save("encrypted.pdf");
// decrypt: open with the owner password and save without passwords
using PdfDocument secret = PdfReader.Open("encrypted.pdf", "owner", PdfDocumentOpenMode.Modify);
secret.SecurityHandler.SetEncryptionToNoneAndResetPasswords();
secret.Save("decrypted.pdf");
Tips#
- To draw on an existing page (watermarks, stamps), open the file in
Modifymode and callXGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Append). - Call
PdfSharpLicense.SetAgplLicense()once at program start in every 6.5+ program, including the snippets above. - PDFsharp 6 can import pages from PDFs with object streams and xref streams; older 1.x versions couldn’t.
- For automatic layout (paragraphs, tables, page breaks), use MigraDoc or QuestPDF instead of positioning every line.