Stamp page numbers onto every page of a PDF. Control position, font, format, and starting number. Skip the cover page or use Roman numerals for front matter.
use pdfluent::{PdfDocument, PageNumberOptions, PageNumberPosition};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut doc = PdfDocument::open("report.pdf")?;
doc.add_page_numbers(
PageNumberOptions::default()
.position(PageNumberPosition::BottomCenter)
.format("{page} / {total}")
.font_size(9.0)
.start_page(1) // skip cover page (index 0)
.start_number(1),
)?;
doc.save("report_numbered.pdf")?;
Ok(())
}Add the pdfluent crate to Cargo.toml.
[dependencies]
pdfluent = "0.9"Load the document you want to number.
use pdfluent::PdfDocument;
let mut doc = PdfDocument::open("thesis.pdf")?;
println!("Pages: {}", doc.page_count());PageNumberOptions controls position, font, format string, and which pages receive numbers.
use pdfluent::{PageNumberOptions, PageNumberPosition};
let opts = PageNumberOptions::default()
.position(PageNumberPosition::BottomCenter)
.format("{page}") // or "Page {page} of {total}"
.font("Helvetica")
.font_size(10.0)
.margin(30.0) // distance from page edge in points
.start_page(0) // zero-based index of first numbered page
.start_number(1); // the number printed on start_pageApply Roman numeral numbering to the first few pages, then switch to Arabic for the main body.
use pdfluent::{PageNumberOptions, PageNumberPosition, NumberStyle};
// Front matter: pages 0-3 in Roman numerals (i, ii, iii, iv)
let front_opts = PageNumberOptions::default()
.position(PageNumberPosition::BottomCenter)
.style(NumberStyle::RomanLower)
.start_page(0)
.end_page(3)
.start_number(1)
.font_size(9.0);
// Main body: pages 4 onward in Arabic (1, 2, 3, ...)
let body_opts = PageNumberOptions::default()
.position(PageNumberPosition::BottomCenter)
.style(NumberStyle::Arabic)
.start_page(4)
.start_number(1)
.font_size(9.0);
doc.add_page_numbers(front_opts)?;
doc.add_page_numbers(body_opts)?;Write the result to disk.
doc.save("thesis_numbered.pdf")?;
println!("Page numbers added.");No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.
Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.
Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.