Skip to content

Latest commit

 

History

History
1205 lines (708 loc) · 37.5 KB

File metadata and controls

1205 lines (708 loc) · 37.5 KB

Changelog

This changelog format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

Added

  • modify_layer_configs operation: add, update, delete, rename or promote to default the named layer configurations (/OCProperties /Configs); dump_layers now reports each configuration's locked layers and creator

  • resample_images now takes mono_dpi=<n> and threshold=<x>

  • subset_fonts takes keep_type1, leaving Type 1 fonts unconverted (Poppler draws a font converted to CFF with slightly different glyph edges)

  • shrink operation: makes a PDF smaller in one step, at lossless (default), balanced, strong or extreme, running pdftl's size-reduction passes in a benchmarked order; target=<size> picks the least lossy settings that fit

  • delete_tags operation: deletes the structure tree (tags); pages look the same, but the file is no longer accessible

  • compact_content operation: rewrites content streams in their shortest equivalent form

  • merge_font_subsets operation: merges the per-page subsets of one TrueType or Type1C (CFF) font into one font

  • deduplicate_xobjects operation: merges identical Form XObjects and link appearances

  • round_text_positions operation: writes text positions with fewer digits, moving no glyph more than a tolerance

  • photos_to_jpeg operation: re-encodes losslessly stored photographs as JPEG when the JPEG keeps their pixels and local structure (needs the photos-to-jpeg extra)

  • mrc_compress operation: splits scanned pages into a 1-bit text layer over low-resolution colour layers (needs the mrc-compress extra)

  • recompress, compress_xmp, drop_thumbnails and deflate zopfli output options: recompress streams at maximum level, compress XMP metadata, drop page thumbnails, use zopfli

  • render works in a pipeline, handing a later stage an image-only PDF

  • PDFTL_PROFILE_MEMORY=<stage>|all writes a memory profile of a CLI stage, and stages using more than PDFTL_MEMORY_THRESHOLD MB say so

  • Interactive password prompt support for encrypted PDFs (using PROMPT or A=PROMPT).

Security

  • Parsing an embedded Type 1 font program is now bounded in steps, operand stack and memory, so a crafted font can no longer hang pdftl or exhaust memory

  • Interpreting a glyph's charstring (reading CFF widths, converting Type 1 to CFF) is now bounded in work and subroutine nesting; a glyph with runaway subroutines is skipped rather than hanging or crashing the operation

Fixed

  • modify_layers: a specific target now overrides a conflicting action for all, so hide all show X reliably leaves X visible (it depended on Python's hash seed) and strip all keep X keeps X; conflicting actions on the same target are an error

  • dump_layers, modify_layers, modify_layer_configs and layer creation in overlay, barcode and redact no longer crash on malformed optional content: a lone dictionary where an array belongs (e.g. /Configs), junk array entries, or a non-dictionary /D or /Usage. dump_layers also accepts an /Intent given as a single name, as the spec allows

  • modify_layers strip/merge now also removes the layers from /Locked, /RBGroups and the /AS auto-state arrays

  • modify_layers strip/merge now handles content controlled by several layers through an optional content membership dictionary (OCMD) by its /P policy or /VE expression: such content was left untouched when marked, and an XObject was dropped (strip) or made permanent (merge) whenever any one of its layers was targeted

  • modify_layers strip/merge now applies to annotations: those on a stripped layer are deleted with their popups (form fields are also removed from the form), those on a merged layer become permanent, and layered content in appearance streams is stripped or merged like page content

  • render with no output writes page_1.png, page_2.png, ... as documented

  • optimize_images never makes an image bigger, also optimises inverted bitonal images (without changing a pixel), and at low no longer re-encodes JPEGs

  • resample_images, recolor_images, modify_images and render bound the memory they use, and running out of memory prints an error, not a traceback

  • simplify_vectors leaves alone a content stream it cannot fully parse, instead of dropping the unreadable parts

  • excise and redact no longer move surviving text: tidying the rewritten content stream dropped the line spacing a removed line's TD had set, moved T* ahead of a Tm, and treated a Tz restored by Q (or inherited by a Form XObject) as redundant

  • excise and redact keep a colour or font set just before a Q with no matching q

  • simplify_vectors no longer makes a content stream bigger (it keeps the original when the simplified one would not compress smaller), uses less memory, and skips content streams over the new max_stream_size (default 16MB) instead of exhausting memory on them

  • subset_fonts no longer changes how text renders: it keeps a TrueType or CFF font's original font-wide bounding box (a recomputed, tighter one altered Poppler's rendering)

  • subset_fonts keeps only the glyphs a PDF draws, and drops font tables PDF renderers never read (Office documents' fonts come out about half the size)

  • subset_fonts no longer gives a simple TrueType font widths keyed by Unicode (/LastChar 8217), which made MuPDF draw each line's text on top of itself

  • deduplicate_images and deduplicate_xobjects now merge copies that differ only in the obsolete /Name key, which ImageMagick sets per copy (a 36 MB photo PDF drops to 12 MB)

  • The oxipng step of save-time recompression now works on Windows, where oxipng could not open the temporary file

  • uncompress now really stores streams uncompressed: streams that were already Flate-compressed in the input used to be copied still compressed

  • Images decoded through the low-level fallback (used when pikepdf cannot extract an image, for example by recolor_images and export_images) now have their /Decode array applied, like every other image, instead of coming out inverted; encoded image data that happened to be longer than the raw pixel size is no longer misread as raw pixels

  • resample_images and modify_images skip images Pillow cannot represent (such as 5-ink DeviceN "hi-fi" images) instead of aborting the whole operation

  • Embedded Type 1 fonts with no eexec trailer (/Length3 0, as TeX-produced PDFs commonly have) now get their widths read and patched, rather than silently skipped

  • Embedded CFF fonts whose Top DICT omits charset (meaning the standard ISOAdobe charset) now get their widths read and patched; patching such a font, or a CID-keyed one missing its charset, no longer crashes

  • resample_images, modify_images, import_images and recolor_images no longer invert images with a non-default /Decode array (such as [1 0] bitonal scans, which came out as negatives)

  • Over-aggressive content-stream cleanup in excise and redaction fixed

  • unpause: raise error on unknown arguments instead of silently ignoring them

  • booklet and montage: validate and reject unknown configuration keys

  • set_info: allow setting PdfID0 metadata on PDFs lacking an existing trailer /ID array

  • delete_attachments: annotations of removed attachments are now removed too; minbytes/maxbytes compare the file size, not the compressed stream length

  • dump_tags: linter now checks every inline (direct) structure element, not just the first

  • simplify_vectors, excise: stroked rectangles no longer lose their fourth side; stroke merging no longer drops the closing edge of closed subpaths

  • set_info: an invalid PageLabelStart now skips the label, as its warning says, instead of writing /St anyway

  • dump_bookmarks, dump_data, toc and delete_bookmarks: destinations that target structure elements now resolve to the correct page when the page reference is on a later inline child

  • stamp_fields: inline widget kids after the first are no longer skipped

  • Documentation fixes:

    • Correct FORCE_COLORS to FORCE_COLOR
    • Correct input handle lifetime documentation
    • Clarify handle scoping for page ranges in cat (e.g., B2,4 vs B2,B4)
  • barcode: correct orientation on rotated pages

[0.29.0] - 2026-09-23

Added

  • delete_images, export_images, import_images, recolor_images, and resample_images now target inline images (BI/ID/EI content stream blocks), not just XObject images

  • dump_annots and delete_annots now support filtering by nested annotation properties using slash-separated key paths, both by value and existence

  • New output options:

    • drop_meta: discard all metadata
    • drop_vendor_extensions: discard private vendor/application data hung directly off the document catalog
    • drop_xmp_streams: discard all XMP metadata streams

Changed

  • usage now reports private vendor/application data hung directly off the document catalog in a new vendor_extension category, rather than as part of document_structure

  • modify_images: despeckle transformation now takes a size parameter

  • optimize_images accepts jbig2_group_size parameter to allow better compression

  • help now prioritizes nearby keywords/help topics in the same pipline stage rather than always choosing the first one

Fixed

  • dump_annots and delete_annots handle malformed arguments better

  • redact no longer leaves single-character regex matches (e.g. /e/) in the content stream; glyph deletion now uses real overlap/containment against the glyph's own box (excise's new glyph_overlap option) instead of only a center-point test

  • modify_images now finds images drawn through Form XObjects (common in scanned PDFs) instead of reporting that no images were found

  • optimize_images no longer creates an images directory next to the output file (or writes into an existing one); intermediate files now go in a temporary directory that is removed afterwards

  • optimize_images: the jpg_quality=<n> option is no longer silently ignored

  • dump_images and modify_images no longer crash on images whose /Filter is an empty array

  • server: oversized uploads are now rejected with a properly delivered 413 on Windows, instead of a connection error.

  • server: correct stale file logging in verbose mode

[0.28.1] - 2026-09-11

Changed

  • dump_bookmarks: friendlier launch, goto_remote, named_action keys for /Launch, /GoToR, and /Named outline actions (previously a raw ISO action dict)

  • excise outputs cleaner content streams

Fixed

  • dump_images PPI calculation fixed to take CTM into account

  • dump_images now shows image masks

  • dump_bookmarks/update_bookmarks: fix a crash on outline items with both /Dest and /A (keeps /Dest)

  • Bump minimum pikepdf version to fix AttributeError when reading page rotation during cat operations.

[0.28.0] - 2026-08-30

Added

  • prune_resources output option

  • deduplicate_icc_profiles operation

  • deduplicate_fonts operation

  • deduplicate_images operation

  • add_marks operation

  • usage operation

  • link_urls operation

  • Can now give chop an overlap

  • redact: attempt to verify redaction success when verify=true is passed

  • Custom CA certificate support added to dump_signatures via new trust_roots option, for deterministic trust chain verification.

  • Friendly error handling when input and output filenames agree

Changed

  • redact now redacts entire matches by default. Capturing groups (...) no longer narrow the target unless redact*-named groups are explicitly used (?P<redact_foo>...).

  • A warning is issued when saving will invalidate a signature

Fixed

  • excise and redact now remove annotations whose rectangle cannot be determined

  • replace, style_text, mutate_content, simplify_vectors, recolor_vectors, dump_streams and import_streams now also recurse into tiling Patterns, ExtGState soft-mask groups, and annotation appearance streams (previously only Form XObjects, or Forms+Patterns for the vector operations). Content painted through these mechanisms was silently skipped before; it is now processed like any other reachable content stream.

  • Resolved an issue where signing PDFs inside an active async event loop could fail.

[0.27.0] - 2026-08-26

Added

  • redact operation

  • excise operation

  • add image format selection to modify_images

  • add automatic bookmark detection to update_bookmarks

Fixed

  • subset_fonts: add subset tags to font names

  • add_text: improve system font matching

  • modify_images: improved posterize to make colors more faithful

  • dump_text: correctly handle type 3 fonts without /ToUnicode where possible

Changed

  • subset_fonts: improve Type 1 conversion performance

[0.26.0] - 2026-07-28

Added

  • style_text: use stroke=none to remove text stroke

  • subset_fonts operation

Changed

  • style_text: adding a stroke, by default, now uses the text fill color (if any) as the stroke color

  • render: API now supports explicit format=png|jpg|jpeg|pdf output selection. Image formats return a ZIP archive; format=pdf returns a single rasterized PDF. The CLI continues to determine output format from output.

  • server:

    • UI enhancements to builder interface
    • server pipeline now takes understands @A per-operation arguments, allowing use of stamp, for example

Fixed

  • dump_fonts and export_fonts now correctly scan annotation appearances for fonts

  • unpack_files now correctly returns a zip archive when called via the server

  • stamp, multistamp, background, multibackground: a PDF file argument to use as overlay/underlay is now required, per the documentation

  • optimize_images: better errors on missing ocrmypdf system dependencies

  • delete, 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 classic pdftk burst 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 a Pipe-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 via PDFTL_MAX_CONCURRENT_WORKERS). Previously, a burst of concurrent requests could spawn an unbounded number of worker processes.

[0.25.0] - 2026-07-14

Added

  • server operation

  • deskew operation

  • stamp_fields operation

  • embed_fonts operation

  • --args <file.yml> argument insertion

  • coalesce_strokes option added to simplify_vectors

Changed

  • sign_field no longer changes field appearances

  • style_text now adapts Tr (text rendering mode) better to user parameters

  • improved project version-finding heuristics

Fixed

  • dump_text: if output is passed directly, we now write the text, not the PDF.

  • render now initializes forms, so that they are properly rendered

  • dump_signatures now correctly reports pyhanko's valid/invalid status

[0.24.0] - 2026-07-07

Added

  • import_fonts operation

  • export_fonts operation

  • added upscale and adaptive_threshold to modify_images

  • import_images operation

  • export_images operation

  • import_streams operation

  • add_bookmarks: new options for bookmark specs: uri, launch, named, dest, color, bold, italic

  • dump_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 correctly

  • generate_fdf: optional status string in generated FDF output (ISO 32000-2 Table 246)

  • generate_fdf: multi-select choice field arrays now serialized correctly in FDF output

  • set operation: trapped field for document trapping status (True, False, or Unknown)

  • set operation: author now accepts comma-separated values for multiple authors

  • Bookmarks: non-GoTo actions (e.g. Launch, Named, JavaScript) are now preserved when copying or round-tripping outlines via dump_bookmarks / add_bookmarks

Changed

  • Improved verbose pipeline logging feedback loops

  • Suppressed noisy metadata field conversion logging strings in dump_data

  • dump_streams: output header format changed from Page <N> / Page <N> / XObject <name> (<obj>:<gen>) to Page <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 through import_streams

  • Improve 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 /XYZ coordinates were handled

  • Null coordinate values in /XYZ destinations now correctly preserved during rotation and scaling

  • fill_form: digital signature fields are now safely skipped instead of corrupted

  • Bookmarks: 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/Dests dictionaries are now resolved correctly

  • Structure 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

  • set operation: PDF 2.0 documents now correctly omit deprecated metadata fields from the /Info dictionary, per ISO 32000-2 §14.3.3

[0.23.0] - 2026-06-27

Added

  • delete_actions operation

  • dump_actions operation

  • dump_tags operation

  • tag operation

  • dump_streams operation

  • simplify_vectors operation

  • png_compression setting for the render operation

  • operations are now linked in the HTML docs

Changed

  • replace now recurses into XObjects by default

Fixed

  • delete_images global mode fixed to delete per-page images too

  • burst now keeps outlines and annotations, like cat

  • Prevent BrokenPipeError leaking out

[0.22.0] - 2026-06-20

Added

  • add_images operation

  • diff_text operation

  • dump_tables operation

  • modify_images operation

  • System font name and file path resolution for add_text

  • block repetition of page specs via copy<N>

  • multithreading for resample_images and recolor_images

Changed

  • page specs now tolerate whitespace (by stripping it before parsing)

  • dump_bookmarks: named destinations now resolved to page/view by default; pass no_resolve to skip

  • update_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_text bugs: (1) coalesce content streams (2) handle SC etc

  • add pattern support to recolor_vectors

Added

  • auto-paged help output on linux/mac

[0.21.0] - 2026-06-12

Fixed

  • render should no longer segfault when an unknown output file extension is passed

  • dump_annots now properly passing the PDF down the pipeline

  • Top margin percentage bug fixed in clip and crop

Changed

  • pipeline info added to verbose mode

  • make parentheses optional for crop, clip, delete_blank, delete_images, and style_text, in many cases

Added

  • repetitions in page specs viarep<N>

  • barcode operation

  • recolor_images operation

  • recolor_vectors operation

  • style_text operation

[0.20.0] - 2026-06-07

Added

  • Guess shell for --completion if it is not specified

  • add {count} as an alias for {n} in add_text and add_bookmarks

  • unpause operation

  • dump_colorspaces operation

  • delete_attachments operation

  • dump_fonts operation

  • create operation

  • resample_images operation

  • grep operation

Changed

  • Performance improvements in link/outline remapping

  • dump_files output format changed to JSON, with more detail

  • Several 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_annots and delete_annots

  • add EACH ... JOB, documented under pdftl help pipeline

  • delete_bookmarks operation

  • add_bookmarks operation

  • add {n} template to add_text (and add_bookmarks)

Changed

  • Improve error message when too many files are opened

[0.18.1] - 2026-05-29

Changed

  • When --debug is passed, optimize_images now outputs ocrmypdf debug messages

  • Improve error message for invalid page specs

Fixed

  • dump_annots: fix crash caused by named destinations which are not valid python dictionary keys

  • Updated 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

  • zoom operation

  • fast output option

Changed

  • pipx-specific installation instructions for missing dependencies

  • help output uses executable name correctly

  • update_bookmarks can now read bookmark data from stdin

  • add_text supports markdown-style hyperlinks

  • set handles common metadata, in both Info and XMP

  • stamp, multistamp, background, multibackground accept page specs

  • help: link to readthedocs page

Fixed

  • modify_layers now hooks up print/view events (/AS dictionary)

  • dump_layers reports /AS dictionary hookup as 'active' state

[0.17.0] - 2026-05-02

Added

  • modify_layers operation

  • dump_images operation

  • highlight operation

  • stamp, background, multistamp, multibackground: option to add content in a new layer

  • page ranges accept portrait and landscape qualifiers

Changed

  • plain render arguments are now page specs, and we can output a multi-page render PDF

[0.16.0] - 2026-04-26

Added

  • delete_blank operation

  • delete_images operation

[0.15.0] - 2026-04-19

Added

  • set operation

  • improve 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_encryption operation

  • dump_bookmarks operation

  • update_bookmarks operation

Changed

  • montage: removed fit parameter

Fixed

  • pdftk compatibility: default to all permissions denied

  • montage and booklet bug handling pages with negative rotation fixed

  • place and add_text rotation bugs fixed and visual tests added

  • crop rotation 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 intervals

  • burst accepts page specs or bookmark levels for chunk split points, and chunk size limits

Fixed

  • Completions updated

  • dump_text now works in a pipeline, instead of crashing

  • montage and booklet now handle page rotation better

  • pdftk compatibility:

    • burst now outputs doc_data.txt
    • dump_data omits empty fields

Changed

  • Minor shell completion performance improvements

[0.12.1] - 2026-04-06

Fixed

  • Improved memory management

  • Fixed chop, place, and booklet operations to correctly calculate physical boundaries on pages with non-zero origins or non-standard /Rotate flags

Changed

  • Paper spec parser now falls back to landscape when missing an underscore (e.g., a4l to a4_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

  • clip operation: enclose page content in a clipping rectangle

  • Absolute rectangle specifications for crop and clip

  • montage operation: 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).

  • booklet operation: 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

  • --version now displays core dependencies (pikepdf, libqpdf, python) and optional dependencies, along with a docs URL

Fixed

  • crop with an invalid spec now prints a clean error message instead of a traceback

  • --version no longer crashes if pikepdf is not installed

[0.11.1] - 2026-02-09

Fixed

  • Bug fix: render should no longer save a PDF to the pattern file

[0.11.0] - 2026-02-08

Added

  • Inline pipeline substitution using new JOB and DONE keywords, documented under pdftl 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 cat and dump_data

  • API now accepts io.BytesIO as PDF inputs (as well as pathlib.Path, etc)

Fixed

  • Resolved issue with outlines (contents) when using cat with 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, and rotate operations, 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 handling None values 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 defusedxml to avoid xml.etree.ElementTree vulnerabilities.

  • Ensure passwords are redacted from all logging calls.

[0.9.1] - 2026-01-21

Fixed

  • README.md, NOTICE.md and CHANGELOG.md updated/corrected

[0.9.0] - 2026-01-21

Added

  • mutate_content operation: mutate page content streams using a user-supplied Python script

  • update_info: Support setting PdfID0 to "RESET" to force valid ID regeneration on save.

  • replacement_font option: change the font used for user text in forms

Changed

  • --version includes optional dependency versions

  • Documentation updated for dump_data, dump_annots, and dump_data_fields to better explain output formats and pdftk compatibility.

Fixed

  • Compatibility: generate_fdf fixed and replacement_font implemented. Now passes the pdftk-java tests using bleeding edge pikepdf.

  • 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-java test suite, from pdftk-java. This test suite only is licensed under the GPL 2, see NOTICE.md.

  • no_encrypt_metadata option: do not encrypt metadata. Only supported by AES encryption methods.

  • COMPATIBILITY.md: compatibility notes

  • dump_data_fields now extracts tooltips (FieldNameAlt) and default values (FieldValueDefault).

  • API: inputs now support pathlib.Path objects directly.

Changed

  • Encryption method now defaults to encrypt_aes128 if user_pw or owner_pw are passed, instead of not encrypting. This is more similar to pdftk.

  • attach_files is now an operation, not an output option (pdftk compatibility)

  • exit codes better aligned with pdftk's exit codes

  • CLI: stricter argument parsing now raises DuplicateArgumentError if keywords are repeated.

Fixed

  • cat should now properly handle forms.

  • fill_form compatibility fixes

  • dump_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 pdftk compatibility testing using third party php test suite.

  • drop_xfa output option to drop XFA form data (pdftk compatibility)

  • render operation: rasterize pages

  • move, update_info, update_info_utf8 now accept instructions from a JSON "at-file" using @filename.json in place of CLI arguments

  • dump_data gives JSON output via the json keyword

  • extensibility: add custom operations by putting Python files in ~/.config/pdftl/operations (*nix) or %APPDATA%\pdftl\config (windows)

Fixed

  • bug in add_pages.py when a page has an integer key-value

  • more comprehensive handling of the five PDF page boxes for dump_data and update_info

  • drop_info and drop_xmp output options should now work as claimed

  • flatten reimplemented for robustness

[0.6.0] - 2026-01-04

Added

  • move operation: move pages within a PDF file

  • place operation: 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

  • spin operation. See place for this functionality.

[0.5.0] - 2026-01-03

Added

  • add_text features:

    • source metadata variables (source_filename, source_page, etc)

    • Bates stamping variable features, e.g. DEF-{page+120:06d} produces DEF-000121, DEF-000122, ...

  • insert operation: 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.md and auto-generated API docs

Changed

  • Renamed operation: list_files is now dump_files

Fixed

  • Fixed bug preventing parsing of the page specification "right"

[0.3.1] - 2025-12-20

Fixed

  • README.md corrected, and "platform" badge added

[0.3.0] - 2025-12-20

Added

  • Get help by tag with pdftl help tag:<tagname>

  • dump_signatures: view and validate PDF signatures

  • PDF signature output options:

    • sign_cert <file> Path to certificate PEM

    • sign_field <name> Signature field name (default: Signature1)

    • sign_key <file> Path to private key PEM

    • sign_pass_env <var> Environment variable with sign_cert passphrase

    • sign_pass_prompt Prompt 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: added fit and fit-group

  • artwork

  • extended NOTICE.md: acknowledge pikepdf/qpdf and pypdfium2

  • Windows 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_text Add user-specified text strings to PDF pages
    • background Use a 1-page PDF as the background for each page
    • burst Split a single PDF into individual page files
    • cat Concatenate pages from input PDFs into a new PDF
    • chop Chop pages into multiple smaller pieces
    • crop Crop pages
    • delete Delete pages from an input PDF
    • delete_annots Delete annotation info
    • dump_annots Dump annotation info
    • dump_data Metadata, page and bookmark info (XML-escaped)
    • dump_data_annots Dump annotation info in pdftk style
    • dump_data_fields Print PDF form field data with XML-style escaping
    • dump_data_fields_utf8 Print PDF form field data in UTF-8
    • dump_data_utf8 Metadata, page and bookmark info (in UTF-8)
    • dump_dests Print PDF named destinations data to the console
    • dump_text Print PDF text data to the console or a file
    • fill_form Fill a PDF form
    • filter Do nothing. (The default if <operation> omitted.)
    • generate_fdf Generate an FDF file containing PDF form data
    • inject Inject code at start or end of page content streams
    • list_files List file attachments
    • modify_annots Modify properties of existing annotations
    • multibackground Use multiple pages as backgrounds
    • multistamp Stamp multiple pages onto an input PDF
    • normalize Reformat page content streams
    • optimize_images Optimize images
    • replace Regex replacement on page content streams
    • rotate Rotate pages in a PDF
    • shuffle Interleave pages from multiple input PDFs
    • spin Spin page content in a PDF
    • stamp Stamp a 1-page PDF onto each page of an input PDF
    • unpack_files Unpack file attachments
    • update_info Update PDF metadata
    • update_info_utf8 Update PDF metadata from dump_data_utf8 instructions
  • Output options:
    • allow <perm>... Specify permissions for encrypted files
    • attach_files <file>... Attach files to the output PDF
    • compress (default) Compress output file streams
    • drop_info Discard document-level info metadata
    • drop_xmp Discard document-level XMP metadata
    • encrypt_128bit Use 128 bit encryption (obsolete, maybe insecure)
    • encrypt_40bit Use 40 bit encryption (obsolete, highly insecure)
    • encrypt_aes128 Use 128 bit AES encryption (maybe obsolete)
    • encrypt_aes256 Use 256 bit AES encryption
    • flatten Flatten all annotations
    • keep_final_id Copy final input PDF's ID metadata to output
    • keep_first_id Copy first input PDF's ID metadata to output
    • linearize Linearize output file(s)
    • need_appearances Set a form rendering flag in the output PDF
    • output <file> The output file path, or a template for 'burst'
    • owner_pw <pw> Set owner password and encrypt output
    • uncompress Disables compression of output file streams
    • user_pw <pw> Set user password and encrypt output
    • verbose Turn on verbose output