Render, generate, edit, and extract PDF content

This guide shows developers how to perform core PDF operations with PDFluent. It covers rendering PDFs to images, editing documents, and processing annotations.

Render PDFs to images, anywhere.

Convert PDF pages to PNG, JPEG, or WebP with sub-pixel accuracy. Runs server-side, in Lambda, or via WASM.

rust
use pdfluent::{PdfDocument, ImageFormat};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let doc = PdfDocument::open("document.pdf")?;

    let png = doc.render_page(0, 150, ImageFormat::Png)?;
    std::fs::write("page-1.png", png)?;
    Ok(())
}

Generate PDF thumbnails at scale.

Convert first pages or any pages to JPEG/PNG thumbnails. Batch process document libraries without a display server.

rust
use pdfluent::{PdfDocument, ImageFormat};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let doc = PdfDocument::open("document.pdf")?;

    for i in 0..doc.page_count() {
        let png = doc.render_page(i, 72, ImageFormat::Png)?;
        std::fs::write(format!("thumb-{}.png", i + 1), png)?;
    }
    Ok(())
}

Run PDF processing in the browser.

PDFluent compiles to WASM. Process PDFs client-side without uploading files to a server.

rust
// Install: npm install @pdfluent/sdk-wasm

import init, { PdfluentSdk } from '@pdfluent/sdk-wasm';

async function renderFirstPage(file) {
  await init(); // loads pdfluent_bg.wasm (~6 MB uncompressed, ~2 MB Brotli-compressed; cached after first load)

  const sdk = new PdfluentSdk();
  const bytes = new Uint8Array(await file.arrayBuffer());
  const doc = sdk.openBytes(bytes);

  const image = doc.renderPage(0, {
    format: 'png',
    dpi: 96,
  });

  const blob = new Blob([image], { type: 'image/png' });
  document.getElementById('preview').src = URL.createObjectURL(blob);

  doc.free();
}

Read and write PDF annotations.

Parse, create, and modify comments, highlights, stamps, and ink annotations. Compliant with PDF spec section 12.5.

rust
use pdfluent::{Sdk, Annotation, HighlightAnnotation, Rect, Color};

fn main() -> pdfluent::Result<()> {
    let sdk = Sdk::new()?;
    let mut doc = sdk.open("input.pdf")?;

    let annot = HighlightAnnotation::builder()
        .page(0)
        .rect(Rect::new(72.0, 680.0, 300.0, 695.0))
        .color(Color::rgb(1.0, 0.93, 0.0))
        .author("Alice")
        .contents("Key clause")
        .build();

    doc.page_mut(0)?.add_annotation(annot)?;
    doc.save("annotated.pdf")?;

    Ok(())
}

Edit existing PDFs in Rust.

Modify text, add elements, fill forms, and update metadata — without re-generating the document from scratch. Pure Rust, no Adobe SDK, no Java.

rust
use pdfluent::{PdfDocument, Font, Position, Metadata};

fn stamp_and_update(input: &[u8]) -> Vec<u8> {
    let mut doc = PdfDocument::from_bytes(input)?;

    // Add text to the first page
    let page = doc.page_mut(0)?;
    page.add_text(
        "APPROVED — Finance Team",
        Font::helvetica_bold(12),
        Position::new(50.0, 50.0),
    );

    // Update document metadata
    let mut meta = doc.metadata();
    meta.set_author("Finance Team");
    meta.set_keywords("approved, processed, 2026");
    meta.set_custom("x-workflow-status", "approved");
    doc.set_metadata(meta);

    doc.save_bytes()
}

Add watermarks and stamps to PDFs.

Apply text watermarks, image overlays, and stamps to single pages or entire documents. Batch watermark with per-document variable data.

rust
use pdfluent::{PdfDocument, WatermarkOptions};

fn main() -> pdfluent::Result<()> {
    let mut doc = PdfDocument::open("document.pdf")?;

    let opts = WatermarkOptions::centered()
        .font_size(64.0)
        .rotated(45.0)
        .opacity(0.15)
        .color(0.6, 0.0, 0.0);

    doc.add_watermark("CONFIDENTIAL", opts)?;
    doc.save("watermarked.pdf")?;
    Ok(())
}

Text extraction. Done right.

PDF text extraction with 97.5% pass rate. Preserve layout, reading order, and font metadata.

rust
use pdfluent::PdfDocument;

fn main() -> pdfluent::Result<()> {
    let doc = PdfDocument::open("document.pdf")?;

    // Plain text
    println!("{}", doc.extract_text()?);

    // Positioned text blocks: text + bounding box + page
    for block in doc.text_with_layout()? {
        println!("p{} {:?} {}", block.page, block.bbox, block.text);
    }
    Ok(())
}