Compare two PDFs
Two contract drafts that look nearly identical at a glance can hide the one clause that actually matters, and no one reads two hundred pages twice to find it by eye. The Compare PDFs API takes two versions of a document and returns exactly what changed between them, down to the sentence, so a human only has to review the differences instead of the whole file.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
The redline problem, without the redlining
Version control is a solved problem for code and a constant headache for documents. A contract goes out for negotiation, comes back edited, and now someone has to figure out what actually moved: a changed payment term, a deleted indemnity clause, a renumbered section that looks different but says the same thing. Doing that by eye across dozens of pages is slow and error-prone, and the errors are exactly the ones that matter most. The compare two pdfs api replaces that manual redlining with a direct diff between the two files.
What the comparison actually captures
You send both PDFs and get back a structured account of the differences: text that was added, text that was removed, and text that shifted position, distinguished from formatting noise like a page reflow that moved a paragraph without changing a word. That distinction is what separates a useful comparison from an unusable wall of false positives, and it is why a naive text diff on extracted content tends to disappoint on real-world documents with headers, footers, and page breaks in the way.
How the request works end to end
POST both documents to /pdf/compare and the call returns a task_id immediately, since comparing full documents takes real computation that should never sit inside an open connection. Once the comparison finishes, the structured diff arrives at your signed webhook or through a signed link valid for 24 hours. If the job fails, it is retried three times with backoff before you see a clear error, and you are never billed for a comparison that did not complete.
Why this needed a dedicated tool
PDF was designed to fix the layout of a page exactly, which is wonderful for print and terrible for anyone trying to compare two versions with a generic diff tool, since identical content can be encoded in completely different byte sequences depending on how it was generated. A meaningful comparison has to look past that encoding noise to the actual visible content and its order on the page, which is precisely the layer this endpoint operates on rather than the raw file bytes.
Where it plugs into a workflow
Because results are delivered asynchronously and in a structured format, comparison drops cleanly into contract lifecycle tools, document approval systems, or a nightly job that checks whether a published policy PDF changed from the version cached last week. Access requires prepaid balance, which keeps requests fast and the service abuse-free, and pricing is a flat, published $0.002 per request with nothing else to calculate. This endpoint is live today.
What you can do with it
Contract redlining without the redlines
A legal team compares the version a counterparty returns against the last sent draft, instantly seeing every clause that changed instead of scanning two hundred pages side by side.
Policy change monitoring
A compliance team compares each new revision of a published regulatory PDF against the previous version to confirm exactly what language changed before republishing internal guidance.
Vendor agreement audits
A procurement platform compares a signed agreement against its original template to flag any custom edits a vendor slipped in before approval.
Publication proofing
A publisher compares a final print-ready PDF against the previously approved proof to confirm that only the intended corrections were applied and nothing else shifted.
FAQ
How do I compare two PDFs with an API?
Send a POST to /pdf/compare with both documents. The compare two pdfs api returns a task_id right away and delivers the structured diff to your webhook or a signed link once the comparison finishes.
Is this API free to use?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
Does it compare text, layout, or both?
It compares the actual visible content and its position, distinguishing real additions and deletions from cosmetic reflow, so a paragraph that only moved because of pagination is not flagged as changed content.
Can it compare scanned PDFs?
Comparison works on the text layer of a document, so a scanned PDF needs a text layer, such as one added by an OCR step, before a meaningful text comparison is possible.
How large can the two PDFs be?
The endpoint is built to handle full-length real-world documents like contracts and policies; because processing is asynchronous, size does not block your request thread while the comparison runs.
Can I run comparisons on many document pairs in bulk?
Yes. Each pair is submitted as its own POST and processed independently, so a batch of comparisons can run in parallel with each result delivered by webhook as it finishes.
Is the Compare PDFs API live now?
Yes, this endpoint is live today and accepting requests at the published price of $0.002 per request.
What happens to my documents after comparing them?
Both files and the resulting diff are deleted after the retention window and are never used for training. Delivery is by signed webhook or a signed link valid for 24 hours.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/pdf/compare \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"pdf":"https://ejemplo.com/documento.pdf"}'const res = await fetch("https://api.kit.forhosting.com/pdf/compare", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"pdf": "https://ejemplo.com/documento.pdf"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/pdf/compare",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"pdf": "https://ejemplo.com/documento.pdf"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/pdf/compare", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"pdf":"https://ejemplo.com/documento.pdf"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"pdf":"https://ejemplo.com/documento.pdf"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/pdf/compare", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"pdf": "https://ejemplo.com/documento.pdf"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "pdf.compare",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
max_pages | 200 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
413 | input_too_large | The file exceeds the size limit. |