pdftlο
pdftl (βPDF tackleβ) is a CLI tool for PDF manipulation written in Python. It is intended to be a command-line compatible extension of the venerable pdftk.
Leveraging the power of pikepdf (qpdf) and other modern libraries, it offers advanced capabilities like cropping, chopping, regex text replacement, adding text and arbitrary content stream injection.
Quick startο
pipx install pdftl[full]
# merge, crop to letter paper, rotate last page and output with encryption with one command
pdftl A=a.pdf B=b.pdf cat A1-5 B2-end \
--- crop '4-8,12(letter)' \
--- rotate endright \
output out.pdf owner_pw foo user_pw bar encrypt_aes256
Key features and pdftk compatibilityο
Familiar syntax: Command-line compatible with
pdftk. Verified against Mike Haertlβs php-pdftk test suite and the pdftk-java test suite logic, sos/pdftk/pdftl/should result in working scripts.Pipelining: Chain multiple operations in a single command using
---.Performant:
pdftlseems faster thanpdftk-javafor many operations (based on informal benchmarks). Reason:pdftlmostly drivespikepdfwhich drivesqpdf, a fast C++ library.Extra/enhanced operations and features such as zooming pages, smart merging preserving links and outlines, cropping/chopping up pages, text extraction, optimizing images.
Modern security: Supports AES-256 encryption and modern permission flags out of the box.
Content editing: Find & replace text via regular expressions, inject raw PDF operators, or overlay dynamic text.
pdftl maintains command-line compatibility with pdftk while introducing features required for modern PDF workflows.
Feature |
|
|
|---|---|---|
Pipelining |
β (Requires temp files) |
β
Native (Chain ops with |
Encryption |
β οΈ (Obsolete RC4) |
β AES-256 Support |
Syntax |
Standard |
β Compatible Extension |
Page Geometry |
β |
β Crop to fit, Zoom, & Chop |
Pipelined Logic |
β |
β Rotate + Stamp in one command |
Plugins |
β |
β Custom operations/mutation scripts written in Python |
Installation |
Often complex binary |
β
Simple |
Performance |
Variable |
β Powered by pikepdf/qpdf |
Link Integrity |
β οΈ Often breaks TOC/Links |
β Preserves internal cross-refs |
Shell Completion |
β οΈ zsh |
β bash, zsh and powershell |
Help |
β οΈ Basic (manpage) |
β
Self-documenting: |
Installationο
Install pipx, and then:
pipx install pdftl[full]
A simple pip install pdftl[full] install is also supported.
Note: The [full] install includes ocrmypdf for image optimization, reportlab for text generation, pypdfium2 for text extraction and robust flattening, and pyHanko for cryptographic signature functionality. Omit [full] to omit those features and dependencies.
Key featuresο
π Standard operationsο
Combine:
cat,shuffle(interleave pages from multiple docs).Split:
burst(split into single pages, by bookmarks, by size,β¦),deletepages ordelete_blankpages.Metadata:
dump_data,update_info,setpage labels, document properties, β¦Attachments:
attach_files,unpack_files,dump_files,delete_attachments.Bookmarks:
dump_bookmarks,add_bookmarks,delete_bookmarksandupdate_bookmarkswith high fidelity, using structured YAML or JSON.Watermarking:
stamp/background(single page),multistamp/multibackground.
βοΈ Geometry & splittingο
Whole-page geometry:
rotatepages (absolute or relative) orzoompagesClip and Crop:
croppages to margins or standard paper sizes (e.g., βA4β), or keep pages unchanged andclipto hide content outside a given region.Chop:
choppages into grids or rows (e.g., split a scanned spread into two pages).Shift, scale and spin page content inside the page boundaries using
place.Montage:
montagemultiple pages onto a grid layout for contact sheets and N-up handouts.Booklet: create a print-ready
bookletwith optional RTL support and signature splitting.
π Forms & annotationsο
Forms:
fill_form,generate_fdf,dump_data_fields.Annotations:
modify_annots(surgical edits to link properties, colors, borders),delete_annots,dump_annots,highlightby full-text regular expression search.
π Securityο
Decryption: using
input_pw.Encryption: using
owner_pw,user_pwandencrypt_aes256, optionally setting permissions withallow. Read permissions/encryption data withdump_encryptionSignatures: add secure signatures using
sign_keyandsign_cert. List and verify signatures usingdump_signatures(powered bypyHanko).
π οΈ Advancedο
Text replacement:
replacetext in content streams using regular expressions (experimental).Code injection:
injectraw PDF operators at the head/tail of content streams.Images:
optimize_images(smart compression via OCRmyPDF),delete_images,dump_imagesorrenderPDF to images.Dynamic text:
add_textsupports Bates stamping and can add page numbers, filenames, timestamps, etc.Cleanup:
normalizecontent streams,linearizefor web viewing.Layers (aka OCGs):
dump_layers) andmodify_layers: list, strip or merge PDF layers.Plugins: write your own custom operation in Python, save to
~/.config/pdftl/operations(*nix) or%APPDATA%\pdftl\config(Windows) and you can use it in pdftl, just like the built-in operations. And you canmutate_contentusing simple Python scripts.
Examplesο
For more than 100 other examples: pdftl help examples.
Concatenationο
# Merge two files
pdftl in1.pdf in2.pdf cat output combined.pdf
# Now with in2.pdf zoomed in
pdftl A=in1.pdf B=in2.pdf cat A Bz1 output combined2.pdf
Geometryο
# Take pages 1-5, rotate them 90 degrees East, and crop to A4
pdftl in.pdf cat 1-5east --- crop "(a4)" output out.pdf
Pipeliningο
You can chain operations without intermediate files using ---:
# Burst a file, but rotate and stamp every page first
pdftl in.pdf rotate south \
--- stamp watermark.pdf \
--- burst output page_%04d.pdf
Forms and metadataο
# Fill a form and flatten it (make it non-editable)
pdftl form.pdf fill_form data.fdf flatten output signed.pdf
Modify annotationsο
# Change all Highlight annotations on odd pages to Red
pdftl docs.pdf modify_annots "odd/Highlight(C=[1 0 0])" output red_notes.pdf
Modify contentο
# Add a watermark, the pdftk way
pdftl in.pdf stamp watermark.pdf output marked1.pdf
# Add an obnoxious semi-transparent red watermark on odd pages only
pdftl in.pdf add_text 'odd/YOUR AD HERE/(position=mid-center, font=Helvetica-Bold, size=72, rotate=45, color=1 0 0 0.5)' output with_ads.pdf
# Add Bates numbering starting at 000121
# Result: DEF-000121, DEF-000122, ...
pdftl in.pdf \
add_text "/DEF-{page+120:06d}/(position=bottom-center, offset-y=10)" \
output bates.pdf
# Content stream replacement with regular expressions (YMMV)
# Change black to red
pdftl in.pdf replace '/0 0 0 (RG|rg)/1 0 0 \1/' output redder.pdf
Python APIο
While pdftl is primarily a CLI tool, it also exposes a robust Python API for integrating PDF workflows into your scripts.
It supports both a Functional interface (similar to the CLI) and a Fluent interface (for method chaining).
from pdftl import pipeline
# Chain operations fluently without saving intermediate files
(
pipeline("input.pdf")
.rotate("right")
.stamp("watermark.pdf")
.save("output.pdf")
)
See the API Tutorial for more details.
Operations and optionsο
Operation |
Description |
|---|---|
Add top-level bookmarks |
|
Add user-specified text strings to PDF pages |
|
Attach files to the output PDF |
|
Use a 1-page PDF as the background for each page |
|
Impose pages into printable booklet signatures |
|
Split a single PDF into multiple files |
|
Concatenate pages from input PDFs into a new PDF |
|
Chop pages into multiple smaller pieces |
|
Clip page content to a rectangle |
|
Crop pages to a rectangle |
|
Delete pages from an input PDF |
|
Delete annotation info |
|
Delete file attachments based on criteria |
|
Delete bookmarks |
|
Delete blank or near-blank pages |
|
Delete images |
|
Dump annotation info |
|
Extract PDF bookmarks into YAML or JSON |
|
Report color spaces used |
|
Metadata, page and bookmark info (XML-escaped) |
|
Dump annotation info in pdftk style |
|
Print PDF form field data with XML-style escaping |
|
Print PDF form field data in UTF-8 |
|
Metadata, page and bookmark info (in UTF-8) |
|
Print PDF named destinations data to the console |
|
Print PDF encryption details and permissions |
|
List file attachments |
|
Extract PDF embedded image metadata to JSON |
|
Dump layer info (JSON) |
|
List and validate digital signatures |
|
Print PDF text data to the console or a file |
|
Fill a PDF form |
|
Do nothing (the default if |
|
Generate an FDF file containing PDF form data |
|
Highlight text matching a regex pattern |
|
Inject code at start or end of page content streams |
|
Insert blank pages |
|
Modify properties of existing annotations |
|
Merge or strip specific layers |
|
Impose pages onto a grid layout |
|
Move pages to a new location |
|
Use multiple pages as backgrounds |
|
Stamp multiple pages onto an input PDF |
|
Mutate page content streams using a user-supplied Python script |
|
Reformat page content streams |
|
Optimize images |
|
Shift, scale, and spin page content |
|
Regex replacement on page content streams |
|
Render PDF pages as images |
|
Rotate pages in a PDF |
|
Set document properties, viewer preferences, and page labels |
|
Interleave pages from multiple input PDFs |
|
Stamp a 1-page PDF onto each page of an input PDF |
|
Unpack file attachments |
|
Remove βpauseβ frames from a slide deck |
|
Replace PDF bookmarks from a YAML or JSON file |
|
Update PDF metadata from dump_data instructions |
|
Update PDF metadata from dump_data_utf8 instructions |
|
Rescale entire pages |
Option |
Description |
|---|---|
Specify permissions for encrypted files |
|
Compress output file streams (default) |
|
Discard document-level info metadata |
|
Discard form XFA data if present |
|
Discard document-level XMP metadata |
|
Use 128 bit encryption (obsolete, maybe insecure) |
|
Use 40 bit encryption (obsolete, highly insecure) |
|
Use 128 bit AES encryption (maybe obsolete) |
|
Use 256 bit AES encryption |
|
Skip stream recompression for faster saving |
|
Flatten all annotations |
|
Copy final input PDFβs ID metadata to output |
|
Copy first input PDFβs ID metadata to output |
|
Linearize output file(s) |
|
Leave metadata unencrypted |
|
Set a form rendering flag in the output PDF |
|
The output file path, or a template for burst |
|
Set owner password and encrypt output |
|
Replace the font used for all form fields with a TTF file |
|
Path to certificate PEM |
|
Signature field name (default: Signature1) |
|
Path to private key PEM |
|
Environment variable with sign_cert passphrase |
|
Prompt for sign_cert passphrase |
|
Disable compression of output file streams |
|
Set user password and encrypt output |
|
Turn on verbose output |
Linksο
License: This project is licensed under the Mozilla Public License 2.0.
Changelog: CHANGELOG.md.
Documentation: pdftl.readthedocs.io.