This guide shows you how to use the PDFluent SDK to permanently remove sensitive content from your PDF documents. It is for developers who need to implement secure and compliant redaction.
Add the pdfluent crate to Cargo.toml. No native dependencies are required.
[dependencies]
pdfluent = "1.0.0-beta.18"Remove sensitive content from PDF files with black-box redaction. PDFluent removes the underlying text and image data, not just paints over it.
use pdfluent::{PdfDocument, RedactOptions};
fn main() -> pdfluent::Result<()> {
let mut doc = PdfDocument::open("contract.pdf")?;
doc.redact("CONFIDENTIAL", RedactOptions::new())?;
doc.save("redacted.pdf")?;
Ok(())
}Load the PDF you want to redact. Use open() for files on disk or from_bytes() for in-memory data.
use pdfluent::PdfDocument;
let mut doc = PdfDocument::open("sensitive_report.pdf")?;Call redact_text() with the exact string to remove. PDFluent searches all pages and marks every occurrence. The text is not yet removed at this step.
use pdfluent::RedactOptions;
// Remove specific strings (search + redact across all pages)
doc.redact("Alice Johnson", RedactOptions::new())?;
doc.redact("account: 4111-1111-1111-1111", RedactOptions::new())?;
// Redact a page region by coordinates [x1, y1, x2, y2] (points, from bottom-left)
doc.redact_region(0, [50.0, 700.0, 300.0, 720.0])?;The default fill is solid black. You can change the fill colour or add a label such as "REDACTED" over the box.
use pdfluent::RedactOptions;
// Scope a redaction to specific pages, case-insensitive
let opts = RedactOptions::new().case_sensitive(false).on_pages(&[0, 1]);
doc.redact("SSN: 123-45-6789", opts)?;Call apply_redactions() to permanently remove the marked content from the data stream. Then save the file. After this step the content cannot be recovered.
// redact() / redact_region() apply in place — write the sanitised file
doc.save("report_redacted.pdf")?;
println!("All redactions applied and saved.");Use regular expressions to find and permanently remove credit card numbers, SSNs, email addresses, or any structured data from a PDF.
use pdfluent::{PdfDocument, RedactOptions};
fn main() -> pdfluent::Result<()> {
let mut doc = PdfDocument::open("data.pdf")?;
doc.redact(r"\d{3}-\d{2}-\d{4}", RedactOptions::new().regex(true))?;
doc.save("redacted.pdf")?;
Ok(())
}Load the file from disk or from an in-memory buffer.
use pdfluent::PdfDocument;
let mut doc = PdfDocument::open("customer_data.pdf")?;Write patterns for the data types you want to remove. PDFluent uses the Rust regex crate syntax.
// Credit card: Visa, Mastercard, Amex formats
let cc_pattern = r"\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13})\b";
// Email addresses
let email_pattern = r"[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}";
// US phone numbers
let phone_pattern = r"\b\(?\d{3}\)?[\s.\-]?\d{3}[\s.\-]?\d{4}\b";Call redact_pattern() for each regex. You can chain multiple patterns before calling apply_redactions().
use pdfluent::RedactOptions;
let opts = RedactOptions::new().regex(true);
doc.redact(cc_pattern, opts.clone())?;
doc.redact(email_pattern, opts.clone())?;
doc.redact(phone_pattern, opts)?;apply_redactions() permanently removes all matched text from the content stream.
// Pattern redactions apply in place — write the cleaned file
doc.save("customer_data_clean.pdf")?;
println!("Pattern redaction complete.");Permanently remove personal data from PDF content streams — not just visually. A black-box overlay leaves text extractable; PDFluent removes it from the object layer.
use pdfluent::{PdfDocument, RedactOptions};
fn main() -> pdfluent::Result<()> {
let mut doc = PdfDocument::open("records.pdf")?;
doc.redact("[email protected]", RedactOptions::new())?;
doc.redact_region(0, [72.0, 700.0, 320.0, 720.0])?;
doc.save("redacted.pdf")?;
Ok(())
}Determine which personal data is present in the document. PDFluent supports regex-based pattern matching, manual region selection, and full-text search. Common patterns include social security numbers, names, email addresses, phone numbers, and financial identifiers.
use pdfluent::{PdfDocument, RedactOptions};
let mut doc = PdfDocument::open("contract_with_pii.pdf")?;
// Regex match — redact all occurrences across all pages
let re = RedactOptions::new().regex(true);
doc.redact(r"\b[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}\b", re.clone())?; // email
doc.redact(r"\b\d{3}-\d{2}-\d{4}\b", re.clone())?; // US SSN
doc.redact(r"\b\d{4}[\s\-]?\d{4}[\s\-]?\d{4}[\s\-]?\d{4}\b", re)?; // credit cardMarking creates redaction annotations over the identified content. At this stage the content is still present — marks are reversible until you call apply_redactions(). This lets you review and adjust the selection before committing.
// Redact a specific region by coordinates [x1, y1, x2, y2] (page index first)
doc.redact_region(0, [72.0, 600.0, 300.0, 620.0])?;
// Or redact an exact text string
doc.redact("Jan de Vries", pdfluent::RedactOptions::new())?;apply_redactions() modifies the PDF content stream directly. Text and image data in marked regions is removed from the object layer, not just hidden. After this step the content cannot be recovered, even by a PDF parser operating on the raw bytes.
use pdfluent::RedactOptions;
// RedactOptions controls matching. redact() / redact_region() mutate the
// document in place — there is no separate "apply" step.
let _opts = RedactOptions::new().case_sensitive(false).regex(true);After applying redactions, extract the text and check that the personal data is absent. This step is important for audit purposes and to confirm the redaction worked as intended before delivering or storing the document.
// Verify: extracted text must not contain the redacted values
let text = doc.text()?;
assert!(!text.contains("Jan de Vries"), "Redaction failed: name still present");
assert!(!text.contains("123-45-6789"), "Redaction failed: SSN still present");
println!("Verification passed — PII removed from content stream");PDF metadata (Author, Title, Subject, Keywords) and XMP metadata may contain PII independently of the page content. Clear it before saving. Keep the original file for your audit trail if required by your data retention policy.
// Clear document Info metadata that may carry PII
doc.metadata_mut().set_title("").set_author("").set_subject("").commit()?;
// Save to a new path — keep the original for audit
doc.save("contract_redacted.pdf")?;
println!("Redacted document saved.");