All formats

PdfPig

LanguageC# (.NET Standard 2.0, .NET 6+, .NET Framework 4.6.2+)
LicenseApache-2.0
Repositorygithub.com/UglyToad/PdfPig
DocumentationREADME and wiki
Depends onnothing (fully managed)
Read / writeyes / basic: text, letters, words, images, annotations, metadata; create pages with text and graphics, merge

PdfPig is a port of the parsing parts of Apache PDFBox to C#, with no native dependencies. It reads every letter with its font, size and bounding box, and includes document layout analysis tools: word extractors, page segmenters (Docstrum, recursive XY cut) and reading-order detection, useful for extracting text from multi-column documents or feeding PDFs to search and machine-learning pipelines. It opens encrypted files with a password.

PdfDocumentBuilder creates simple documents (standard 14 or TrueType fonts, lines, rectangles, images) and copies pages from existing files, and PdfMerger merges files. PdfPig doesn’t render pages, fill forms or encrypt. The version is below 1.0, so minor releases can change the API.

Installation#

Shell
dotnet add package PdfPig

Basic usage: extract text from a PDF#

C#
using UglyToad.PdfPig;
using UglyToad.PdfPig.Content;
using UglyToad.PdfPig.DocumentLayoutAnalysis.TextExtractor;

using PdfDocument document = PdfDocument.Open("in.pdf");
Console.WriteLine($"{document.NumberOfPages} pages, PDF {document.Version}");

foreach (Page page in document.GetPages())
{
    // text in content order, with line breaks and spaces inferred from positions
    string text = ContentOrderTextExtractor.GetText(page);
    Console.WriteLine($"--- page {page.Number} ({page.Width} x {page.Height} pt) ---");
    Console.WriteLine(text);
}

page.Text returns the raw text in the order it appears in the content stream, without inferred spaces or line breaks: usually not what you want.

How to get words and their positions#

C#
using UglyToad.PdfPig.DocumentLayoutAnalysis.WordExtractor;

Page page = document.GetPage(1);  // pages are numbered from 1
foreach (var word in page.GetWords(NearestNeighbourWordExtractor.Instance))
{
    var box = word.BoundingBox;
    Console.WriteLine($"{word.Text} at ({box.Left:F1}, {box.Bottom:F1}) font {word.FontName}");
}
foreach (var letter in page.Letters.Take(5))
    Console.WriteLine($"{letter.Value} size {letter.PointSize}");

How to read PDF metadata#

C#
using PdfDocument document = PdfDocument.Open("in.pdf");
var info = document.Information;
Console.WriteLine($"Title: {info.Title}");
Console.WriteLine($"Author: {info.Author}");
Console.WriteLine($"Producer: {info.Producer}");
Console.WriteLine($"Created: {info.CreationDate}");

How to open a password-protected PDF#

C#
using UglyToad.PdfPig;

using var document = PdfDocument.Open("secret.pdf", new ParsingOptions { Password = "password" });

How to merge PDF files#

C#
using UglyToad.PdfPig.Writer;

byte[] merged = PdfMerger.Merge("a.pdf", "b.pdf", "c.pdf");
File.WriteAllBytes("merged.pdf", merged);

How to create a PDF with text#

C#
using UglyToad.PdfPig.Content;
using UglyToad.PdfPig.Core;
using UglyToad.PdfPig.Fonts.Standard14Fonts;
using UglyToad.PdfPig.Writer;

var builder = new PdfDocumentBuilder();
PdfPageBuilder page = builder.AddPage(PageSize.A4);
PdfDocumentBuilder.AddedFont font = builder.AddStandard14Font(Standard14Font.Helvetica);
page.AddText("Hello, PDF!", 24, new PdfPoint(72, 750), font);
page.DrawLine(new PdfPoint(72, 740), new PdfPoint(300, 740));
File.WriteAllBytes("hello.pdf", builder.Build());

Standard 14 fonts support only Latin-1 text; register a TrueType font with builder.AddTrueTypeFont(File.ReadAllBytes("font.ttf")) for other characters.

How to extract images#

C#
foreach (var image in document.GetPage(1).GetImages())
{
    if (image.TryGetPng(out byte[] png))
        File.WriteAllBytes($"image-{Guid.NewGuid()}.png", png);
    else
        File.WriteAllBytes($"image-{Guid.NewGuid()}.bin", image.RawBytes.ToArray());  // e.g. JPEG data
}

Tips#