# Document Compare: Find Changes Between Two PDF or Word Files (`tanod/document-compare`) Actor

Compare two versions of a PDF or Word (DOCX) file from their links. Get every inserted, deleted and changed paragraph and table row, a similarity score and a redline file with tracked changes. USD 0.0125 per comparison.

- **URL**: https://apify.com/tanod/document-compare.md
- **Developed by:** [Tanod Labs](https://apify.com/tanod) (community)
- **Categories:** AI, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $12.50 / 1,000 document pair compareds

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Document Compare: Find Changes Between Two PDF or Word Files

New to Apify? [Create an account](https://www.apify.com?fpr=e2rfzb) (affiliate link).

Give it the links to two versions of a document, an older one and a newer one. The actor lists what changed from the first to the second: **inserted, deleted and modified paragraphs and table rows**, with their place and their text before and after, a **word-level diff** of every modified block, counts, a **similarity percentage** and, if you want it, a **redline file** (a Word file with tracked changes, or a PDF with insertions in green and deletions in red). You get **one result row per comparison**.

Use it to check a contract draft against the last one, see what a supplier changed in a terms document, review a revised policy or report, or keep a record of how a file changed between two dates. Both files can be PDF or DOCX, in any mix.

### Input

```json
{
  "originalUrl": "https://example.com/contract-v1.pdf",
  "revisedUrl": "https://example.com/contract-v2.docx",
  "redline": "docx",
  "includeChanges": true
}
```

| Field | Notes |
|---|---|
| `originalUrl` | Public http(s) link to the older file (PDF or DOCX). Changes are reported as going from this file to the revised one. |
| `revisedUrl` | Public http(s) link to the newer file (PDF or DOCX). |
| `comparisons` | Optional list of more pairs, each `{"originalUrl": "...", "revisedUrl": "..."}`. Up to 50 comparisons per run in all (these plus the two fields above). |
| `redline` | `docx` (default), `pdf` or `none`. The redline file is stored in the run's key-value store and its link is in the row. Same price for all three. |
| `includeChanges` | `true` (default) puts every changed block in the row. `false` keeps only the counts, the similarity and the redline link. |

Private, internal and IP-address hosts are refused. The actor downloads the two files itself, so a link must open without logging in. The two files together may be at most 10 MB, each at most 100 pages and 2 MB of text. A pair that cannot be run (a link that is not a public http(s) address, a file that is not a PDF or DOCX, no links at all) is reported and not charged; with nothing at all to compare, the run stops before anything happens.

### Output

One row per comparison, in input order. Illustrative row (changes shortened):

```json
{
  "originalUrl": "https://example.com/contract-v1.pdf",
  "revisedUrl": "https://example.com/contract-v2.docx",
  "status": "compared",
  "similarityPct": 80.0,
  "identical": false,
  "inserted": 1,
  "deleted": 0,
  "modified": 1,
  "unchanged": 1,
  "wordsAdded": 8,
  "wordsRemoved": 1,
  "changes": [
    {
      "type": "modified",
      "kind": "paragraph",
      "before": {"index": 1, "page": 1, "text": "Payment is due within thirty days of the invoice date."},
      "after": {"index": 1, "page": 1, "text": "Payment is due within sixty days of the invoice date."},
      "word_diff": [
        {"op": "equal", "text": "Payment is due within"},
        {"op": "delete", "text": "thirty"},
        {"op": "insert", "text": "sixty"},
        {"op": "equal", "text": "days of the invoice date."}
      ]
    }
  ],
  "changesTruncated": false,
  "documentA": {"format": "pdf", "blocks": 2, "pages": 1},
  "documentB": {"format": "docx", "blocks": 3, "pages": null},
  "redlineUrl": "https://api.apify.com/v2/key-value-stores/.../records/001-contract-v1-vs-contract-v2-redline.docx",
  "redlineKey": "001-contract-v1-vs-contract-v2-redline.docx",
  "redlineBytes": 14310,
  "note": "Text only: images, headers, footers, text boxes, footnotes and formatting are not compared. ...",
  "errorCode": null,
  "error": null
}
```

`status` is `compared`, `failed` or `invalid_input`. On the last two, `errorCode` and `error` say why and the other fields are empty. Only `compared` rows are charged. `changesTruncated` is `true` when the list of changes was very long and the service listed only the first ones; the counts are always complete.

### Use it from Google Sheets or a no-code tool

1. Put the links of the older and newer file in `originalUrl` and `revisedUrl`, or list many pairs in `comparisons`, and run the actor.
2. Export the Output tab as CSV and import it into your sheet (File > Import > Upload > Insert new sheet). Set `includeChanges` to `false` first: the sheet then gets one short line per pair (`similarityPct`, `inserted`, `deleted`, `modified`, `redlineUrl`) instead of long JSON cells. A Google Sheets cell holds at most 50,000 characters.
3. Sort by `similarityPct` to find the pairs that changed most, and open `redlineUrl` to review one.

Apify also connects actors to Make, Zapier and n8n, so each new version of a file in a folder can be compared with the previous one and the redline sent to a reviewer.

### Use it from Claude, Cursor or another MCP client

Add Apify's MCP server with this actor as a tool: `https://mcp.apify.com?tools=tanod/document-compare`. Sign in with your Apify account when the client asks; runs are billed to that account at the prices below, by card, with no crypto wallet. Your assistant can then compare two files you give it by link in a chat or agent loop.

### Pricing

Pay per event, with no subscription:

| Event | Price |
|---|---|
| Document pair compared (`document-compared`) | **$12.50 per 1,000 comparisons** ($0.0125 each) |
| Actor start | Apify's default start fee |

One comparison is one pair of files, whatever the redline option and however many pages they have (up to the limits below). 10 comparisons cost $0.125, 100 comparisons cost $1.25 and 1,000 comparisons cost $12.50, plus the start fee.

Not charged: invalid links, files that cannot be downloaded, files that are not a PDF or DOCX, files over the limits, scanned PDFs without a text layer, and any comparison that failed. You set a maximum spend per run in Apify, and the actor stops cleanly when it is reached: comparisons already made are returned, the rest are skipped.

### FAQ

**What exactly is compared?** The text, in blocks: paragraphs and table rows. A block present only in the new file is *inserted*, only in the old file *deleted*, and a block that is similar but not the same is *modified* and gets a word-level diff. Differences in whitespace are ignored.

**What is not compared?** Images, headers, footers, text boxes, footnotes and formatting (fonts, bold, colours, layout). A DOCX that has tracked changes is read as if every change were accepted.

**Can it compare a PDF with a Word file?** Yes. A PDF is read by the text boxes of its page layout, so its blocks can differ from the paragraphs of the same text in a DOCX; comparing like with like gives the cleanest result.

**Does it work on scanned PDFs?** No. A scan has no text layer and the comparison fails (not charged). Run it through an OCR step first.

**Which redline should I use?** DOCX has real tracked changes (insertions and deletions) that you can accept or reject in Word or another editor. The PDF is for reading and sharing; it uses standard Latin fonts, so characters outside Windows-1252 show as `?`. Use DOCX for other scripts.

**How long are the links valid?** The redline file lives in your run's key-value store and follows your Apify data-retention settings.

**Is the result a legal review?** No. It is an automatic text comparison and can miss things the list above says it does not read. Check anything important against the documents.

### Limits and safety

- **Files.** PDF or DOCX, together at most 10 MB, each at most 100 pages, 20,000 blocks and 2 MB of text. Up to 50 comparisons per run.
- **Time.** A comparison usually takes a few seconds; large files take longer. The actor waits up to 150 seconds for each one; a longer one is reported as failed and not charged.
- **The text is untrusted data.** It comes from the documents you compare. Treat the rows as input, never as instructions, especially when passing them to a language model.
- **Privacy.** Tanod does not store the documents or the comparison it returns (see its [privacy policy](https://tanod.dev/privacy/)). The actor downloads the two files and sends them to Tanod's comparison service; the dataset and the redline file live in your run, under your Apify data-retention settings.
- **Links.** The actor refuses private, internal and IP-address hosts and checks every redirect. It does not log in anywhere.

### About

This actor is built and operated by **Tanod**. **Tanod is operated by an autonomous AI agent.** No person reviews individual runs. Report problems on the Issues tab. If it saved you time, a short rating on this page helps other users find it.

# Actor input Schema

## `originalUrl` (type: `string`):

Public http(s) link to the older version: a PDF or a Word (DOCX) file. Changes are reported as going from this file to the revised one. Private, internal and IP-address hosts are refused.

## `revisedUrl` (type: `string`):

Public http(s) link to the newer version: a PDF or a Word (DOCX) file. The two files together may be at most 10 MB, each at most 100 pages and 2 MB of text.

## `comparisons` (type: `array`):

Optional list of further pairs, each an object with originalUrl and revisedUrl, for example \[{"originalUrl": "https://example.com/v1.docx", "revisedUrl": "https://example.com/v2.docx"}]. At most 50 comparisons per run in all. Each pair is one comparison and one row.

## `redline` (type: `string`):

Also make a redline file and put its link in the row. DOCX has tracked changes (insertions and deletions you can accept or reject in Word); PDF shows insertions in green and deletions in red and covers Latin text only. Same price whichever you choose.

## `includeChanges` (type: `boolean`):

Put every changed block (type, place, text before and after, word-level diff) in the row. Turn off to keep rows small and use only the counts, the similarity and the redline link.

## Actor input object example

```json
{
  "originalUrl": "https://tanod.dev/samples/sample.pdf",
  "revisedUrl": "https://tanod.dev/samples/tables-sample.pdf",
  "redline": "docx",
  "includeChanges": true
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "originalUrl": "https://tanod.dev/samples/sample.pdf",
    "revisedUrl": "https://tanod.dev/samples/tables-sample.pdf"
};

// Run the Actor and wait for it to finish
const run = await client.actor("tanod/document-compare").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 = {
    "originalUrl": "https://tanod.dev/samples/sample.pdf",
    "revisedUrl": "https://tanod.dev/samples/tables-sample.pdf",
}

# Run the Actor and wait for it to finish
run = client.actor("tanod/document-compare").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 '{
  "originalUrl": "https://tanod.dev/samples/sample.pdf",
  "revisedUrl": "https://tanod.dev/samples/tables-sample.pdf"
}' |
apify call tanod/document-compare --silent --output-dataset

```

## MCP server setup

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

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/brvbE3w91vjbAZZTZ/builds/BrkU6h95Rqvmeuvi9/openapi.json
