Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Encrypted PDFs

pdfboss opens files encrypted with the PDF Standard security handler: RC4 (40–128-bit, /V 1–2, and /V 4 with crypt filter V2), AES-128 (/V 4, crypt filter AESV2) and AES-256 (/V 5, crypt filter AESV3). Either the user password or the owner password opens the document, and both unlock the same full content. A file protected only by an owner password has an empty user password and opens transparently, with no password at all.

Non-ASCII passwords are tried UTF-8 encoded and, for the legacy RC4/AES-128 revisions, Latin-1 encoded as well, covering both encodings real files use.

Checking whether a file needs a password

pdfboss info never fails on an encrypted file. Whether the file needs a password is the very question being asked:

pdfboss info locked.pdf
version:   1.7
encrypted: true
pages:     unknown

encrypted: true means the file did not open with the password supplied (by default, none). A file that opens (because it is unencrypted, protected only by an owner password, or because --password carried the right value) reports encrypted: false along with the full page and metadata listing:

pdfboss info --password hunter2 locked.pdf
version:   1.7
encrypted: false
pages:     1
  page 1: 612 x 792 pt

CLI

Every subcommand that reads a PDF (info, text, md, render, images, obj, tui, json, hex and q) takes --password, accepted as either the user or the owner password:

pdfboss text --password hunter2 locked.pdf

Apart from info, a command given no password (or a wrong one) for a password-protected file prints an error and exits nonzero.

Python

Document takes a password keyword, and raises PdfError when the file needs a password it was not given (or the given one is wrong):

import pdfboss

try:
    doc = pdfboss.Document("locked.pdf")
except pdfboss.PdfError:
    doc = pdfboss.Document("locked.pdf", password="hunter2")
print(doc.extract_text())

The same keyword exists on the data= form of the constructor and on all three async constructors: AsyncDocument.open, AsyncDocument.open_url and AsyncDocument.from_bytes (see Async and remote documents):

import asyncio

import pdfboss

async def main() -> None:
    doc = await pdfboss.AsyncDocument.open("locked.pdf", password="hunter2")
    print(doc.page_count)

asyncio.run(main())

Rust

Document::open (and Document::load for bytes in memory) handles the empty-user-password case on its own and returns Error::Encrypted when a real password is needed; open_with_password/load_with_password take one:

use pdfboss_core::{Document, Error};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let doc = match Document::open("report.pdf") {
        Err(Error::Encrypted) => Document::open_with_password("report.pdf", "hunter2")?,
        other => other?,
    };
    println!("{} pages", doc.page_count());
    Ok(())
}

A wrong password also comes back as Error::Encrypted. The async document mirrors the sync surface with AsyncDocument::open_with_password, open_url_with_password and from_bytes_with_password:

use pdfboss_aio::AsyncDocument;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let doc = AsyncDocument::open_with_password("report.pdf", "hunter2").await?;
    println!("{} pages", doc.page_count());
    Ok(())
}

Once a document is open, every operation (text, markdown, rendering, images) works exactly as on an unencrypted file; decryption happens transparently underneath. Full option listings live in the CLI reference.