Count PDF pages and words
The PDF Page & Word Count API reads any PDF you send it and returns the exact number of pages, words and characters it contains. You POST the document, we do the parsing on our global edge, and the counts come back by webhook or a signed link, ready to feed into billing, quotas or editorial workflows.
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.
What it actually measures
A PDF is a layout format, not a text format, so the size of the file tells you almost nothing about how much is inside it. A single glossy page can weigh more than a two-hundred-page contract. This pdf page count api resolves that ambiguity: it opens the document, walks its page tree for an authoritative page total, and extracts the text layer to tally words and characters. The result is three honest integers you can act on, instead of a guess based on bytes.
Who reaches for this
Print shops and translation agencies price by the page or by the word, and a wrong count is a wrong invoice. Document-management platforms need per-page or per-word limits to enforce plans. Legal and compliance teams want to know how much text a disclosure bundle really holds before a human ever opens it. Anyone charging, quoting or throttling by document length is doing arithmetic that this endpoint does for them, deterministically and at scale.
How the request flows
You send a single POST /pdf/stats with your PDF, and the call returns immediately with a task_id. Counting is asynchronous because a large or image-heavy document should never block your request thread. When the work finishes, we deliver the page, word and character counts to your signed webhook, or you can poll a signed link that stays valid for twenty-four hours. If a task fails it is retried three times with backoff; only after that do you get a clear error, and a failed task is never billed.
A word about the format
PDF has carried text since 1993, and over three decades it has accumulated encodings, embedded fonts, custom character maps and pages assembled in any order. A faithful count has to respect all of that: honoring the real page tree rather than trusting metadata, decoding text that fonts may have remapped, and counting words the way a person would rather than splitting on raw glyphs. That fidelity is the whole point of a dedicated endpoint instead of a naive local script.
Fitting it into automation
Because every response is structured and every result is pushed to you, the API drops cleanly into a pipeline. Ingest a document, call the endpoint, and let the webhook trigger the next step: generate a quote, enforce a page cap, route long files for review, or write the counts straight to your database. Access needs prepaid balance, which keeps the service fast and free of abuse; each request is a flat, published price with no tokens or hidden credits to reconcile.
What you can do with it
Per-page print quoting
A print-on-demand service accepts a customer upload and instantly quotes the job by multiplying the returned page count by its unit rate, with no operator counting pages by hand.
Translation word estimates
A localization agency runs incoming PDFs through the endpoint to get a word count before assigning translators, turning a rough guess into a firm, defensible quote.
Upload limits on a SaaS plan
A document platform checks the page count on ingest and blocks or upsells any file that exceeds the tier's per-document cap, enforcing the plan automatically.
eDiscovery volume triage
A legal team measures the total characters across a disclosure batch to size the review effort and estimate cost before a single reviewer opens a page.
FAQ
How do I get the page count of a PDF with an API?
Send a POST /pdf/stats request with your file and you receive a task_id right away. The pdf page count api returns the page, word and character totals to your webhook or a signed link once processing finishes.
Is there a free version of this API?
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 count words or just pages?
Both, plus characters. A single call returns the page total, the word total and the character total, so you can price or gate by whichever unit your workflow uses.
Will it work on scanned or image-only PDFs?
Page counts are always accurate because they come from the document structure. Word and character counts depend on a real text layer, so a purely scanned PDF with no embedded text will report zero words until it has been through OCR.
Can I count pages for many PDFs in bulk?
Yes. Submit each document as its own POST and the tasks run in parallel on our global edge. Each request is billed independently, and any task that fails is retried and never charged.
How accurate is the page count?
The page total is read directly from the PDF page tree, the authoritative source, so it matches what a viewer would show. It does not rely on metadata, which can be wrong or missing.
How do I receive the result of an async request?
Two ways: a signed webhook we POST to your server the moment counting finishes, which is recommended, or a signed link valid for twenty-four hours that you can fetch on your own schedule.
What happens to my document after processing?
Your file and its results are deleted after the retention window and are never used to train anything. Delivery links are signed and expire, so counts stay tied to your request alone.
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/stats \
-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/stats", {
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/stats",
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/stats", 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/stats", 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.stats",
"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. |