pdf-diff-sbs
Compare two PDFs and generate a searchable side-by-side (SBS) PDF, with removed words highlighted in red and added words highlighted in green. Original pages retain their vector content and selectable text.
Install from GitHub
Requires Python 3.10+ and Git. Use a virtual environment:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install "git+https://github.com/matplo/pdf-diff-sbs.git"
On Windows, activate with .venv\Scripts\activate instead.
Install a specific version with:
python -m pip install "git+https://github.com/matplo/pdf-diff-sbs.git@v0.1.0"
PyMuPDF is installed automatically. No Poppler installation is required. The package
is prepared for future PyPI distribution; it has not been published to PyPI.
Once the first PyPI release is published, install it with python -m pip install pdf-diff-sbs.
Usage
pdf-diff-sbs old.pdf new.pdf -o comparison.pdf
pdf-diff-sbs --list
pdf-diff-sbs --list --directory /path/to/documents
pdf-diff-sbs --version
With no positional arguments, the tool selects the sole matching PDF filename in
v0/ and the current directory. Use --directory to choose another directory for
this automatic selection. Explicit OLD, NEW, and output paths are always relative
to the current working directory.
The default output is output/pdf/diff.pdf. Existing files are protected; use another
output filename for a repeat comparison. Recursive scanning skips .venv, .git,
output, tmp, and __pycache__ directories.
You can also run python -m pdf_diff_sbs with the same arguments.
Python API
from pdf_diff_sbs import compare, scan
pdfs = scan("documents")
result = compare("old.pdf", "new.pdf", "comparison.pdf")
print(result.pages, result.removed_words, result.added_words)
Paths can be strings or pathlib.Path objects. compare returns a
ComparisonResult with output, pages, removed_words, and added_words.
Invalid inputs raise exceptions; neither input nor existing output files are overwritten.
What the comparison means
- Text is compared across the whole document to reduce differences caused by wrapping and page shifts. Source pages are displayed by page number, so matching text may appear on different output pages after reflow.
- Whitespace, common ligature encoding differences, and standalone page numbers near page edges are ignored. Repeated marginal lines identical in both PDFs are ignored.
- A line-ending hyphen followed by lowercase text is treated as a split word. This heuristic can also join genuine compound words. Punctuation and case changes count.
- Formatting, images, signatures, and graphical changes are not compared. Scanned PDFs need OCR first; documents with no selectable text are rejected. Image-only pages in mixed documents are displayed, but their changes are not detected.
- Reading order depends on PDF extraction; complex columns may cause extra differences. Source annotations and form widgets are not imported into the comparison.
Development
python -m pip install -e ".[dev]"
python -m pytest
python -m build
python -m twine check dist/*
Tests generate small synthetic PDFs in temporary directories. The repository contains the package and tests; input documents and generated comparison PDFs are excluded.
Releases
See RELEASING.md for the PyPI Trusted Publisher configuration and tag-triggered release steps. A manual run of the publishing workflow validates the release build without uploading to PyPI.
Metadata
Release files for pdf-diff-sbs 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pdf_diff_sbs-0.1.1.tar.gz | 8.4 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pdf_diff_sbs-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.2 kB
Release files / pdf_diff_sbs-0.1.1.tar.gz
| Download URL | pdf_diff_sbs-0.1.1.tar.gz |
|---|---|
| Size | 8.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
beb3e1e4f4d421b09f3b13488703d8a0f010d9844caf3a9f75aed99afe274800
|
|
BLAKE2b-256 checksum How to use checksums |
a7ece45c1fe5b91714b296faeeefdc54099a230a37d36db36c77e42093433745
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.
Transparency logRelease files / pdf_diff_sbs-0.1.1-py3-none-any.whl
| Download URL | pdf_diff_sbs-0.1.1-py3-none-any.whl |
|---|---|
| Size | 7.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ccf6fe0d8566cddfbb96e5f9e76d76b5821b9cc1d7cb934a3b73e331b702edba
|
|
BLAKE2b-256 checksum How to use checksums |
2f7348ef13e121ff4f9c9c7d5787e91e29fa01e1a0f90f7fa8ce8f20a2d7cf61
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.
Transparency logSecurity for pdf-diff-sbs 0.1.1
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for pdf_diff_sbs-0.1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.
Transparency logA 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.