# PDF Toolkit: Merge, Split, Compress & Convert PDFs. (`apifmcpfactory/pdf-toolkit`) Actor

Merge, split, compress, convert, rotate and watermark PDFs in one tool. Batch jobs and URL-to-PDF, no file-size limits. For people and AI agents.

- **URL**: https://apify.com/apifmcpfactory/pdf-toolkit.md
- **Developed by:** [Howth Technology Factory](https://apify.com/apifmcpfactory) (community)
- **Categories:** Developer tools, Agents, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

Nine PDF operations in one tool — merge, split, compress, rotate, delete pages, watermark, PDF-to-images, images-to-PDF and URL-to-PDF. Point it at public file URLs, pick an action, and get back downloadable output files. No file-size limit, no signup, and one flat price per file produced.

### 1. Why use PDF Toolkit

Document work in an automated pipeline usually means stitching together several single-purpose services: one for merging, another for compression, a third to render a web page as PDF. Each has its own account, its own limits and its own failure mode, and the free tiers stop exactly when a real batch starts.

The operations themselves are not hard. What is hard is having all of them behind one interface, callable from a workflow or an AI agent, that does not impose a page cap or a daily quota, and that only charges when a file actually comes out.

This Actor is that interface. One input shape, nine actions, one price per produced file.

### 2. Key features

- **Nine operations**: `merge`, `split`, `compress`, `rotate`, `deletePages`, `watermark`, `pdfToImages`, `imagesToPdf`, `urlToPdf`.
- **No file-size limit** and no page cap.
- **Batch input.** Most actions accept multiple files in a single call.
- **Before/after sizes returned** on every run, so compression results are measurable rather than asserted.
- **Downloadable output URLs** — produced files are written to the run's key-value store and returned as direct links.
- **Charged on output only.** A failed run produces no dataset item, and an Actor that fails is not billed for a result.
- **Dependencies loaded on demand** — a merge does not load the browser engine that URL-to-PDF needs, so light actions stay light.
- **Callable by AI agents** as one step in a document workflow.

### 3. Who it's for

**For operations and back office.** Merge a month's signed delivery notes into one archive PDF, or split a combined scan into per-invoice files, without a desktop tool and without uploading client documents to a consumer website.

**For finance teams.** Compress a folder of statements before attaching them to a filing, and see the before/after byte counts rather than trusting a "compressed!" message.

**For marketing.** Render a live web page to PDF for an approvals trail, or watermark a draft deck before circulating it outside the company.

**For developers and AI agents.** Call it inside a document pipeline: an agent handling an inbound email can split the attachment, extract the pages it needs, and pass them on, all through one tool with one price.

### 4. How to use it

1. Open the Actor and click **Try for free**.
2. Choose an **Action** from the dropdown.
3. Put the public `https` URL(s) of your file(s) in **Files**. PDFs for most actions; images for `imagesToPdf`; `urlToPdf` takes its target in **Options** instead.
4. Add any action-specific settings in **Options** as JSON.
5. Click **Start**, then collect the links in `outputUrls` from the **Output** tab.

### 5. Input parameters

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `action` | string | Yes | `merge` | One of `merge`, `split`, `compress`, `rotate`, `deletePages`, `watermark`, `pdfToImages`, `imagesToPdf`, `urlToPdf`. |
| `files` | array of strings | For most actions | — | Public `https` URL(s) of the file(s) to process. PDFs for most actions, images for `imagesToPdf`. Also accepts `kvs:<key>` to read from the run's key-value store. |
| `options` | object | No | `{}` | Action-specific settings as JSON. Only the fields relevant to the chosen action are read. |

`urlToPdf` is the exception: it takes its target page in `options` rather than in `files`.

### 6. Output

Exactly one dataset item per successful run:

```json
{
  "action": "merge",
  "inputCount": 3,
  "outputUrls": [
    "https://api.apify.com/v2/key-value-stores/%3CstoreId%3E/records/merged.pdf"
  ],
  "sizeBefore": 4812390,
  "sizeAfter": 4798122,
  "ms": 1840
}
```

Actions that produce several files — `split`, `pdfToImages` — return one entry in `outputUrls` per file.

### 7. Output fields

| Field | Meaning |
|---|---|
| `action` | The action that ran. |
| `inputCount` | How many input files were processed. |
| `outputUrls` | Direct download links to the produced file(s), served from the run's key-value store. |
| `sizeBefore` | Total input size in bytes. |
| `sizeAfter` | Total output size in bytes. For `compress`, the pair is the result you care about. |
| `ms` | Wall-clock duration of the operation. |

If the run fails, the Actor fails with a message and **no dataset item is written** — so a failed run produces no result charge.

### 8. How it works

Input files are fetched from their public URLs, or read from the run's key-value store when referenced as `kvs:<key>`. The chosen action's module is imported dynamically, so a run only loads the dependencies it actually needs — a merge never loads the browser engine that `urlToPdf` requires.

Produced files are written to the run's key-value store and their public URLs collected. Exactly one dataset item is then written summarising the run, which is what the built-in per-result charge bills against.

Compression is structural rather than lossy: object streams are rebuilt and redundancy removed. Text and vector content are unaffected, which is why the gain on an already-optimised PDF can be modest and is always reported honestly through `sizeBefore` and `sizeAfter`.

### 9. API & MCP usage

**cURL**

```bash
curl -X POST "https://api.apify.com/v2/acts/apifmcpfactory~pdf-toolkit/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"action":"merge","files":["https://example.com/a.pdf","https://example.com/b.pdf"]}'
```

**As an Apify MCP tool.** This Actor is callable directly by AI agents such as Claude and Cursor. Usage bills through your own Apify account.

```
https://mcp.apify.com?tools=apifmcpfactory/pdf-toolkit
```

Claude Desktop (`claude_desktop_config.json`):

```json
{
    "mcpServers": {
        "pdf-toolkit": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=apifmcpfactory/pdf-toolkit",
                "--header",
                "Authorization: Bearer YOUR_APIFY_TOKEN"
            ]
        }
    }
}
```

**As a standalone MCP server.** Five of these operations also run as a dedicated hosted MCP server — `merge_pdfs`, `split_pdf`, `compress_pdf`, `pdf_to_text` and `images_to_pdf`. See the product page for that endpoint.

### 10. Pricing

$0.02 per file produced by a successful operation, plus a small per-run start fee.

A failed run writes no dataset item, so it carries no result charge.

### 11. Limits & performance

| | |
|---|---|
| File size | No imposed limit |
| Page count | No imposed limit |
| Output | Written to the run's key-value store |
| Dependency loading | On demand, per action |

### 12. Limitations

- **Input files must be reachable.** Public `https` URLs, or `kvs:<key>` references within the run. Files behind a login cannot be fetched.
- **Compression is structural, not lossy.** It rebuilds the file's internals rather than downsampling images. On an already-optimised PDF the saving may be small — the returned sizes tell you exactly how small.
- **No OCR.** `pdfToImages` rasterises pages; it does not recognise text in scans.
- **No editing of existing text.** The toolkit operates on pages and files, not on the text inside them.
- **No encryption or password removal.** Password-protected inputs cannot be processed.
- **`urlToPdf` renders public pages.** A page requiring a login will render as whatever an anonymous visitor sees.

### 13. FAQ

**What can it do?** Merge, split, compress, rotate, delete pages, watermark, convert PDF to images, build a PDF from images, and render a web page to PDF.

**Is there a file-size or page limit?** No limit is imposed by the Actor.

**How do I get my files back?** Each successful run returns `outputUrls` — direct download links to the produced files in the run's key-value store.

**What am I charged for?** Each file produced by a successful operation, plus a small run start fee. A failed run produces no dataset item and therefore no result charge.

**Why did compression save so little?** Compression is structural, not lossy. A PDF that was already optimised has little redundancy left to remove. Compare `sizeBefore` and `sizeAfter` for the exact figure.

**Can it read the text in a scanned document?** No. `pdfToImages` converts pages to images; there is no OCR.

**Can it open a password-protected PDF?** No. Encrypted inputs are not processed.

**Can an AI agent use it?** Yes — via the Apify MCP endpoint above, or the standalone MCP server for the five core operations.

### More tools from MCP Factory

- **[llms.txt Suite](https://apify.com/apifmcpfactory/llms-txt-suite)** — audit, generate and monitor llms.txt for AI-search readiness.
- **[Website Technology Detector](https://apify.com/apifmcpfactory/tech-stack-detector)** — detect any site's CMS, framework and analytics stack.
- **[Sanctions Screening](https://apify.com/apifmcpfactory/sanctions-screening)** — screen names against official OFAC, EU, UK and UN sanctions lists in bulk.

— A Howth Technology Factory tool. Nothing stored beyond your own run.

# Actor input Schema

## `action` (type: `string`):

What do you want to do?

## `files` (type: `array`):

Public https URL(s) of the file(s) to process (PDFs for most actions, images for 'Convert images to a PDF'). Not used for 'Convert a web page to PDF' — use Page URL below instead.

## `options` (type: `object`):

Action-specific settings, as JSON. Only the fields for the selected action are used:
• split / deletePages → "pages": "1,3-5" (1-based page ranges)
• rotate → "angle": 90 | 180 | 270 (clockwise)
• watermark → "text", "opacity" (0-1), "position": "center"|"top-left"|"top-right"|"bottom-left"|"bottom-right"
• pdfToImages → "format": "png"|"jpeg", "scale" (e.g. 2 = ~144 DPI)
• imagesToPdf → "pageSize": "A4"|"Letter"|"fit" (fit = match each image)
• compress → "quality": "low"|"medium"|"high" (low = smallest file)
• urlToPdf → "url": the public https page to render, "format": "A4"|"Letter", "landscape": true|false

## Actor input object example

```json
{
  "action": "merge",
  "files": [
    "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
    "https://pdfobject.com/pdf/sample.pdf"
  ],
  "options": {}
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "files": [
        "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
        "https://pdfobject.com/pdf/sample.pdf"
    ],
    "options": {}
};

// Run the Actor and wait for it to finish
const run = await client.actor("apifmcpfactory/pdf-toolkit").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "files": [
        "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
        "https://pdfobject.com/pdf/sample.pdf",
    ],
    "options": {},
}

# Run the Actor and wait for it to finish
run = client.actor("apifmcpfactory/pdf-toolkit").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "files": [
    "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
    "https://pdfobject.com/pdf/sample.pdf"
  ],
  "options": {}
}' |
apify call apifmcpfactory/pdf-toolkit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,apifmcpfactory/pdf-toolkit"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/4UBNtCls5YHSk6obP/builds/EJQEQPneCcrQ6FMrR/openapi.json
