How to Compress PDFs in C# using IronPDF
IronPDF compresses PDFs in C# through the CompressAndSaveAs method, which re-encodes embedded images as JPEG and optionally strips the PDF structure tree to cut file size in a single call. The companion CompressPdfToBytes and CompressPdfToStream methods do the same work in memory when you never want to touch disk.
Images usually account for most of a PDF's size, and table-heavy documents carry a structure tree that adds further weight. IronPDF targets both, so the same call works on PDFs loaded from disk or held in a memory stream.
Quickstart: Compress PDF Files with IronPDF
Load your PDF with PdfDocument.FromFile and call CompressAndSaveAs to re-encode its images and write the slimmed-down copy in one step. The second argument is the JPEG quality.
-
Install IronPDF with NuGet Package Manager
-
Copy and run this code snippet.
PdfDocument.FromFile("input.pdf").CompressAndSaveAs("compressed.pdf", 40); -
Deploy to test on your live environment
Start using IronPDF in your project today with a free trial
Minimal Workflow (3 steps)
- Download the C# library for PDF compression from NuGet
- Import an existing PDF or render a new PDF
- Call
CompressAndSaveAs(outputPath, quality, removeStructureTree)to compress images, optionally strip the structure tree, and save the result
CompressImages, CompressStructTree, and Compress(CompressionOptions) are deprecated.How Do I Compress Images in PDFs?
Pass a JPEG quality value as the second argument to CompressAndSaveAs and IronPDF re-encodes every embedded image at that quality. Values run from 0 (maximum compression) to 100 (minimal loss), and the underlying engine decides how each value maps to the output. This is the method to reach for whenever a document carries embedded images.
As a rough guide:
- 90 and above: high quality
- 80 to 90: medium quality
- 70 to 80: low quality
A lower number squeezes harder but can introduce visible artifacts, and how much clarity drops depends on the source image, so test a few settings against your own content to find the balance you want.
Input
:path=/static-assets/pdf/content-code-examples/how-to/pdf-compression-image.cs
using IronPdf;
ChromePdfRenderer renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderUrlAsPdf("https://en.wikipedia.org/wiki/Main_Page");
// Compress images in the PDF
pdf.CompressAndSaveAs("compressed.pdf", 40);
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
Dim pdf As PdfDocument = renderer.RenderUrlAsPdf("https://en.wikipedia.org/wiki/Main_Page")
' Compress images in the PDF
pdf.CompressAndSaveAs("compressed.pdf", 40)
Output
What Results Can I Expect from Image Compression?
Reduced by 39.24% on a Wikipedia render.
How Do I Compress PDF Tree Structure?
Pass removeStructureTree: true as the third argument to CompressAndSaveAs to strip the tree structure the Chrome Engine writes into a PDF. The saving is largest on Chrome Engine PDFs that hold extensive table data. Some rendering engines emit no such structure, which leaves nothing for the feature to remove.
Stripping the tree can weaken text highlighting and selection, so weigh that against the size gain if readers later need to extract text and images from the result.
Test CompressAndSaveAs with tree structure removal using this PDF with table data.
:path=/static-assets/pdf/content-code-examples/how-to/pdf-compression-tree-structure.cs
using IronPdf;
PdfDocument pdf = PdfDocument.FromFile("table.pdf");
// Compress tree structure in PDF
pdf.CompressAndSaveAs("compressedTable.pdf", null, true);
Imports IronPdf
Dim pdf As PdfDocument = PdfDocument.FromFile("table.pdf")
' Compress tree structure in PDF
pdf.CompressAndSaveAs("compressedTable.pdf", Nothing, True)
What File Size Reduction Can Tree Structure Compression Achieve?
Reduced by 67.90%. The figure climbs as the table PDF grows.
How Can I Apply Both Compression Methods Together?
Supply a quality value and set removeStructureTree to true in the same CompressAndSaveAs call to shrink both sources of bloat at once. This pairing earns its keep on documents that mix images with structured data, such as reports with charts or invoices with embedded tables.
:path=/static-assets/pdf/content-code-examples/how-to/pdf-compression-compress.cs
using IronPdf;
PdfDocument pdf = PdfDocument.FromFile("sample.pdf");
// Configure compression with automatic optimization
pdf.CompressAndSaveAs("compressed.pdf", 80, true);
Imports IronPdf
Dim pdf As PdfDocument = PdfDocument.FromFile("sample.pdf")
' Configure compression with automatic optimization
pdf.CompressAndSaveAs("compressed.pdf", 80, True)
What Parameters Does CompressAndSaveAs Accept?
outputPath(string): the file path where the compressed PDF is written.quality(int?, 0 to 100): JPEG quality applied to every embedded image. Lower values produce smaller files. Passnullto skip image compression entirely.removeStructureTree(bool, defaultfalse): whentrue, strips the PDF structure tree to reduce file size further. Most effective for HTML-generated PDFs with tables.
Let the use case set the dial. Archival copies often favor quality over size, while web distribution rewards the smaller file. The same trade-off applies when you compress PDF/A compliant documents, where image fidelity may be the priority.
The IronSuite play a crucial role in our operations. These are tools that increase efficiencies across the business including creating floor plans and improving inventory management.
How Do I Get Fine-Grained Control Over Compression?
For most documents the two-argument call is enough, but image-heavy archives and strict size budgets sometimes need more control. Pass an AdvancedCompressionOptions object to CompressAndSaveAs to tune the compression pipeline, including image DPI downsampling, JPEG re-encoding quality, and the zlib compression level. The simpler CompressAndSaveAs(outputPath, quality, removeStructureTree) overload still works unchanged and produces the same output as before.
:path=/static-assets/pdf/content-code-examples/how-to/pdf-compression-advanced.cs
using IronPdf;
PdfDocument pdf = PdfDocument.FromFile("input.pdf");
// Web or email: strong size reduction
pdf.CompressAndSaveAs("compressed.pdf", new AdvancedCompressionOptions
{
JpegQuality = 70,
TargetImageDpi = 150,
RemoveStructureTree = true
});
// Print quality: minimal quality loss
pdf.CompressAndSaveAs("print.pdf", new AdvancedCompressionOptions
{
JpegQuality = 90,
TargetImageDpi = 300
});
Imports IronPdf
Dim pdf As PdfDocument = PdfDocument.FromFile("input.pdf")
' Web or email: strong size reduction
pdf.CompressAndSaveAs("compressed.pdf", New AdvancedCompressionOptions With {
.JpegQuality = 70,
.TargetImageDpi = 150,
.RemoveStructureTree = True
})
' Print quality: minimal quality loss
pdf.CompressAndSaveAs("print.pdf", New AdvancedCompressionOptions With {
.JpegQuality = 90,
.TargetImageDpi = 300
})
The two properties that move the needle most are JpegQuality and TargetImageDpi:
JpegQuality(int?, 1 to 100, defaultnull): re-encodes images at this JPEG quality. Leave itnullto skip image re-encoding entirely.TargetImageDpi(int?, default150): downsamples images whose effective DPI exceeds this value before re-encoding. Set it tonullor0to disable downsampling and keep the original resolution.
Recommended JpegQuality values (applies only when set):
| Value | Use case |
|---|---|
null (default) |
No image re-encoding |
95 |
Archival, minimal artifacts |
85 |
High quality |
70 |
Balanced, good for general use |
50 |
Web or email, smaller files with visible artifacts |
Recommended TargetImageDpi values (lossy):
| Value | Use case |
|---|---|
300 |
Print quality, lossless to the eye at normal viewing distance |
200 |
Crisp on high-DPI and retina screens |
150 (default) |
Best size and quality balance for screen and email |
96 |
Aggressive, soft text but still readable |
null or 0 |
Disabled, preserves the original resolution |
TargetImageDpi downsampling is lossy: once an image is downsampled, its original resolution cannot be restored. Decide up front whether you want resolution reduction or quality-only re-encoding, and set TargetImageDpi accordingly.How Do I Compress PDFs Without Saving to Disk?
API responses, cloud functions, and email attachments rarely need a compressed PDF on disk. CompressPdfToBytes returns the result as a byte array, so you decide where the bytes go next.
:path=/static-assets/pdf/content-code-examples/how-to/pdf-compression-to-bytes.cs
using IronPdf;
PdfDocument pdf = PdfDocument.FromFile("sample.pdf");
// Compress and return as byte array
byte[] compressedBytes = pdf.CompressPdfToBytes();
File.WriteAllBytes("compressed.pdf", compressedBytes);
Imports IronPdf
Dim pdf As PdfDocument = PdfDocument.FromFile("sample.pdf")
' Compress and return as byte array
Dim compressedBytes As Byte() = pdf.CompressPdfToBytes()
File.WriteAllBytes("compressed.pdf", compressedBytes)
If you need a Stream rather than a byte array, call CompressPdfToStream and copy it to your destination. This suits piping output to an HTTP response body, a cloud storage upload, or any stream-based workflow.
:path=/static-assets/pdf/content-code-examples/how-to/pdf-compression-to-stream.cs
using IronPdf;
PdfDocument pdf = PdfDocument.FromFile("sample.pdf");
// Compress and return as Stream
using var compressedStream = pdf.CompressPdfToStream();
using var fileStream = File.Create("compressed.pdf");
compressedStream.CopyTo(fileStream);
Imports IronPdf
Dim pdf As PdfDocument = PdfDocument.FromFile("sample.pdf")
' Compress and return as Stream
Using compressedStream = pdf.CompressPdfToStream()
Using fileStream = File.Create("compressed.pdf")
compressedStream.CopyTo(fileStream)
End Using
End Using
What CompressionMode Options Are Available?
Both CompressPdfToBytes and CompressPdfToStream take an optional CompressionMode argument that decides how the work is done. Deployment targets differ in whether they allow disk access, and the mode lets you pick the right trade-off:
| Mode | Disk access | Image resampling | Output size |
|---|---|---|---|
Automatic (default) |
Tries disk, falls back to memory | When disk is available | Smallest where permitted |
FastMemory |
None | No | Larger |
HighQuality |
Temp directory required | Yes | Smallest |
Automatic attempts HighQuality first and drops to FastMemory when the temporary directory is off limits. The example below forces HighQuality for the smallest output, which needs write access to the system temp directory at runtime.
:path=/static-assets/pdf/content-code-examples/how-to/pdf-compression-mode.cs
using IronPdf;
PdfDocument pdf = PdfDocument.FromFile("sample.pdf");
// HighQuality resamples images using the system temp directory, so it produces
// the smallest output but needs write access to that directory at runtime
byte[] compressedBytes = pdf.CompressPdfToBytes(50, false, CompressionMode.HighQuality);
File.WriteAllBytes("compressed.pdf", compressedBytes);
Imports IronPdf
Dim pdf As PdfDocument = PdfDocument.FromFile("sample.pdf")
' HighQuality resamples images using the system temp directory, so it produces
' the smallest output but needs write access to that directory at runtime
Dim compressedBytes As Byte() = pdf.CompressPdfToBytes(50, False, CompressionMode.HighQuality)
File.WriteAllBytes("compressed.pdf", compressedBytes)
Output
CompressPdfToBytes and CompressPdfToStream are now available across all IronPDF platforms, including Java, Node.js, and Python.Conclusion
You now have one method, CompressAndSaveAs, that re-encodes images and strips the structure tree, plus CompressPdfToBytes and CompressPdfToStream for the same job in memory under a chosen CompressionMode. A natural next step is turning those slimmed-down pages into thumbnails with PDF rasterization.
Frequently Asked Questions
How much can PDF file size be reduced with compression?
Results vary by content. In the examples shown, image compression reduced a file by 39.24% and structure tree removal reduced a table-heavy PDF by 67.90%. Image-heavy and table-heavy documents see the largest savings.
How does IronPDF compress PDFs in C#?
IronPDF handles compression through a single method — CompressAndSaveAs. It reduces embedded image sizes using a configurable JPEG quality (0–100) and can optionally strip the PDF's internal structure tree by setting removeStructureTree: true, which is especially effective for table-heavy documents.
What quality levels should I use for JPEG compression in PDFs?
IronPDF supports JPEG compression quality from 1% to 100%. Recommended levels are: 90% and above for high quality, 80%-90% for medium quality, and 70%-80% for low quality. The optimal setting depends on your balance between file size and visual quality requirements.
Can I compress a PDF in just one line of code?
Yes, IronPDF allows PDF compression in a single line of code: PdfDocument.FromFile("input.pdf").CompressAndSaveAs("compressed.pdf", 40); This loads a PDF, compresses images at 40% quality, and saves the result.
Does compression work with PDFs created from HTML?
Yes, IronPDF's compression works with PDFs created through various methods including HTML string to PDF conversions, URL to PDF conversions, and HTML file conversions, as well as existing PDF files.
What types of content benefit most from PDF compression?
Images typically consume the majority of PDF file sizes, making image-heavy documents ideal candidates for compression. Additionally, PDFs with complex table structures benefit from IronPDF's structure tree compression feature.
Can I compress a PDF without saving it to disk?
Yes, IronPDF provides CompressPdfToBytes and CompressPdfToStream methods that return the compressed PDF as a byte array or Stream respectively. Both accept an optional CompressionMode parameter with options for Automatic, FastMemory, or HighQuality compression.
Is PDF compression available in languages other than C#?
Yes, CompressPdfToBytes and CompressPdfToStream are now available across all IronPDF platforms, including Java, Node.js, and Python.
How do I get fine-grained control over PDF compression in C#?
Pass an AdvancedCompressionOptions object to CompressAndSaveAs to tune the pipeline, including image DPI downsampling via TargetImageDpi, JPEG re-encoding quality via JpegQuality, and the zlib CompressionLevel. The original CompressAndSaveAs(outputPath, quality, removeStructureTree) overload still works and produces the same output as before.

