A set of helpful PDF utilities — compress, split/merge, convert to Word or JPG, extract images and decrypt — available as command-line scripts and a small Flask API.
The heavy lifting is done by PyMuPDF, PyPDF2, pdf2docx and the Ghostscript command-line tool. Most functionality is bundled into a single multi-action CLI (pdf_util.py); single-purpose scripts and an HTTP API (app.py) expose the same operations.
- Compress PDFs via Ghostscript with five quality presets (
default,prepress,printer,ebook,screen) - Split PDFs: one file per page, custom page ranges (e.g.
1-3,7), fixed-size chunks, or merge selected ranges into a single PDF; multi-file output is delivered as a ZIP - Convert PDF → Word (
.docx) with pdf2docx - Render PDF pages → JPG at a chosen DPI, zipped
- Extract embedded images from a PDF (CMYK images converted to RGB), zipped
- Decrypt password-protected PDFs
- Flask API exposing
POST /compress_pdfandPOST /split_pdf, plus a samplerequestsclient
- Python 3
- Ghostscript installed and on
PATH(gs,gswin32orgswin64) — required for all compression features; the scripts invoke the executable directly (theghostscriptpip package in requirements.txt is not what does the work) - Python packages:
pip install -r requirements.txt
pip install pdf2docx # imported by pdf_to_word.py / pdf_util.py but not listed in requirements.txtgit clone https://github.com/mkamranr/pdf-helper.git
cd pdf-helper
pip install -r requirements.txt
pip install pdf2docx
mkdir PDFFiles # working directory expected by the Flask app and sample client# PDF -> Word
python pdf_util.py -a pdf_to_word -i input.pdf -o output.docx
# Split: one PDF per page, zipped
python pdf_util.py -a split_pdf -i input.pdf -o pages.zip
# Split: specific pages/ranges, zipped
python pdf_util.py -a split_pdf -i input.pdf -p "1-3,7" -o parts.zip
# Merge the selected ranges into ONE output PDF instead of a ZIP
python pdf_util.py -a split_pdf -i input.pdf -p "1-3,7" -m 1 -o merged.pdf
# Split into fixed 10-page chunks, zipped
python pdf_util.py -a split_pdf -i input.pdf -f 10 -o chunks.zip
# Render every page to JPG at 150 DPI, zipped
python pdf_util.py -a convert_pdf_to_jpg -i input.pdf -o images.zip -q 150
# Extract embedded images, zipped
python pdf_util.py -a extract_images_from_pdf -i input.pdf -o extracted_images.zip
# Decrypt an encrypted PDF
python pdf_util.py -a decrypt_pdf -i locked.pdf -s mypassword -o decrypted_file.pdf| Flag | Meaning |
|---|---|
-a, --action |
pdf_to_word, split_pdf, convert_pdf_to_jpg, extract_images_from_pdf, decrypt_pdf |
-i, --input |
input PDF path |
-o, --out |
output path (defaults: converted.docx, splitted.zip, images.zip, extracted_images.zip, decrypted_file.pdf) |
-p, --pages |
page ranges, e.g. "1-3,7"; empty = every page separately |
-m, --merge |
1 = merge selected ranges into a single PDF (only when -f is not used) |
-f, --fixedrange |
split into chunks of N pages |
-s, --password |
password for decrypt_pdf |
-q, --quality |
DPI for convert_pdf_to_jpg (default 150) |
# Ghostscript compression: -c 0=default 1=prepress 2=printer 3=ebook 4=screen
# (defaults: level 2 "printer", output temp.pdf)
python pdf_compressor.py -i input.pdf -o compressed.pdf -c 3
# Same split engine as pdf_util.py (-p / -m / -f as above)
python pdf_split.py -i input.pdf -p "1-3,7" -o parts.zip
# PDF -> DOCX (default output converted.docx)
python pdf_to_word.py -i input.pdf -o output.docx
# Older positional-argument script
python split_pdf.py split input.pdf pages.zip
python split_pdf.py compress input.pdf compressed.pdf 50python app.py # serves on http://localhost:5000 in debug modePOST /compress_pdf— multipart fieldfileplus form fieldcompression_level(0=default,1=prepress,2=printer,3=ebook,4=screen); returns the compressed PDFPOST /split_pdf— multipart fieldfile; returns a ZIP containing one PDF per page
curl -F "file=@input.pdf" -F "compression_level=4" http://localhost:5000/compress_pdf -o compressed.pdf
curl -F "file=@input.pdf" http://localhost:5000/split_pdf -o pages.zipmain.py is a sample client: edit api_url and file_path at the bottom (as shipped it posts PDFFiles/Configuration.pdf to /split_pdf and saves the returned ZIP under PDFFiles/), then run python main.py.
Splitting uses PyMuPDF (fitz): pages are copied with insert_pdf into per-range documents written to a temp folder, then zipped — or appended into one merged document when -m 1 is set. Compression shells out to Ghostscript's pdfwrite device with -dPDFSETTINGS presets and reports the size reduction. Word conversion delegates to pdf2docx's Converter. JPG rendering rasterises each page with page.get_pixmap using a DPI-derived zoom matrix; image extraction walks each page's image XObjects and saves them as PNG (CMYK converted to RGB first). Decryption uses PyPDF2's PdfReader.decrypt and rewrites all pages. The Flask app wraps Ghostscript compression and a PyPDF2 per-page split behind HTTP endpoints, storing intermediate files in PDFFiles/.
| File | Purpose |
|---|---|
pdf_util.py |
All-in-one CLI: to-Word, split/merge, to-JPG, image extraction, decryption |
pdf_compressor.py |
Ghostscript compression CLI (levels 0–4) |
pdf_split.py |
Split/merge CLI (same engine as pdf_util.py) |
pdf_to_word.py |
PDF → DOCX CLI |
split_pdf.py |
Older positional-args split/compress script |
app.py |
Flask API: /compress_pdf, /split_pdf (port 5000) |
main.py |
Sample requests client for the API |
requirements.txt |
Pinned dependencies |
LICENSE |
GPL-3.0 |
app.pyandpdf_compressor.pyusesubprocess.STARTUPINFO, which only exists on Windows — as written, those two compression paths fail on macOS/Linux (split_pdf.py's Ghostscript call is plain and cross-platform;pdf_util.pyhas no compress action).- The Flask app expects a
PDFFiles/directory to exist next toapp.py, runs withdebug=True, and does not clean up saved uploads. pdf_util.pyaccepts-c/--compressbut implements no compression action.split_pdf.py'scompressaction reads an image-quality argument but always calls Ghostscript with the fixedebookpreset.requirements.txtomitspdf2docxand includes packaging extras (pyinstaller,pywin32-ctypes) not used by the scripts at runtime.
This project is licensed under the GNU General Public License v3.0 — see LICENSE.