Ask Anvil

Answers to questions about automating PDFs, e-signatures, Webforms, and other paperwork problems.
PDFs
Categories

How do I password-protect a PDF I generate in Python?

from pypdf import PdfReader, PdfWriter

reader = PdfReader("input.pdf")
writer = PdfWriter()

# copy every page into a fresh writer
for page in reader.pages:
    writer.add_page(page)

# user_password: required to open the file
# owner_password: controls permissions (printing, editing, copying)
writer.encrypt(
    user_password="open-sesame",
    owner_password="owner-secret",
    algorithm="AES-256",
)

with open("protected.pdf", "wb") as f:
    writer.write(f)

What each argument does

The user_password is what a reader types to open the document. The optional owner_password unlocks full permissions such as printing, editing, and copying text, so give it a different value: that way, sharing the open password does not also hand over owner rights. The algorithm argument matters most. If you omit it, pypdf falls back to RC4, which is old and insecure, so always pass an AES option. The pypdf documentation lists RC4-40, RC4-128, AES-128, AES-256-R5, and AES-256 as the choices, and recommends AES-256-R5.

Reading the file back

An encrypted file reports is_encrypted as True, and touching its pages before you supply the password raises FileNotDecryptedError. Call decrypt() with the user password first, then read the pages as usual.

from pypdf import PdfReader

reader = PdfReader("protected.pdf")
print(reader.is_encrypted)      # True
reader.decrypt("open-sesame")   # supply the user password first
print(len(reader.pages))        # pages are now readable

Two caveats

First, a password protects the file at rest, not everything that happens afterward. Once a recipient opens it they can re-save an unprotected copy, and a short password can be brute forced, so pick a long, unique one and still move the file over an encrypted channel such as HTTPS rather than a plain email attachment.

Second, AES encryption is an optional dependency in pypdf. The base install leaves out the AES backend, so install it with pip install "pypdf[crypto]", which pulls in the cryptography package. Without that extra, AES encryption is unavailable. The default RC4 works without it but is insecure and not worth using.

Back to All Questions

The fastest way to build software for documents

Anvil Document SDK is a comprehensive toolbox for product teams launching document flows where PDF filling, signing, and complex conditional scenarios are necessary.
Explore Anvil
Anvil Webforms