PDF Tools (Merge / Split / Compress / OCR / Watermark)
Pricing
from $1.40 / 1,000 results
PDF Tools (Merge / Split / Compress / OCR / Watermark)
All-in-one PDF processor: merge multiple PDFs, split by page ranges, compress file size, extract text, OCR scanned documents (Tesseract), add text watermarks, rotate pages, and read metadata. Accepts PDF URLs or Key-Value Store keys.
Pricing
from $1.40 / 1,000 results
Rating
0.0
(0)
Developer
Alex O
Maintained by CommunityActor stats
0
Bookmarked
6
Total users
2
Monthly active users
3 days ago
Last modified
Categories
Share
PDF Tools
Process PDF batches on Apify: merge, split, compress, extract text, OCR scans, watermark, rotate and inspect metadata. Accepts public PDF URLs or existing Key-Value Store records, including password-protected documents.
Every generated file has a download URL, byte count and SHA-256 checksum. Text extraction includes per-page JSON. Failed inputs are identified individually, and the SUMMARY record reports the outcome of the entire batch.
Quick start
- Select an operation in the Actor input form.
- Add direct PDF URLs or provide
pdfKeysand an existinginputKeyValueStoreId. - Start the run. Open the dataset for results and download links; open the default Key-Value Store for files and
SUMMARY.
Example for invoices containing both digital and scanned pages:
{"operation": "extractText","pdfUrls": ["https://example.com/invoice.pdf"],"autoOcr": true,"ocrLanguages": "eng+deu"}
Replace example URLs with your own direct-download links. Signed download links and endpoints without a .pdf suffix are supported; the response must contain an actual PDF. Public HTTP(S) destinations are supported. Localhost, private network addresses, embedded URL credentials and HTTPS-to-HTTP redirects are rejected.
Operations
| Operation | Result | Details |
|---|---|---|
merge | One PDF | Preserves source order and imports bookmarks. Every source must succeed; never silently produces an incomplete document. |
split | PDFs and optional ZIP | Processes every input PDF. Split into individual pages or semicolon-separated groups. |
compress | Lossless stream optimization; preserves metadata by default. No image downsampling. | |
extractText | TXT and JSON | Extracts embedded text. Optional autoOcr processes only pages without embedded text. |
ocr | TXT and JSON | Runs Tesseract on every selected page, with page numbers, extraction method and individual errors. |
watermark | Centered or tiled Unicode text, adjustable opacity and angle, optionally restricted to selected pages. | |
rotate | Rotates selected pages by 90, 180 or 270 degrees. | |
metadata | Dataset record | Document metadata, dates, encryption flag, form-field count, page sizes and rotation. |
pageCount | Dataset record | Page count and exact input byte size. |
Rotation and watermarking preserve the document structure, including ordinary AcroForms, metadata and bookmarks. Merge prefixes form-field names with document_1, document_2, etc. to avoid collisions. Split imports relevant bookmarks and form fields using pypdf. Complex XFA forms and arbitrary damaged PDF structures are not guaranteed to survive rewriting.
Inputs
Sources and page selection
| Field | Default | Meaning |
|---|---|---|
operation | pageCount | One of the operations above. |
pdfUrls | — | Array of public download URLs. |
pdfKeys | — | Array of raw PDF record keys. |
inputKeyValueStoreId | Run default store | Existing input store; the run must have read access. Outputs always go to the run default store. |
pdfPassword | Empty | Shared password for encrypted inputs; marked secret in the input form. |
pageRanges | All pages | One-based selection such as 1-3,5. For split, 1-2;3;4-5 creates three PDFs. |
outputFileName | Automatic | Optional name using letters, digits, dots, hyphens and underscores, maximum 100 characters. |
API aliases pdfUrl, startUrls (including { "url": "..." } objects) and pdfKey remain supported. Newlines can separate sources in a string; commas are retained because they can be part of signed URLs. Sources are processed in URL-field order followed by key-field order. Intentional duplicates are retained.
Invalid, reversed or out-of-bounds page ranges fail explicitly. Within a group, repeated pages are deduplicated and returned in document order. pageRanges applies to split, text extraction, OCR, rotation and watermarking. It does not reorder pages.
For cloud runs, upload PDFs to an existing store first and set inputKeyValueStoreId; a new run's default store generally has no pre-uploaded PDF records.
Text and OCR
| Field | Default | Meaning |
|---|---|---|
autoOcr | false | OCR fallback for pages with no embedded text during extractText. |
ocrLanguages | eng | eng, deu, fra, spa, ita, por; combine with +. |
ocrDpi | 200 | 72–400 DPI. Rendering caps the long edge at 4000 pixels. |
ocrPageTimeoutSeconds | 60 | 5–300 seconds for each page render and each OCR subprocess. |
maxOcrPages | 100 | Maximum OCR pages per input, including fallback; allowed range 1–500. |
includeTextInDataset | true | Include page text in dataset items. TXT/JSON retain the full text regardless. |
Pages use one-based numbering and identify method as embedded or ocr. An OCR page failure produces PARTIAL or FAILED, never an unconditional success. Pages with no recognized text are listed in emptyPages.
The Actor exports OCR text, not a searchable PDF with an invisible text layer. Native extraction does not promise table reconstruction or original multi-column reading order. OCR quality depends on scan quality; autoOcr does not replace an existing but inaccurate text layer.
PDF editing
| Field | Default | Meaning |
|---|---|---|
compressionLevel | medium | low: compress streams; medium: also recompress Flate streams; high: additionally normalize content. |
stripMetadata | false | Remove document Info and XMP metadata during compression. |
zipOutput | false | Additional ZIP per split input, including a single output chunk. |
rotateAngle | "90" | "90", "180", "270"; numeric API values also accepted. |
watermarkText | CONFIDENTIAL | Up to 500 characters; Latin, Greek and Cyrillic font coverage. Unsupported glyphs fail explicitly. |
watermarkOpacity | 0.15 | 0–1; zero is respected. |
watermarkFontSize | 60 | 10–200 points. Centered text shrinks to fit if needed. |
watermarkAngle | 45 | 0–360 degrees, relative to the displayed page. |
watermarkTiled | false | Repeat watermark text across the page. |
Without metadata stripping, compression returns the original when optimization would increase its size. Explicit metadata removal takes priority over file size and may produce a larger file. Already optimized image-heavy PDFs may not shrink. Compression does not convert to PDF/A or sanitize active PDF content.
Rewritten PDFs are unencrypted. Compression can retain an unchanged encrypted original when it is smaller. Rewriting digitally signed PDFs invalidates their signatures; affected operations report a warning.
Resource controls
| Field | Default | Allowed range |
|---|---|---|
maxConcurrency | 2 complete file pipelines | 1–4 |
maxFileSizeMb | 25 MiB per PDF | 1–100 |
maxTotalInputSizeMb | 100 MiB accepted input per run | 1–500 |
maxPages | 500 per PDF; combined pages for merge | 1–2000 |
downloadTimeoutSeconds | 60 per attempt, including redirects/streaming | 5–300 |
downloadRetries | 2 | 0–3 |
failOnError | false | Set true to fail a partially successful Apify run. |
downloadRetries covers DNS resolution, connection and transport failures as well as HTTP 408, 429 and transient 5xx responses, so a transient resolver hiccup does not fail an input (or abort a merge batch). Safety, size and format violations always fail immediately without retry.
At most 100 sources are accepted. Generated files and cumulative split output per input are limited to 100 MiB. Text extraction is limited to 10 million characters per input. Dataset text is omitted automatically when structured text exceeds 4 MiB; use the complete JSON file instead.
These limits bound normal batch work, not every possible PDF parser expansion. Use smaller batches and lower concurrency for complex documents. Platform memory and run timeout settings remain relevant. Start with 1–2 GiB for OCR or large merges and measure your documents.
Results and error handling
Successful file records include:
{"operation": "rotate","inputIndex": 1,"inputFile": "https://example.com/report.pdf","outputKey": "rotated_1.pdf","outputUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/rotated_1.pdf","pageCount": 3,"fileSizeBytes": 12345,"fileSizeKb": 12.1,"sha256": "<SHA-256 of the output bytes>","status": "OK","error": null}
Text records additionally provide pages, totalChars, failedPageCount, ocrPageCount, structuredOutputKey and structuredOutputUrl. URLs contain no access tokens. Download private records using your Apify authentication. Input URL credentials, query strings and fragments are omitted from result labels and download errors; inputIndex distinguishes repeated URLs.
SUMMARY contains counts for successful, partial and failed inputs, generated files, accepted input bytes and elapsed time. The summary is a KV record, not an extra dataset item.
OK: all requested work for that record completed.PARTIAL: some inputs/pages failed or only some split files could be saved. Completed outputs remain available.FAILED: the input or all selected text pages failed. If every input fails, the Apify run fails too.
With failOnError: false, a batch with successful and failed inputs can finish as an Apify SUCCEEDED run; check SUMMARY.status and dataset statuses. With failOnError: true, any partial result fails the run after preserving completed work.
Stable errorCode values include INVALID_INPUT, INVALID_PDF, PASSWORD_REQUIRED, INVALID_PAGE_RANGE, FILE_TOO_LARGE, TOTAL_INPUT_LIMIT, PAGE_LIMIT, OCR_PAGE_LIMIT, UNSAFE_URL, HTTP_ERROR, DOWNLOAD_FAILED, MERGE_ABORTED, OUTPUT_KEY_CONFLICT and ALL_PAGES_FAILED.
Unexpected internal failures are reported as PROCESSING_FAILED with a generic message that contains no credentials or document text; the matching traceback is written to the run log, so the cause stays diagnosable without leaking details into shared datasets. While a batch runs, the run status message reports progress (Processed 2/10 inputs, 2 OK) instead of only showing a final summary.
Output naming and examples
Automatic keys include merged.pdf, split_page_1.pdf, compressed_1.pdf, text_1.txt, text_1.json, ocr_1.txt, watermarked_1.pdf and rotated_1.pdf.
Custom names retain the operation prefix and source index: outputFileName: "report" produces rotated_report_1.pdf, merged_report.pdf, or split_report_1_pages_1to2.pdf for the first source of a batch. ZIP keys start with zip_. All source indices refer to original input positions, including failed inputs.
Batch split:
{"operation": "split","pdfKeys": ["first.pdf", "second.pdf"],"inputKeyValueStoreId": "YOUR_STORE_ID","pageRanges": "1-2;3","zipOutput": true,"outputFileName": "chapters"}
One dataset result generally corresponds to one processed input PDF. Merge produces one combined result; split produces one result per PDF chunk and one per ZIP archive. Failed-input records are also written. Refer to the live Store listing for current pricing; platform usage and dataset-event charging depend on the Actor's configured pricing model.
Development and verification
Python 3.12 is the production runtime. Poppler, Tesseract, six OCR language packs and DejaVu fonts are installed by .actor/Dockerfile.
requirements.txt declares supported dependency ranges. The container and development environment install the verified versions from requirements.lock; regenerate and retest the lock deliberately when upgrading dependencies.
uv venv --python 3.12uv pip install -r requirements-dev.txtpython -m pytest -q -m "not ocr"ruff check src testsdocker build -f .actor/Dockerfile -t pdf-tools:improvement .docker build -f tests/Dockerfile -t pdf-tools:test .docker run --rm --memory 2g --cpus 2 pdf-tools:testdocker run --rm --memory 2g --cpus 2 pdf-tools:test python -m tests.sdk_smoke
The container suite includes actual OCR; the SDK smoke suite invokes python -m src in isolated local stores and verifies dataset records, files, checksums and exit statuses. These are local tests. A deployment still requires a successful remote Apify build and online run verification under the workspace rules.
See CHANGELOG.md for compatibility changes and walkthrough.md for the improvement audit and validation evidence.