PDF Toolkit: split, merge, extract pages, tables, OCR, redact
Pricing
from $2.00 / 1,000 processed pages
PDF Toolkit: split, merge, extract pages, tables, OCR, redact
One Actor for the common PDF jobs: extract or split pages, merge, rotate, render pages to images, pull text, extract tables as JSON, watermark, redact terms, compress and fill forms. Structured output, per-page pricing.
Pricing
from $2.00 / 1,000 processed pages
Rating
0.0
(0)
Developer
praestat media
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
PDF Toolkit — extract pages, split, merge, tables, redact, compress
One Apify Actor for the everyday PDF jobs. No Ghostscript, no external service: everything runs inside the actor container, results come back as structured dataset items plus downloadable files in the key-value store.
Operations
operation | What it does | Output |
|---|---|---|
extract_pages | Keep only the pages you select (1-3,7,10-, negative = from the end) | new PDF + page list |
split | Split into single pages or every N pages | one PDF per part |
merge | Merge several PDFs in the given order | one PDF |
rotate | Rotate selected pages by 90/180/270° | new PDF |
text | Text per page (fast, no layout reconstruction) | text + char count per page |
metadata | Page count, document info, encryption flag | JSON |
extract_tables | Tables via pdfplumber, returned as row/column JSON | tables.json |
to_images | Render pages to PNG/JPEG at a chosen DPI | image files |
watermark | Diagonal text watermark on selected pages | new PDF |
redact | Remove terms from the text layer and black out the area | new PDF + hit list |
compress | Strip duplicates, deflate streams, re-encode images as JPEG | smaller PDF + savings |
fill_form | Fill AcroForm fields by name | new PDF + filled/missing field list |
markdown | Convert pages to LLM-ready Markdown: headings, lists, tables, page anchors | document.md |
ocr | Recognise text and word boxes on scanned pages — Tesseract runs inside the container, no external OCR service | ocr.json with text, word boxes and confidence per page |
Input example
{"operation": "extract_pages","pdfUrls": ["https://example.com/invoice.pdf"],"pages": "1-2,5"}
{"operation": "redact","pdfUrls": ["https://example.com/contract.pdf"],"redactTerms": ["Max Mustermann", "AT61 1904 3002 3457 3201"],"pages": ""}
{"operation": "extract_tables","pdfUrls": ["https://example.com/report.pdf"],"pages": "2-6"}
{"operation": "markdown","pdfUrls": ["https://example.com/report.pdf"],"pages": ""}
{"operation": "ocr","pdfUrls": ["https://example.com/scan.pdf"],"pages": "1-3","ocrLanguage": "eng+deu","ocrDpi": 300}
Output
Every run pushes one item per operation to the dataset:
{"operation": "extract_pages","pages": [1, 2, 5],"pageCount": 3,"file": "out/extracted.pdf"}
Generated files are also stored in the default key-value store (OUTPUT records plus the binary
files), so a follow-up actor or your own script can pick them up directly.
Pricing (pay per event)
| Event | When | Price |
|---|---|---|
apify-actor-start | once per run and per GB of memory (2 GB default) | $0.005 |
page-processed | per page in the result | $0.002 |
image-rendered | per rendered page image | $0.001 |
table-extracted | per table found | $0.02 |
page-redacted | per page that contained a match | $0.01 |
form-filled | per filled form field | $0.002 |
page-ocred | per page run through OCR (replaces page-processed for this operation) | $0.01 |
A 10-page extract therefore costs about $0.03; a 3-table report extraction about $0.08.
OCR is the expensive operation: recognition needs roughly a second of CPU per page, so an OCR page
is charged at $0.01 and page-processed is not charged on top of it.
The start event is charged once per GB of memory, so the 2 GB default costs $0.01. The code charges the remaining events.
Limits and honest notes
textreads the PDF text layer. Scanned pages have none — useocrfor those instead.markdownis a heuristic, not a layout engine: headings come from font size, lists from bullet characters, tables are appended per page as pipe tables, and the reading order follows the position on the page. Multi-column layouts will come out interleaved — check the output before feeding it into a pipeline.ocruses Tesseract with English and German models. It is accurate on clean scans and printed text, weaker on handwriting, unusual fonts and rotated pages. The confidence per word is in the output so you can see where it struggled instead of trusting a single number.- OCR is CPU work: expect roughly 1–2 seconds per page at 200 DPI on a 2 GB run. For a few hundred
pages, raise the memory setting — the
apify-actor-startprice scales with it. - Which DPI?
ocrDpidefaults to 200, and that is measured, not guessed: on a clean two-page scan, 150 / 200 / 300 DPI produced the same text in 17.6 s / 23.6 s / 31.9 s. Higher resolution does not improve clean input, it only costs runtime. Use 300 when the source is noisy, faxed or a poor photocopy — there the extra pixels do help. redactremoves the matched text from the content stream and paints a filled box. It is not a compliance-grade redaction suite: hidden metadata, annotations or attached files are not scrubbed.compressre-encodes embedded images; scanned PDFs shrink a lot, text PDFs only slightly.- Encrypted PDFs are rejected with a clear error (no password support yet).
- Max input size is limited by the Apify memory setting of the run.
Reporting a problem
Please use the Issues tab on the Actor page instead of email. The report then sits with the right Actor, together with the input and the run it came from — usually exactly what is missing to reproduce it. Issues are read and answered there.
What happens to your data
Input files and results stay in your run's storage on Apify. Apify keeps the ten most recent runs of an Actor indefinitely; older runs and their default storages are deleted under the platform's retention rules. I do not export or archive your files anywhere else, and the Actor never sends them to a third-party service.
Local development
python -m venv .venv && .venv/bin/pip install -r requirements.txt.venv/bin/python -m pytest tests -qecho '{"operation":"extract_pages","pdfUrls":["/path/file.pdf"],"pages":"1-2"}' > /tmp/in.json.venv/bin/python -m src --input /tmp/in.json --outdir out --push
The CLI path is the same code as the actor run, so what passes locally behaves identically on Apify.