Changelog
This changelog format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
Changed
render: API now supports explicitformat=png|jpg|jpeg|pdfoutput selection. Image formats return a ZIP archive;format=pdfreturns a single rasterized PDF. The CLI continues to determine output format fromoutput.server:UI enhancements to
builderinterfaceserver pipeline now takes understands
@Aper-operation arguments, allowing use ofstamp, for example
Fixed
stamp,multistamp,background,multibackground: a PDF file argument to use as overlay/underlay is now required, per the documentationoptimize_images: better errors on missingocrmypdfsystem dependenciesdelete,delete_blank,unpause,insert,move: page labels (/PageLabels) are now preserved and remapped across page deletion, insertion, and reordering, so surviving pages keep their original logical page numbers (e.g. roman-numeral front matter) instead of losing custom numbering.burst: each output chunk now preserves the ORIGINAL document’s page labels/numbering rather than restarting at “1” — e.g. splitting a book by chapter keeps each chapter’s pages numbered as they were in the whole book. This is an intentional deviation from classicpdftkburst behaviour, which has no equivalent concept.dump_bookmarks: strip trailing nulls from outline titles and metadata, like most PDF readers
[0.25.1] - 2026-07-15
Fixed
server:Replaced a racy
multiprocessing.Queue-based IPC mechanism for subprocess-isolated operation execution with aPipe-based protocol that correctly handles worker timeouts, crashes, and cleanup. This fixes intermittent hangs, leaked worker processes/pipes, and dropped/incorrect exception types under concurrent load.Fixed a timeout error message that silently dropped the configured timeout value.
Fixed a keep-alive connection handling bug where rejecting an oversized upload could leave the request thread blocked waiting on the remainder of an in-flight upload body.
Fixed a per-worker memory limit that crashed workers outright on some platforms (notably macOS) instead of degrading gracefully.
Security
server: bounded the number of concurrent subprocess-isolated operation workers (default: capped to available CPU count, configurable viaPDFTL_MAX_CONCURRENT_WORKERS). Previously, a burst of concurrent requests could spawn an unbounded number of worker processes.
[0.25.0] - 2026-07-14
Added
serveroperationdeskewoperationstamp_fieldsoperationembed_fontsoperation--args <file.yml>argument insertioncoalesce_strokesoption added tosimplify_vectors
Changed
sign_fieldno longer changes field appearancesstyle_textnow adapts Tr (text rendering mode) better to user parametersimproved project version-finding heuristics
Fixed
dump_text: ifoutputis passed directly, we now write the text, not the PDF.rendernow initializes forms, so that they are properly rendereddump_signaturesnow correctly reports pyhanko’s valid/invalid status
[0.24.0] - 2026-07-07
Added
import_fontsoperationexport_fontsoperationadded
upscaleandadaptive_thresholdtomodify_imagesimport_imagesoperationexport_imagesoperationimport_streamsoperationadd_bookmarks: new options for bookmark specs:uri,launch,named,dest,color,bold,italicdump_colorspaces: CalGray, CalRGB, and Lab colour spaces now resolved and reported (previously silently fell through)dump_tags: non-standard structure tags now reported as warnings (ISO 32000-2 §14.8)dump_tags: invalid structure attributes now reported as warnings per standard owner definitions (ISO 32000-2 §14.8.5)fill_form: multi-select choice fields now supported (ISO 32000-2 §12.7.5.4)fill_form: radio buttons, checkboxes, list-boxes, and nested fields now handled correctlygenerate_fdf: optionalstatusstring in generated FDF output (ISO 32000-2 Table 246)generate_fdf: multi-select choice field arrays now serialized correctly in FDF outputsetoperation:trappedfield for document trapping status (True,False, orUnknown)setoperation:authornow accepts comma-separated values for multiple authorsBookmarks: non-GoTo actions (e.g.
Launch,Named,JavaScript) are now preserved when copying or round-tripping outlines viadump_bookmarks/add_bookmarks
Changed
Improved verbose pipeline logging feedback loops
Suppressed noisy metadata field conversion logging strings in
dump_datadump_streams: output header format changed fromPage <N>/Page <N> / XObject <name> (<obj>:<gen>)toPage <N> / Contents/ full nested breadcrumb paths (e.g.Page 1 / XObject /Fm1 / XObject /Fm0); obj:gen suffixes are no longer shown. Form XObjects reachable via more than one path now emit a% ALIAS OF: <canonical path>stub on repeat references instead of being silently skipped
Fixed
dump_streams: content stream lines beginning with===or\are now escaped so they don’t get misread as structural headers when round-tripped throughimport_streamsImprove handling of OS errors while saving to disk
Improve handling of invalid or missing arguments in several operations
Destination coordinates for all ISO 32000-2 explicit destination types (
/FitH,/FitV,/FitR,/FitBH,/FitBV,/Fit,/FitB) now correctly transformed when rotating or scaling pages; previously only/XYZcoordinates were handledNull coordinate values in
/XYZdestinations now correctly preserved during rotation and scalingfill_form: digital signature fields are now safely skipped instead of corruptedBookmarks: non-GoTo outline actions (e.g. URI links, launch actions) were silently dropped when merging PDFs; they are now preserved
Named destinations in legacy PDF 1.1
/Root/Destsdictionaries are now resolved correctlyStructure destinations (ISO 32000-2 §12.3.2.3) in outlines now resolve to the correct page, with a fallback to page 1 if no content is found
setoperation: PDF 2.0 documents now correctly omit deprecated metadata fields from the/Infodictionary, per ISO 32000-2 §14.3.3
[0.23.0] - 2026-06-27
Added
delete_actionsoperationdump_actionsoperationdump_tagsoperationtagoperationdump_streamsoperationsimplify_vectorsoperationpng_compressionsetting for therenderoperationoperations are now linked in the HTML docs
Changed
replacenow recurses into XObjects by default
Fixed
delete_imagesglobal mode fixed to delete per-page images tooburstnow keeps outlines and annotations, likecatPrevent BrokenPipeError leaking out
[0.22.0] - 2026-06-20
Added
add_imagesoperationdiff_textoperationdump_tablesoperationmodify_imagesoperationSystem font name and file path resolution for
add_textblock repetition of page specs via
copy<N>multithreading for
resample_imagesandrecolor_images
Changed
page specs now tolerate whitespace (by stripping it before parsing)
dump_bookmarks: named destinations now resolved topage/viewby default; passno_resolveto skipupdate_bookmarks: strict schema validation; accepts structured data directly via API (bookmarks=kwarg)
Fixed
Preserve outline state (open/closed, formatting) when copying outlines
Fix a crash when a subpipeline is passed as an operation argument
bash completion: fix mid-word completion behaviour, update docs
[0.21.1] - 2026-06-14
Fixed
fix
style_textbugs: (1) coalesce content streams (2) handleSCetcadd pattern support to
recolor_vectors
Added
auto-paged help output on linux/mac
[0.21.0] - 2026-06-12
Fixed
rendershould no longer segfault when an unknown output file extension is passeddump_annotsnow properly passing the PDF down the pipelineTop margin percentage bug fixed in
clipandcrop
Changed
pipeline info added to
verbosemodemake parentheses optional for
crop,clip,delete_blank,delete_images, andstyle_text, in many cases
Added
repetitions in page specs via
rep<N>barcodeoperationrecolor_imagesoperationrecolor_vectorsoperationstyle_textoperation
[0.20.0] - 2026-06-07
Added
Guess shell for
--completionif it is not specifiedadd
{count}as an alias for{n}inadd_textandadd_bookmarksunpauseoperationdump_colorspacesoperationdelete_attachmentsoperationdump_fontsoperationcreateoperationresample_imagesoperationgrepoperation
Changed
Performance improvements in link/outline remapping
dump_filesoutput format changed to JSON, with more detailSeveral JSON dump output formats changed from flat lists to
{"name": [...]}format
[0.19.0] - 2026-06-01
Fixed
Fix crash on outline items without a /Title
Added
Filter annotations in
dump_annotsanddelete_annotsadd
EACH…JOB, documented underpdftl help pipelinedelete_bookmarksoperationadd_bookmarksoperationadd
{n}template toadd_text(andadd_bookmarks)
Changed
Improve error message when too many files are opened
[0.18.1] - 2026-05-29
Changed
When
--debugis passed,optimize_imagesnow outputs ocrmypdf debug messagesImprove error message for invalid page specs
Fixed
dump_annots: fix crash caused by named destinations which are not valid python dictionary keysUpdated API type stubs
Improve broken pipe handling: suppress tracebacks when piping to a pager
Improve test robustness (fixes #25)
[0.18.0] - 2026-05-05
Added
zoomoperationfastoutput option
Changed
pipx-specific installation instructions for missing dependencies
help output uses executable name correctly
update_bookmarkscan now read bookmark data from stdinadd_textsupports markdown-style hyperlinkssethandles common metadata, in both Info and XMPstamp,multistamp,background,multibackgroundaccept page specshelp: link to readthedocs page
Fixed
modify_layersnow hooks up print/view events (/AS dictionary)dump_layersreports /AS dictionary hookup as ‘active’ state
[0.17.0] - 2026-05-02
Added
modify_layersoperationdump_imagesoperationhighlightoperationstamp,background,multistamp,multibackground: option to add content in a new layerpage ranges accept
portraitandlandscapequalifiers
Changed
plain
renderarguments are now page specs, and we can output a multi-page render PDF
[0.16.0] - 2026-04-26
Added
delete_blankoperationdelete_imagesoperation
[0.15.0] - 2026-04-19
Added
setoperationimprove handling of unknown command line flags
suggest possible bug reporting on errors
CONTRIBUTING.md added
Fixed
work around a pyHanko bug affecting
dump_signatures
[0.14.0] - 2026-04-17
Added
dump_encryptionoperationdump_bookmarksoperationupdate_bookmarksoperation
Changed
montage: removedfitparameter
Fixed
pdftkcompatibility: default to all permissions deniedmontageandbookletbug handling pages with negative rotation fixedplaceandadd_textrotation bugs fixed and visual tests addedcroprotation bugs fixed and visual tests added
[0.13.0] - 2026-04-15
Added
page ranges accept
step<n>to step through a range in regular intervalsburstaccepts page specs or bookmark levels for chunk split points, and chunk size limits
Fixed
Completions updated
dump_textnow works in a pipeline, instead of crashingmontageandbookletnow handle page rotation betterpdftkcompatibility:burstnow outputs doc_data.txtdump_dataomits empty fields
Changed
Minor shell completion performance improvements
[0.12.1] - 2026-04-06
Fixed
Improved memory management
Fixed
chop,place, andbookletoperations to correctly calculate physical boundaries on pages with non-zero origins or non-standard/Rotateflags
Changed
Paper spec parser now falls back to landscape when missing an underscore (e.g.,
a4ltoa4_l).Pipeline execution now fails with an error if stage arguments cannot be parsed, rather than warning and proceeding.
Improved error messages for corrupted or invalid PDF files.
[0.12.0] - 2026-04-04
Added
clipoperation: enclose page content in a clipping rectangleAbsolute rectangle specifications for
cropandclipmontageoperation: impose multiple pages onto a grid layout, useful for contact sheets and N-up handouts. Supports configurable grid size, canvas, margins, gutters, and aspect ratio control (fit=contain|fill).bookletoperation: reorder and impose pages for duplex booklet printing. Automatically pads to a multiple of 4, supports signature-based chunking (sig=N), custom canvas size, and right-to-left binding (rtl=true).
[0.11.2] - 2026-03-22
Added
--versionnow displays core dependencies (pikepdf, libqpdf, python) and optional dependencies, along with a docs URL
Fixed
cropwith an invalid spec now prints a clean error message instead of a traceback--versionno longer crashes if pikepdf is not installed
[0.11.1] - 2026-02-09
Fixed
Bug fix:
rendershould no longer save a PDF to the pattern file
[0.11.0] - 2026-02-08
Added
Inline pipeline substitution using new
JOBandDONEkeywords, documented underpdftl help pipeline
Changed
Bump pikepdf required version to 10.3.0 to enable better pdftk compatibility
Compatibility:
Default to encrypt_aes128 encryption, the strongest which is pdftk compatible
pdftl now passes the vendored pdftk-java test suite
Shell completion improvements and optimization
Respect XDG environment variables for cache and plugin directory on non-Windows
Performance improvements, particularly in
catanddump_dataAPI now accepts
io.BytesIOas PDF inputs (as well aspathlib.Path, etc)
Fixed
Resolved issue with outlines (contents) when using
catwith named destinations
[0.10.0] - 2026-01-28
Added
Shell completion for bash, zsh and powershell
[0.9.2] - 2026-01-26
Changed
Performance improvements for
cat,shuffle, androtateoperations, especially regarding hyperlink handling.Invalid page arguments (e.g., requesting page 10 of a 5-page PDF) now return descriptive error messages instead of crashing.
Fixed
delete: Now properly removes page resources, resulting in smaller output files.generate_fdf: Fixed an issue where generation could fail or produce invalid output when handlingNonevalues or specific binary string formats.The option parser (used in
add_text, etc.) now correctly handles unbalanced quotes by raising a descriptive error, preventing data corruption.
Security
Replaced regex parsing with a state machine to prevent application hangs (ReDoS) when processing malformed quoted strings.
Now using
defusedxmlto avoidxml.etree.ElementTreevulnerabilities.Ensure passwords are redacted from all logging calls.
[0.9.1] - 2026-01-21
Fixed
README.md,NOTICE.mdandCHANGELOG.mdupdated/corrected
[0.9.0] - 2026-01-21
Added
mutate_contentoperation: mutate page content streams using a user-supplied Python scriptupdate_info: Support settingPdfID0to “RESET” to force valid ID regeneration on save.replacement_fontoption: change the font used for user text in forms
Changed
--versionincludes optional dependency versionsDocumentation updated for
dump_data,dump_annots, anddump_data_fieldsto better explain output formats and pdftk compatibility.
Fixed
Compatibility:
generate_fdffixed andreplacement_fontimplemented. Now passes the pdftk-java tests using bleeding edgepikepdf.startup performance improvements: lazy loading, and working around heavy Rich formatting for default help text
Pipeline: Read-only operations (like
dump_text) now implicitly pass the input PDF to the next stage, fixing chained commands (e.g.,dump_text --- cat).Handling of features with missing dependencies should be more consistent.
[0.8.0] - 2026-01-17
Added
Official support for Python 3.14
More comprehensive
vendor_tests/pdftk-javatest suite, frompdftk-java. This test suite only is licensed under the GPL 2, see NOTICE.md.no_encrypt_metadataoption: do not encrypt metadata. Only supported by AES encryption methods.COMPATIBILITY.md: compatibility notesdump_data_fieldsnow extracts tooltips (FieldNameAlt) and default values (FieldValueDefault).API: inputs now support pathlib.Path objects directly.
Changed
Encryption method now defaults to
encrypt_aes128ifuser_pworowner_pware passed, instead of not encrypting. This is more similar topdftk.attach_filesis now an operation, not an output option (pdftk compatibility)exit codes better aligned with pdftk’s exit codes
CLI: stricter argument parsing now raises
DuplicateArgumentErrorif keywords are repeated.
Fixed
catshould now properly handle forms.fill_formcompatibility fixesdump_data_fields_utf8: fixed crash/output issues.set_info: added validation for page label indices and better error handling for rotation/mediabox.
[0.7.0] - 2026-01-11
Added
automated
pdftkcompatibility testing using third party php test suite.drop_xfaoutput option to drop XFA form data (pdftk compatibility)renderoperation: rasterize pagesmove,update_info,update_info_utf8now accept instructions from a JSON “at-file” using@filename.jsonin place of CLI argumentsdump_datagives JSON output via thejsonkeywordextensibility: add custom operations by putting Python files in
~/.config/pdftl/operations(*nix) or%APPDATA%\pdftl\config(windows)
Fixed
bug in
add_pages.pywhen a page has an integer key-valuemore comprehensive handling of the five PDF page boxes for
dump_dataandupdate_infodrop_infoanddrop_xmpoutput options should now work as claimedflattenreimplemented for robustness
[0.6.0] - 2026-01-04
Added
moveoperation: move pages within a PDF fileplaceoperation: shift, scale and/or spin content within the page
Changed
Now handles compound page specifications like
1,3-4,7-end
Fixed
Improved API documentation generation
Removed
spinoperation. Seeplacefor this functionality.
[0.5.0] - 2026-01-03
Added
add_textfeatures:source metadata variables (
source_filename,source_page, etc)Bates stamping variable features, e.g.
DEF-{page+120:06d}produces DEF-000121, DEF-000122, …
insertoperation: insert blank pages
[0.4.1] - 2026-01-02
Fixed
Broken link in README.md
[0.4.0] - 2026-01-01
Added
API with fluent and functional interfaces
docs/api_tutorial.mdand auto-generated API docs
Changed
Renamed operation:
list_filesis nowdump_files
Fixed
Fixed bug preventing parsing of the page specification “right”
[0.3.1] - 2025-12-20
Fixed
README.mdcorrected, and “platform” badge added
[0.3.0] - 2025-12-20
Added
Get
helpby tag withpdftl help tag:<tagname>dump_signatures: view and validate PDF signaturesPDF signature output options:
sign_cert <file>Path to certificate PEMsign_field <name>Signature field name (default: Signature1)sign_key <file>Path to private key PEMsign_pass_env <var>Environment variable with sign_cert passphrasesign_pass_promptPrompt for sign_cert passphrase
dump_layers: dump PDF optional content groups (OCGs), a.k.a. “layers”
Fixed
performance improvements for
cat
[0.2.1] - 2025-12-17
Added
crop: addedfitandfit-groupartwork
extended NOTICE.md: acknowledge
pikepdf/qpdfandpypdfium2Windows testing
Fixed
performance improvements (lazy-loaded imports)
help tweaks: add sources for non-operations; more help topic aliases
[0.2.0] - 2025-12-13
Added
readthedocs integration and docs generation
Fixed
Improved help text
[0.1.1] - 2025-12-12
Added
codecov integration
PyPI publish integration
[0.1.0] - 2025-12-11
Added
Initial public release of
pdftl.Operations:
add_textAdd user-specified text strings to PDF pagesbackgroundUse a 1-page PDF as the background for each pageburstSplit a single PDF into individual page filescatConcatenate pages from input PDFs into a new PDFchopChop pages into multiple smaller piecescropCrop pagesdeleteDelete pages from an input PDFdelete_annotsDelete annotation infodump_annotsDump annotation infodump_dataMetadata, page and bookmark info (XML-escaped)dump_data_annotsDump annotation info in pdftk styledump_data_fieldsPrint PDF form field data with XML-style escapingdump_data_fields_utf8Print PDF form field data in UTF-8dump_data_utf8Metadata, page and bookmark info (in UTF-8)dump_destsPrint PDF named destinations data to the consoledump_textPrint PDF text data to the console or a filefill_formFill a PDF formfilterDo nothing. (The default if<operation>omitted.)generate_fdfGenerate an FDF file containing PDF form datainjectInject code at start or end of page content streamslist_filesList file attachmentsmodify_annotsModify properties of existing annotationsmultibackgroundUse multiple pages as backgroundsmultistampStamp multiple pages onto an input PDFnormalizeReformat page content streamsoptimize_imagesOptimize imagesreplaceRegex replacement on page content streamsrotateRotate pages in a PDFshuffleInterleave pages from multiple input PDFsspinSpin page content in a PDFstampStamp a 1-page PDF onto each page of an input PDFunpack_filesUnpack file attachmentsupdate_infoUpdate PDF metadataupdate_info_utf8Update PDF metadata from dump_data_utf8 instructions
Output options:
allow <perm>...Specify permissions for encrypted filesattach_files <file>… Attach files to the output PDFcompress(default) Compress output file streamsdrop_infoDiscard document-level info metadatadrop_xmpDiscard document-level XMP metadataencrypt_128bitUse 128 bit encryption (obsolete, maybe insecure)encrypt_40bitUse 40 bit encryption (obsolete, highly insecure)encrypt_aes128Use 128 bit AES encryption (maybe obsolete)encrypt_aes256Use 256 bit AES encryptionflattenFlatten all annotationskeep_final_idCopy final input PDF’s ID metadata to outputkeep_first_idCopy first input PDF’s ID metadata to outputlinearizeLinearize output file(s)need_appearancesSet a form rendering flag in the output PDFoutput <file>The output file path, or a template for ‘burst’owner_pw <pw>Set owner password and encrypt outputuncompressDisables compression of output file streamsuser_pw <pw>Set user password and encrypt outputverboseTurn on verbose output