DEV Community

IronSoftware
IronSoftware

Posted on

How to Edit PDFs in C# (.NET Guide)

PDF editing in .NET has traditionally meant one of two paths: use iTextSharp and write 50+ lines of boilerplate for simple operations, or shell out to command-line tools like pdftk and manage process execution, error handling, and platform dependencies. Both approaches work but neither feels native to .NET development.

I've maintained systems using iTextSharp for years. The library is powerful but the API shows its age. To add a watermark, you instantiate PdfReader, PdfStamper, manage streams, get page resources, create content streams, write PDF operators, and explicitly dispose everything. The code is verbose, error-prone, and difficult to maintain. Every time someone needs to modify PDF operations, they're debugging low-level PDF structure rather than focusing on business logic.

IronPDF takes a different approach. PDF editing operations are methods on the PdfDocument object: pdf.ApplyWatermark(), pdf.Merge(), pdf.RemovePage(). The code reads like what you're trying to accomplish rather than how PDFs work internally. This abstraction eliminates most of the boilerplate while still providing access to advanced features when needed.

The practical impact is significant. I've replaced 200-line iTextSharp watermarking scripts with 5-line IronPDF equivalents. The shorter code is easier to read, test, and modify. When requirements change — different watermark positioning, conditional application, dynamic text — the changes are straightforward rather than requiring deep PDF knowledge.

For developers inheriting codebases or building new document workflows, IronPDF's approach means less time reading PDF specification documentation and more time solving actual business problems. The library handles PDF structure, coordinate systems, content streams, and resource management internally. You work with high-level concepts: pages, text, images, annotations.

Understanding what "editing" means in PDF context is important. PDFs aren't like Word documents where you click and type. PDFs are structured documents with page content streams, resource dictionaries, and object graphs. Editing typically means adding new content ([watermarks](https://ironpdf.com/java/how-to/java-merge-pdf-tutorial/), annotations, stamps), modifying structure (merge, split, reorder pages), or replacing content (text find-replace, redaction). IronPDF supports all these operations through consistent, discoverable APIs.

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var pdf = PdfDocument.FromFile("document.pdf");
pdf.ApplyWatermark("<h1>DRAFT</h1>", opacity: 50);
pdf.SaveAs("watermarked.pdf");
Enter fullscreen mode Exit fullscreen mode

That's the fundamental pattern for most PDF editing operations: load a PDF, apply modifications, save the result. The modifications happen in-memory, preserving the original file until you explicitly save. For production workflows processing many files, this pattern extends naturally to loops or parallel operations.

How Do I Add Watermarks to PDFs?

Watermarks are the most common PDF editing operation I encounter — marking documents as drafts, adding confidential notices, branding generated reports. IronPDF supports both HTML-based watermarks with full styling control and simple text watermarks.

HTML watermarks with custom positioning:

var pdf = PdfDocument.FromFile("report.pdf");

pdf.ApplyWatermark(@"
    <div style='
        transform: rotate(-45deg);
        font-size: 80px;
        font-weight: bold;
        color: red;
        opacity: 0.3;
    '>CONFIDENTIAL</div>
", opacity: 30, rotation: -45, verticalAlignment: IronPdf.Editing.VerticalAlignment.Middle);

pdf.SaveAs("watermarked.pdf");
Enter fullscreen mode Exit fullscreen mode

The HTML watermark approach gives complete control over appearance using familiar CSS. Font sizes, colors, positioning, rotation — all controlled through standard web styling. The opacity parameter adds an additional transparency layer, with values from 0 (invisible) to 100 (fully opaque). I typically use 20-40% opacity for subtle background watermarks and 50-70% for prominent notices.

Compared to iTextSharp's watermarking, which requires calculating coordinates, managing fonts, writing PDF operators, and handling text rendering modes manually, this HTML approach is dramatically simpler. I've migrated watermarking systems from iTextSharp to IronPDF and reduced code size by 80% while gaining better control over styling.

For simple text watermarks without HTML:

pdf.ApplyWatermark("SAMPLE COPY", opacity: 40);
Enter fullscreen mode Exit fullscreen mode

This applies default styling — centered, rotated diagonally, semi-transparent. Useful when you need quick watermarking without custom design requirements. I use this pattern for automated test document generation where the watermark indicates the document type rather than serving branding purposes.

Watermarks can be applied to all pages or specific page ranges. For watermarking only the first page:

pdf.ApplyWatermark("<h2>Cover Page</h2>", pageIndexes: new[] { 0 });
Enter fullscreen mode Exit fullscreen mode

Page indexing is zero-based: the first page is index 0, second page is index 1, and so on. This can be counterintuitive but it's consistent with standard array indexing throughout .NET.

How Do I Add Stamps and Annotations?

Beyond watermarks, PDFs support stamps (text or images overlaid on pages) and annotations (interactive elements like comments, highlights, or notes). These are useful for review workflows, approval processes, or adding contextual information to existing documents.

Text stamps for approval markings:

var stamper = new IronPdf.Editing.TextStamper
{
    Text = "APPROVED",
    FontFamily = "Arial",
    FontSize = 30,
    IsBold = true,
    Opacity = 80,
    Rotation = 0
};

pdf.ApplyStamp(stamper, pageIndexes: new[] { 0 });
pdf.SaveAs("approved.pdf");
Enter fullscreen mode Exit fullscreen mode

The TextStamper class provides granular control over stamp appearance and positioning. Unlike watermarks which typically span the entire page, stamps are positioned elements. You can place multiple stamps on the same page — approval signatures in one corner, date stamps in another, reference numbers in headers.

I've built approval workflow systems that apply different stamps based on document status: "PENDING REVIEW" in yellow during review, "APPROVED" in green after approval, "REJECTED" in red with rejection reasons. The stamping code checks database status and applies appropriate stamps programmatically, eliminating manual PDF editing.

Image stamps for logos or signature images:

var imageStamper = new IronPdf.Editing.ImageStamper(new Uri("signature.png"))
{
    Opacity = 100,
    VerticalAlignment = IronPdf.Editing.VerticalAlignment.Bottom,
    HorizontalAlignment = IronPdf.Editing.HorizontalAlignment.Right
};

pdf.ApplyStamp(imageStamper);
Enter fullscreen mode Exit fullscreen mode

This embeds an image as a stamp, useful for signature images, company logos, or graphical approval indicators. The alignment options position stamps relative to page corners or centers without requiring coordinate calculations.

For annotations that appear in PDF annotation layers (visible in Adobe Reader's Comments panel):

var annotation = new IronPdf.Annotations.TextAnnotation
{
    Title = "Review Comment",
    Contents = "Please verify the figures in section 3.",
    X = 200,
    Y = 300,
    Width = 150,
    Height = 100
};

pdf.AddAnnotation(annotation, pageIndex: 2);
Enter fullscreen mode Exit fullscreen mode

Annotations differ from stamps in that they're interactive elements. Users can open, close, reply to, or delete annotations in PDF viewers. This makes them appropriate for review workflows where comments need to be addressed and potentially removed, rather than permanent markings like stamps.

How Do I Replace or Redact Text in PDFs?

Text replacement and redaction are critical for document processing — updating outdated information, correcting errors, or removing sensitive data. IronPDF supports both find-replace operations and secure redaction.

Find and replace text:

pdf.ReplaceText("old-company-name", "new-company-name");
pdf.SaveAs("updated.pdf");
Enter fullscreen mode Exit fullscreen mode

This searches the entire document for the specified text and replaces all occurrences. The operation preserves surrounding formatting, fonts, and layout. I use this for updating company names in template documents, correcting repeated errors in generated reports, or updating version numbers in documentation.

The replacement is literal string matching. For pattern-based replacement, you'd need to extract text, perform regex replacements, and regenerate the PDF — a workflow better suited to modifying source HTML before PDF generation rather than editing existing PDFs.

For redacting sensitive information:

pdf.RedactText("social-security-number");
pdf.SaveAs("redacted.pdf");
Enter fullscreen mode Exit fullscreen mode

Redaction differs from deletion. Deleted text leaves blank spaces but the text remains in the PDF's internal structure, potentially recoverable. Redaction completely removes the text and draws a black box over the area, ensuring the data is truly eliminated. This is essential for compliance with privacy regulations like GDPR or HIPAA where sensitive information must be irretrievably removed.

I've built redaction systems for legal document processing where client names, account numbers, and personally identifiable information must be removed before documents are released publicly. The redaction operations happen programmatically based on patterns identified during text analysis, ensuring no manual redaction steps are missed.

For redacting specific regions rather than text search:

pdf.RedactRegion(x: 100, y: 200, width: 300, height: 50, pageIndex: 0);
Enter fullscreen mode Exit fullscreen mode

This redacts a rectangular area at specific coordinates. Useful when you know where sensitive information appears on the page but can't identify it via text search — images, signatures, or data in specific form fields.

How Do I Merge and Split PDFs?

Document organization operations — combining multiple PDFs, extracting specific pages, reordering content — are common in document workflows. IronPDF handles these through merge and copy operations.

Merge multiple PDFs:

var invoice = PdfDocument.FromFile("invoice.pdf");
var terms = PdfDocument.FromFile("terms.pdf");

invoice.Merge(terms);
invoice.SaveAs("complete-package.pdf");
Enter fullscreen mode Exit fullscreen mode

The merge appends the second PDF's pages to the first. This modifies the invoice PDF object in-place. For combining many PDFs, chain merges or use loops. I've built systems that generate invoices from templates, merge standard terms and conditions, add signature pages, and produce complete contract packages automatically.

Extract specific pages into new documents:

var largePdf = PdfDocument.FromFile("annual-report.pdf");
var executive = largePdf.CopyPages(0, 4);  // First 5 pages
executive.SaveAs("executive-summary.pdf");
Enter fullscreen mode Exit fullscreen mode

The CopyPages method creates a new PDF containing the specified page range. Both indexes are inclusive: pages 0 through 4 means the first 5 pages. The original PDF remains unchanged. I use this for extracting report sections, splitting documents by chapter, or creating page-range exports for stakeholder review.

For extracting a single page:

var page = pdf.CopyPage(0);
page.SaveAs("cover.pdf");
Enter fullscreen mode Exit fullscreen mode

This is equivalent to CopyPages with start and end at the same index, but more concise for single-page extraction. Common in workflows that split multi-page documents into individual page files for parallel processing or distribution.

Remove unwanted pages:

pdf.RemovePage(2);  // Remove third page (zero-indexed)
pdf.SaveAs("edited.pdf");
Enter fullscreen mode Exit fullscreen mode

This deletes a page from the document. For removing multiple pages, use RemovePages with a list of indexes. Note that after removing a page, subsequent pages shift down — removing page 2 makes what was page 3 become the new page 2. The RemovePage methods handle this reindexing internally.

How Do I Add Headers and Footers?

Headers and footers are essential for professional documents — page numbers, document titles, dates, company information. IronPDF generates headers and footers from HTML, giving complete control over content and styling.

Simple page numbering footer:

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align: center;'>Page {page} of {total-pages}</div>",
    DrawDividerLine = true
};

var pdf = renderer.RenderHtmlAsPdf("<h1>Document Content</h1>");
pdf.SaveAs("numbered.pdf");
Enter fullscreen mode Exit fullscreen mode

The {page} and {total-pages} placeholders are replaced automatically during rendering. The divider line draws a horizontal rule separating footer content from page content. I use this pattern for generated reports where page numbers help readers navigate printed copies.

For adding headers and footers to existing PDFs rather than during generation, you'd use watermarks or stamps positioned in header/footer regions. IronPDF's header/footer functionality is primarily for HTML-to-PDF generation workflows.

Complex headers with multiple elements:

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = @"
        <div style='display: flex; justify-content: space-between; font-size: 10px;'>
            <div>Company Confidential</div>
            <div>{date:yyyy-MM-dd}</div>
        </div>
    "
};
Enter fullscreen mode Exit fullscreen mode

This creates a two-column header with company notice on the left and current date on the right, using flexbox for layout. The {date} placeholder supports .NET date format strings. Full CSS styling works in headers and footers, allowing complex designs matching your document branding.

How Do I Extract Text and Images from PDFs?

Before editing PDFs, you often need to analyze existing content — extract text for processing, pull images for archival, or parse structure for validation. IronPDF provides extraction methods for both text and images.

Extract all text from a PDF:

var pdf = PdfDocument.FromFile("document.pdf");
string allText = pdf.ExtractAllText();
Console.WriteLine(allText);
Enter fullscreen mode Exit fullscreen mode

This extracts text from all pages into a single string. The text preserves reading order but loses formatting, fonts, and positioning information. Useful for full-text search indexing, content analysis, or feeding text into processing pipelines.

For page-specific text extraction:

string pageText = pdf.ExtractTextFromPage(0);  // First page only
Enter fullscreen mode Exit fullscreen mode

I use page-specific extraction when processing structured documents where different pages contain different data types — invoices where page 1 has summary data, page 2 has line items, page 3 has terms. Extracting pages individually simplifies parsing logic.

Extract all images:

var images = pdf.ExtractAllImages();
foreach (var image in images)
{
    File.WriteAllBytes($"image-{Guid.NewGuid()}.png", image);
}
Enter fullscreen mode Exit fullscreen mode

This extracts every image embedded in the PDF as raw bitmap data. Images lose their original format (JPEG, PNG) and are returned as bitmaps. The extraction is useful for archiving images separately, processing images with computer vision systems, or auditing document content.

Extracted text and images enable workflows where you analyze PDFs before editing them — identify sensitive information for redaction, find specific pages for extraction, or validate content before applying stamps or watermarks.

What About Form Fields and Interactive Elements?

PDF forms contain fillable fields — text inputs, checkboxes, dropdowns. Editing forms means populating field values programmatically, useful for batch-filling forms from database data or generating pre-filled documents.

Fill form fields by name:

var pdf = PdfDocument.FromFile("application-form.pdf");
pdf.Form.Fields["applicant_name"].Value = "John Doe";
pdf.Form.Fields["application_date"].Value = DateTime.Now.ToShortDateString();
pdf.Form.Fields["agree_terms"].Value = "Yes";
pdf.SaveAs("filled-form.pdf");
Enter fullscreen mode Exit fullscreen mode

This populates form fields using field names from the PDF. Field names are defined when the form is created in Adobe Acrobat or other PDF form editors. You can iterate through pdf.Form.Fields to discover field names programmatically.

I've built application processing systems that pull data from databases, match fields to PDF form names, and generate pre-filled forms for applicants to sign. This eliminates manual form filling and ensures data consistency between systems.

For flattening forms (converting fillable fields to static content):

pdf.Form.Flatten();
pdf.SaveAs("flattened.pdf");
Enter fullscreen mode Exit fullscreen mode

Flattening converts form fields to regular PDF content, preventing further editing. Essential for finalized documents where you don't want recipients changing field values. I flatten forms after filling them for archival or distribution where the content should be read-only.

Quick Reference

Task Method Notes
Apply watermark pdf.ApplyWatermark(html) HTML with CSS styling
Text stamp pdf.ApplyStamp(TextStamper) Positioned text overlay
Image stamp pdf.ApplyStamp(ImageStamper) Logo or signature image
Add annotation pdf.AddAnnotation(TextAnnotation) Interactive comment
Replace text pdf.ReplaceText(old, new) Find and replace
Redact text pdf.RedactText(search) Secure removal
Redact region pdf.RedactRegion(x, y, w, h) Coordinate-based
Merge PDFs pdf.Merge(other) Append pages
Copy pages pdf.CopyPages(start, end) Extract page range
Remove page pdf.RemovePage(index) Delete page
Extract text pdf.ExtractAllText() All text content
Extract images pdf.ExtractAllImages() All embedded images
Fill form field pdf.Form.Fields["name"].Value = val Populate forms
Flatten form pdf.Form.Flatten() Convert to static

Key Principles:

  • Load PDFs with PdfDocument.FromFile(), modify in-memory, save with SaveAs()
  • Watermarks apply HTML/CSS styling across entire pages
  • Stamps are positioned elements (text or images)
  • Redaction permanently removes content, replacement preserves layout
  • Merge modifies the calling PDF, copy operations create new documents
  • Page indexes are zero-based (first page = 0)
  • Form field names are defined in the PDF, iterate Fields to discover them

The complete PDF editing tutorial covers advanced scenarios like programmatic annotation positioning and multi-layer watermarking.


Written by Jacob Mellor, CTO at Iron Software. Jacob created IronPDF and leads a team of 50+ engineers building .NET document processing libraries.

Top comments (0)