Count words in a PDF
Two pages holding 11 and 8 words give 19 words, 93 characters, 75 without spaces and an average of 9.5 words per page. Paste the text of each page in order to check theses, filings or proofs against length limits. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Counting the words in a PDF is a routine checkpoint for students, editors, translators, and compliance teams working against page and length limits. This tool takes the PDF's extracted per-page text—an array of strings in page order—and returns deterministic totals: total words, total characters with and without spaces, page count, the words-per-page average, and a per-page breakdown so you can spot a thin or bloated page at a glance. Because the input is already-extracted text, there is no binary parsing, no upload size lottery, and no dependence on a specific PDF library: any extractor that yields text per page feeds it.
How word, character, and page counts are computed
Word counting splits each page's text on Unicode whitespace and counts every non-empty token, which matches the behavior of editor status bars and mainstream online counters: a hyphenated token such as state-of-the-art counts as one word, and runs of spaces, tabs, or newlines collapse into a single separator. Character count is the full string length of the page text exactly as extracted, including spaces and line breaks, while a second total strips all whitespace so you can compare pure content length when layout padding would inflate the figure.
The page count is simply the number of elements in the input array, because each element represents one PDF page in order—so per-page fidelity depends on the extractor you used upstream. The words-per-page average divides total words by page count and rounds to two decimals, which makes it easy to compare manuscripts, reports, and theses of different lengths on one fair metric. Blank or whitespace-only pages contribute zero words but still count as pages, mirroring what a reader sees when flipping through a document with intentional blanks.
Where per-page PDF word counts show up in real work
Students and researchers verify thesis and dissertation length requirements after exporting text from the final PDF, checking both the overall total and the average density per page against faculty rules. Editors and production teams reviewing laid-out proofs use the per-page breakdown to find nearly empty pages, overstuffed spreads, or chapters whose density drifts far from the book's average before sending files to print.
Translators and localization vendors estimate effort and cost from word totals when a client can only supply the exported text of a source document rather than the original editable files. Legal and compliance teams confirm that filings stay under court or regulator word limits, where exceeding a cap can mean a rejected submission and a missed deadline. Data engineers building document pipelines store per-page word and character counts as quality metrics, flagging pages where extraction returned nothing—a reliable signal of scanned image pages that need OCR instead of text extraction.
Archivists comparing two versions of a report diff per-page counts to detect silently dropped or duplicated pages. Because this capability consumes already-extracted text, it composes cleanly with any upstream extractor and never re-parses binary PDFs; if you need the binary parsed for you, that is a separate capability such as pdf.stats.
What you can do with it
Thesis and filing length checks
Export the PDF's text per page and verify total words and the per-page average against university or court word limits before submitting.
Print proof density review
Scan the per-page breakdown for nearly empty or overstuffed pages and chapters that drift from the document's average density.
Extraction quality monitoring
Flag pages with zero words in document pipelines as likely scanned images that need OCR, using per-page counts as a quality signal.
FAQ
How are words counted?
Words are non-empty tokens separated by Unicode whitespace. Multiple spaces, tabs, or newlines collapse into one separator, and a hyphenated token counts as a single word.
Do blank pages count?
Yes. A blank or whitespace-only page contributes zero words but still counts toward the page total, matching what a reader sees in the document.
What happens if the input is empty?
Missing pages, an empty array, or pages whose combined text has no words are treated as client errors and are not charged.
What does it cost?
The browser tool is free and runs locally.
Why are there two character totals?
One counts the text exactly as extracted, spaces and line breaks included; the other strips all whitespace. The second lets you compare pure content length when layout padding would inflate the figure.
Related tools
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, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/pdf/count-words \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"pages":["Chapter One\n\nThe quick brown fox jumps over the lazy dog.","A second page with only a few words."]}'const res = await fetch("https://api.kit.forhosting.com/pdf/count-words", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"pages": [
"Chapter One\n\nThe quick brown fox jumps over the lazy dog.",
"A second page with only a few words."
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/pdf/count-words",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"pages": [
"Chapter One\n\nThe quick brown fox jumps over the lazy dog.",
"A second page with only a few words."
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/pdf/count-words", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"pages":["Chapter One\\n\\nThe quick brown fox jumps over the lazy dog.","A second page with only a few words."]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"pages":["Chapter One\n\nThe quick brown fox jumps over the lazy dog.","A second page with only a few words."]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/pdf/count-words", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"pages": [
"Chapter One\n\nThe quick brown fox jumps over the lazy dog.",
"A second page with only a few words."
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "pdf.count_words",
"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. |
Technical notes
Empty input—missing pages, an empty array, or pages with no words at all—is rejected with a clear invalid_input error instead of silent zeros.
How word, character, and page counts are computed
Pages that are not strings are rejected element by element with a message naming the offending page number, and combined text above the documented character cap fails fast with invalid_input so a single oversized request cannot monopolize Worker memory.
What you send and what you get back
A classic happy path is a two-page article whose totals are the sum of both pages with the average sitting between the two per-page figures, and a document with intentional blank pages still reports the correct page count while contributing zero words. Wire the free browser form for quick paste-and-check work on exported text, then call the identical contract from scripts when you audit whole archives of extracted documents. Send one required field named pages: an array of strings holding the extracted text of each PDF page in reading order. For convenience, the aliases text and content are accepted as a single string, which is treated as a one-page document, and pages_text works as an array alias when wiring older clients. On success the response returns pages, total_words, total_characters, total_characters_no_spaces, words_per_page_average, a per_page array with page number, words, characters, and characters_no_spaces for each page, and operation set to pdf_count_words. Error cases are explicit and never charged: a missing pages field, a non-array value, an empty array, non-string elements, a page count or combined length above the documented caps, and pages whose combined text contains no words all raise invalid_input with a message that says exactly which rule failed. Pricing for successful API calls is the published base of $0.002 per item; validation failures do not consume prepaid balance.
Where per-page PDF word counts show up in real work
API pricing is the published base of $0.002 per successful item, and invalid input is never charged, which keeps bulk archive audits predictable.
Technical questions
What input does this tool expect?
A field named pages: an array of strings with the extracted text of each PDF page in order. The aliases text or content are accepted as a single string and treated as a one-page document.