Skip to main content

A-PDF

A-PDF is a fast, command-line tool designed to replace Unicode and Hex text directly within PDF content streams.

Features

  • Direct Stream Replacement: Modifies the underlying PDF streams directly for fast and precise text replacement.
  • Unicode & Hex Support: Text is automatically encoded to the document's fonts.
  • Layout Preservation: Only the matched text is rewritten, so TJ spacing, justified gaps and column gaps survive (width compensation can be disabled).
  • Regex & Rules Files: Regex with groups (\1), ignore-case, whole-word, and rules from .json / .csv / .tsv.
  • RTL Support: --rtl reverses each OLD string to match the left-to-right glyph order that RTL producers (e.g. Google Docs / Skia) write into content streams.
  • Dry Run, Reports & Verify: Preview every match, get a JSON report, and re-check the output.
  • Safe Output: Atomic write with integrity check before saving. Output is always saved as Input-Edited.pdf, keeping the original intact.
  • Wider Coverage: Form XObjects, annotations/form fields, split text, multi-part /Contents.
  • Batch, Encrypted & Damaged PDFs: Whole folders in parallel, --password, automatic repair.
  • Strict Mode / Fallback Font / Page Selection: As before.

Installation

uv add apdf # or As a tool: uv tool install apdf
uv run apdf --help

Or with pip:

pip install apdf              # core
pip install "apdf[crypto]"    # + AES-encrypted PDF support (--password)

Usage As Library

from apdf import Replacement, replace_pdf_text_detailed

rep = replace_pdf_text_detailed(
    "Test1.pdf",
    "Test1-Edited.pdf",
    [
        Replacement("Old Text", "New Text"),
        Replacement(r"INV-(\d+)", r"BILL-\1", regex=True),
        Replacement("draft", "final", ignore_case=True, whole_word=True),
    ],  # a plain {"Old": "New"} dict still works

    # Optional parameters:
    # pages={2, 3, 4},      # one-based; int, set or range; None = all pages
    # dry_run=True,         # analyse only, write nothing (output_pdf may be None)
    # verify=True,          # re-read the output and confirm the replacements
    # password="secret",    # encrypted input
    # strict=True,
    # fallback_font="FONT.ttf", font_fallback=True,
)

print("Replacements:", rep.replacements)
print("Missing:", rep.missing)
print("Encoding failures:", rep.encoding_failures)
print("Warnings:", rep.warnings)
for m in rep.matches:                 # every occurrence with context
    print(m.page, m.before, "->", m.after)
# rep.to_dict() is JSON-serialisable

The library is silent; attach a handler to the apdf logger for progress.

Usage As CLI Tool

apdf [options] input               # output saved as input-Edited.pdf
apdf --batch FILES/DIRS/GLOBS --out-dir DIR [options]

Examples

# Basic / multiple replacements (saves as input-Edited.pdf)
apdf input.pdf -r "OldText=NewText" -r "2023=2024"

# Preview first (nothing is written)
apdf input.pdf -n -r "foo=bar"

# Regex with a group, case-insensitive, verified, with a JSON report
apdf input.pdf -x -i -r 'INV-(\d+)=BILL-\1' --verify --report report.json

# Arabic / RTL PDF (Google Docs, Skia) — glyphs are stored LTR in the stream
apdf input.pdf -r "جين=جولي" --rtl -i -ff ReadexPro.ttf

# Rules from a file
apdf input.pdf --rules rules.json

# A whole folder, 4 processes, originals untouched (saves as *-Edited.pdf)
apdf --batch ./pdfs --out-dir ./edited --rules rules.json -j 4

Rules file

rules.json (per-rule options; backslashes doubled in JSON):

[
  {"old": "Abodx\\d",   "new": "Tester",   "regex": true, "ignore_case": true},
  {"old": "INV-(\\d+)", "new": "BILL-\\1", "regex": true},
  {"old": "12.50",      "new": "99.00"}
]

A plain {"old": "new"} object also works. rules.csv / .tsv:

old,new,regex
Abodx9,Tester,
INV-(\d+),BILL-\1,regex

Arguments

  • input: Source PDF. Output is saved as input-Edited.pdf in the same directory (the original is always kept).
  • -r OLD=NEW: Replacement pair, repeatable. Use \= for a literal = in OLD.
  • --rules FILE: Load rules from .json, .csv or .tsv, repeatable.
  • -x / -i / -w: Regex / ignore case / whole word, applied to all rules.
  • --rtl: Reverse both OLD and NEW strings before matching/replacing — for RTL PDFs (Arabic, Hebrew) where a producer like Google Docs writes glyphs left-to-right in the content stream.
  • -p 2, -p 2,3,4, -p 1-5: Pages to edit (default: all).
  • -n, --dry-run: Analyse and list every match, write nothing.
  • --verify: Re-read the output and check the replacements are present.
  • --report FILE, --json: JSON report to a file / on stdout. -v lists matches, -q is quiet.
  • --password PW: Encrypted PDF (output is re-encrypted with the same password).
  • --no-annotations: Skip annotation / form-field appearance streams.
  • --batch, --out-dir DIR, --suffix TEXT, -j N: Batch mode — inputs are never overwritten (default suffix is -Edited).
  • --extract: Print the text apdf sees on the selected pages.
  • -nopa: Do not compensate TJ widths after replacements.
  • -s: Strict. Fail if text is missing, cannot be encoded, or verification fails.
  • -ff FONT.ttf / -no-ff: Fallback font to embed for missing glyphs / refuse missing glyphs.

All rules are matched against the original text at once, so A=B plus B=C never turns A into C. Overlaps resolve leftmost, then longest.

Limitations

  • Digital signatures are invalidated by any edit (apdf warns).
  • Edits using a fallback font look different from the surrounding text.
  • Text stored as images or outlines can't be found; Type3 and variable-width CJK fonts are untested.
  • Longer text can overflow its box (no re-wrapping).

Metadata

Release files for apdf 2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for apdf 2.0
File Size Uploaded Provenance
apdf-2.0.tar.gz 42.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for apdf 2.0
File Interpreter ABI Platform
apdf-2.0-py3-none-any.whl Python 3 none any Details

Total release size: 91.5 kB

Release files / apdf-2.0.tar.gz

Download URL apdf-2.0.tar.gz
Size 42.5 kB
Tags Source
SHA-256 checksum
How to use checksums
425526417a8a0c57cc11bb598d915625ead8982fb2c47cb069da75fa37916be7
BLAKE2b-256 checksum
How to use checksums
b1c2054a0f7e107ee5aa39f9501100b0e86d13db16836191f1b69bb826d64258
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / apdf-2.0-py3-none-any.whl

Download URL apdf-2.0-py3-none-any.whl
Size 49.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ccaf27621e3f398a4cadd7cf477bb1f5cbf60c20a3f44d4116bb33dbc05ecf1d
BLAKE2b-256 checksum
How to use checksums
591a522ff3840233414253307ec652bfd9cd976b6dbafc16062ab46ac7897f44
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for apdf 2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page