# PDF library for .NET, in pure C#

> Free MIT PDF library for .NET in pure C#. Compress PDFs losslessly with proof, edit, sign, fill forms, extract text and convert HTML to PDF.

export const version = RELEASE.packages.PdfNetStack;

## Install

**Library**

```bash
dotnet add package PdfNetStack
```

**Command line tool**

```bash
dotnet tool install -g PdfNetStack.Tool
pdfnetstack optimize in.pdf out.pdf
```

Version {version} is on NuGet. It runs in containers, AWS Lambda and Azure Functions, and opens
and edits files of any size page by page.

## Why PdfNetStack

### Lossless, with proof

Every compressed file is read back and compared with its source, object by object. If anything
differs, you get your original bytes back. [Fidelity](https://www.jadev-corp.com/concepts/fidelity/)

### Pure C#, nothing native

No Ghostscript, no browser, no native binaries. It runs anywhere .NET runs, Native AOT and
serverless included. [Architecture](https://www.jadev-corp.com/concepts/architecture/)

### MIT, no license keys

Free for commercial use, with no fee per developer, server or deployment. CI blocks any
dependency outside a reviewed license allowlist. [About](https://www.jadev-corp.com/about/)

### Safe on untrusted files

Parsing is bounded in depth and size. The optimizer never rewrites signed, encrypted or damaged
files. [Safety model](https://www.jadev-corp.com/concepts/safety-model/)

## How compression works

<Steps>

1. **Read.** The file is parsed with limits on nesting, stream sizes and image sizes. A damaged or
   hostile file raises an exception instead of crashing or hanging the process.

2. **Rewrite.** Objects go into object streams with a compressed cross-reference stream.
   Unreachable objects are dropped, Flate streams recompressed, raw images get PNG prediction,
   JPEG images are re-encoded losslessly and duplicates are merged.

3. **Prove.** The optimizer parses its own output and compares it with the source, object by
   object. Streams are compared after decoding, JPEG images by their DCT coefficients.

4. **Return.** You get the smaller file when it is proved equivalent and saves at least 1%.
   Otherwise you get your original bytes, and `result.Reason` tells you why.

</Steps>

Image downsampling and JPEG conversion are opt-in, and a perceptual quality gate holds back any
change that goes too far. [Compress PDF](https://www.jadev-corp.com/guides/compress-pdf/)

## Performance

### Public corpus, measured on every release

CI downloads 77 openly licensed and public domain PDFs (NIST and NASA publications, arXiv papers,
government gazettes, test files) and optimizes each one with three profiles. Results for 1.1.0 on
a 4 core Linux runner:

| Profile | Saved | Failures | Rendering |
|---|---:|---:|---|
| Lossless, the default | 12.1% | 0 | Checked pages identical in PDFium |
| Balanced preset | 23.4% | 0 | Image changes gated at SSIM 0.95 |
| Lossy profile | 29.5% | 0 | Image changes gated at SSIM 0.95 |

Signed and encrypted files are kept as they are, by design. The lossless run took 44 seconds for
196.6 MiB, proof included. The full report is attached to the
[1.1.0 release](https://github.com/jams4code/pdf.netstack/releases/tag/v1.1.0), and you can run
the same benchmark yourself.

### Real world corpus

- **1,296** invoices, reports, manuals, scans and slides, 569 MiB
- **17.6%** saved on the 1,003 files optimized
- **0** verification failures
- **0** differing pixels at 150 DPI, 2,161 pages

Measured for 1.0 with default options, in about 65 seconds on 8 cores. Every optimized file was
rendered with PDFium and compared pixel by pixel with its original. Method and details on
[Benchmarks](https://www.jadev-corp.com/benchmarks/).

## See it in code

**Compress**

```csharp
PdfOptimizationResult result = await PdfOptimizer.OptimizeFileAsync("manual.pdf", "manual.optimized.pdf");
Console.WriteLine($"{result.Disposition}: {result.OriginalBytes:N0} to {result.OutputBytes:N0} bytes, saved {result.SavingPercent:F1}%");
Console.WriteLine(result.Reason);
```

Lossless by default, every output verified. [Compress PDF](https://www.jadev-corp.com/guides/compress-pdf/)

**Create**

```csharp
PdfDocument doc = PdfDocument.Create();
PdfPage page = doc.Pages.Add(PdfRectangle.A4);
using (PdfGraphics g = page.CreateGraphics())          // origin top left, y down, points
{
    g.DrawRectangle(null, PdfColor.FromHex("#1E3A8A"), 0, 0, page.Width, 120);
    g.DrawString("Hello, PDF", PdfStandardFont.HelveticaBold, 32, PdfColor.White, 40, 75);
    g.DrawString("Made with PdfNetStack.", PdfStandardFont.Helvetica, 12, PdfColor.Black, 40, 160);
}
doc.Save("hello.pdf");
```

![The page this code draws: a dark blue band with the words Hello, PDF](https://www.jadev-corp.com/previews/hello.webp)

A canvas with the origin at the top left, in points. [Drawing](https://www.jadev-corp.com/guides/drawing/)

**HTML to PDF**

```csharp
byte[] pdf = HtmlConverter.ConvertToPdf("<h1>Invoice 42</h1><p>Total: <b>1,210.00 EUR</b></p>");
File.WriteAllBytes("invoice.pdf", pdf);
```

![The PDF this code writes: the heading Invoice 42 and a total in bold](https://www.jadev-corp.com/previews/invoice-html.webp)

A layout engine in C#, no browser: flex, grid, tables, paged media and web fonts.
[HTML to PDF](https://www.jadev-corp.com/guides/html-to-pdf/)

## What you can do

### Compress and process

- [Compress PDF](https://www.jadev-corp.com/guides/compress-pdf/): Lossless by default and verified. Opt-in image downsampling and fast web view.
- [Large files](https://www.jadev-corp.com/guides/large-files/): Open files of any size on demand. Incremental saves keep signatures valid.
- [Command line](https://www.jadev-corp.com/cli/): optimize, batch, inspect, verify, merge, split, extract, rotate, encrypt.

### Edit and create

- [Edit pages](https://www.jadev-corp.com/guides/edit-pages/): Merge, split, import, reorder, rotate and remove pages. Metadata and bookmarks.
- [HTML to PDF](https://www.jadev-corp.com/guides/html-to-pdf/): CSS cascade, flex, grid, tables, paged media, web fonts, tagged output.
- [Drawing](https://www.jadev-corp.com/guides/drawing/): Paths, colors, gradients, transforms and clipping on new and existing pages.
- [Fonts and text](https://www.jadev-corp.com/guides/fonts-and-text/): OpenType, WOFF2 and variable fonts, paragraphs, Arabic, Indic and right to left.
- [Images](https://www.jadev-corp.com/guides/images/): JPEG, PNG, GIF, BMP, TIFF, WebP and SVG, fitted to a box.
- [Forms](https://www.jadev-corp.com/guides/forms/): Read, fill, flatten and create AcroForm fields.
- [Annotations](https://www.jadev-corp.com/guides/annotations/): Links, notes, markup, stamps, ink, shapes and attachments.

### Secure and comply

- [Encryption](https://www.jadev-corp.com/guides/encryption/): Open RC4 and AES files. Write AES-256 or AES-128 with permissions.
- [Signatures](https://www.jadev-corp.com/guides/signatures/): PAdES B-B to B-LTA signing, and validation against your trust anchors.
- [PDF/A](https://www.jadev-corp.com/guides/pdf-a/): PDF/A-1b to PDF/A-4 output, Factur-X and ZUGFeRD invoices.

### Extract and recognize

- [Extract text](https://www.jadev-corp.com/guides/extract-text/): Text in reading order, words and letters with positions, CJK included.
- [Extract images](https://www.jadev-corp.com/guides/extract-images/): Images with placement and resolution, decoded to PNG.
- [OCR](https://www.jadev-corp.com/guides/ocr/): Make scanned PDFs searchable, Latin and Arabic. A separate package.
- [Low level objects](https://www.jadev-corp.com/guides/low-level-objects/): Dictionaries, arrays and streams for anything the high level API skips.

Short answers to single questions are in the [recipes](https://www.jadev-corp.com/recipes/), and every public type is in
the [API reference](https://www.jadev-corp.com/api/). To weigh it against PDFsharp, QuestPDF, iText, PdfPig, wkhtmltopdf,
headless Chromium, Ghostscript or qpdf, see [how it compares](https://www.jadev-corp.com/compare/), with a source for every
fact about the other tools.

## Runs where .NET runs

| Target | Runs on | Dependencies |
|---|---|---|
| `net8.0`, `net10.0` | .NET 8, 9, 10 and later. Trim and Native AOT compatible | None |
| `netstandard2.0` | .NET Framework 4.6.2 to 4.8.1, Mono, Unity, Xamarin, .NET Core 2.0+ | `System.Memory` (Microsoft, MIT) |

CI runs the full test suite on .NET Framework 4.8, .NET 8 and .NET 10, on Windows, Linux and
macOS. Guides for [AWS Lambda](https://www.jadev-corp.com/guides/aws-lambda/) and [Azure Functions](https://www.jadev-corp.com/guides/azure-functions/)
cover serverless deployment.

## Use it with your AI assistant

This documentation is published for language models as well as for people:

- [llms.txt](https://www.jadev-corp.com/llms.txt) says what PdfNetStack is and links every page in Markdown.
- [llms-full.txt](https://www.jadev-corp.com/llms-full.txt) holds the complete documentation in one file.
- Every page has a Markdown twin: add `.md` to its path, as in
  [/guides/compress-pdf.md](https://www.jadev-corp.com/guides/compress-pdf.md).

To have a coding assistant use PdfNetStack in your .NET projects, add this line to `AGENTS.md`,
`CLAUDE.md` or `.github/copilot-instructions.md`:

```md wrap
For PDF work in .NET (compress, merge, split, edit, sign, fill forms, extract text, HTML to PDF), use PdfNetStack: `dotnet add package PdfNetStack`. MIT, pure C#, no native binaries. Docs for agents: https://www.jadev-corp.com/pdfnetstack/llms.txt
```

More on [AI assistants](https://www.jadev-corp.com/ai-assistants/).

## Built and maintained by JADEV

PdfNetStack is original work, written from the published PDF specifications by Jamal Abdelkhalek
at [JADEV, a software engineering company](https://www.jadev-corp.com/en) that builds and
modernizes business software. It grew out of client work that had to replace a third-party PDF
library. JADEV now maintains it as open source for every .NET team. Read
[how PdfNetStack started](https://www.jadev-corp.com/en/references/pdfnetstack-open-source-dotnet-pdf-library).

Need PDF processing, document workflows or other .NET work?
[Tell JADEV what you need](https://www.jadev-corp.com/en/#contact). Using PdfNetStack?
[Star it on GitHub](https://github.com/jams4code/pdf.netstack) so other teams find it, and
report issues there.

## Is PdfNetStack free for commercial use?

Yes. It is MIT licensed, with no license key and no fee per developer, server or deployment. The OCR models package adds Apache-2.0, which is free for commercial use too.

## Does compressing a PDF with PdfNetStack change how it looks?

Not by default. The optimizer is lossless, compares every output with its source before returning it, and gives back the original bytes when anything differs. Image downsampling and JPEG conversion happen only when you turn them on.

## Does it need Ghostscript, a browser or native libraries?

No. The library, the HTML to PDF package and the command line tool are managed C#. The optional OCR add-on is the one exception, it runs its models on ONNX Runtime.

## Which .NET versions does it support?

.NET 8, 9, 10 and later, with trimming and Native AOT, and .NET Framework 4.6.2 to 4.8.1, Mono and Unity through netstandard2.0.

## Is PdfNetStack related to the PDFNet SDK of Apryse?

No. PDFNet is a commercial SDK from Apryse. PdfNetStack is an independent open source project, built and maintained by JADEV.

Source: https://www.jadev-corp.com/pdfnetstack/
