What this tool will not do
- This tool sends your text to the server to be counted. It is not stored, logged or kept after the response — but unlike most tools here it does leave your browser, so do not paste anything confidential. See the privacy policy.
- Input is capped at 1 MB.
- Character counts are Unicode code points, not UTF-16 code units. An emoji counts as one where JavaScript’s
lengthwould say two — so if you are checking against a form limit implemented withlength(many are), our number will be lower than the one that limit enforces. An emoji built from a ZWJ sequence (👨👩👧) is still several code points, not one. - Reading time is fixed at 200 words per minute. Real reading speed varies roughly 200–260 WPM, and faster still for skimming.
- Languages without spaces — Chinese, Japanese, Thai — follow the default Unicode rules. Where the count really matters, use a tokenizer built for that language.
Tool overview
This free text statistics tool returns accurate counts for words, characters (with and without spaces), sentences, paragraphs, and an estimated reading time (200 WPM). It's Unicode-aware and follows industry standards for segmentation so results are consistent across languages and emoji-containing text.
How to use
- Paste your text into the input area.
- Click Analyze / Send. The front-end posts JSON { "text": "..." } to POST /api/count.
- The API responds with: words, characters_with_spaces, characters_without_spaces, sentences, paragraphs, reading_time_seconds, and reading_time_display.
- Use the numeric values to display counters, limits, or reading-time badges in your UI.
What the tool returns (example response)
{
"words": 123,
"characters_with_spaces": 678,
"characters_without_spaces": 590,
"sentences": 7,
"paragraphs": 2,
"reading_time_seconds": 36.9,
"reading_time_display": "0m 37s"
}
Principles & implementation notes (sources)
- Word boundaries: follows Unicode Text Segmentation (UAX #29). Prefer using Intl.Segmenter ('word') or an ICU/UAX#29 library over naive whitespace-splitting to support emojis, CJK, and other scripts. Source: https://www.unicode.org/reports/tr29/
- Sentence boundaries: follow UAX #29 sentence rules. Use Intl.Segmenter with granularity 'sentence' or a library that implements UAX #29. Source: https://www.unicode.org/reports/tr29/#Sentence_Boundaries
- Paragraphs: defined per CommonMark — one or more consecutive non-blank lines separated by one or more blank lines (a blank line contains only spaces/tabs). Source: https://spec.commonmark.org/0.29/
- Character counts are Unicode code points, not UTF-16 code units — a character outside the Basic Multilingual Plane (most emoji, for example) counts as one, not two. Note that an emoji built from a ZWJ sequence (👨👩👧) is several code points. characters_without_spaces subtracts Unicode whitespace (at minimum ASCII space, tab, NBSP, and line breaks). Reference implementations: charactercounter.com
- Reading time: computed using 200 words per minute (per product spec). reading_time_seconds = (words / 200) * 60. Cite: Iris Reading summary of average reading ~200 WPM (see references). Note: research shows variation (200–260 WPM); 200 WPM is the product default.
Edge-case policies (explicit choices)
- Hyphenated compounds: treated as a single word when hyphens join letters/digits without surrounding spaces (matches common word-count policies such as MS Word and many ballot/instruction rules).
- Contractions: counted as a single word (apostrophes inside a token are part of the word) per UAX #29.
- Non-space languages (Chinese, Thai): UAX #29 segmentation may behave differently; for language-critical counts consider language-specific tokenizers.
- Emojis: counted as characters; whether an emoji sequence counts as a "word" depends on the segmenter; we follow Unicode segmentation behavior.
Sources (key references)
- Unicode Text Segmentation (UAX #29): https://www.unicode.org/reports/tr29/
- CommonMark (paragraph rules): https://spec.commonmark.org/0.29/
- Intl.Segmenter (MDN docs): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter
- Character count conventions: https://charactercounter.com
- Reading time reference (product default justification): https://irisreading.com/the-average-reading-speed/
FAQ
How do you count words?
We use Unicode Text Segmentation (UAX #29). When available, implementations use Intl.Segmenter ('word') or an equivalent library; this handles punctuation, apostrophes, emojis, and many Unicode corner cases more accurately than splitting on whitespace.
What's the difference between characters_with_spaces and characters_without_spaces?
characters_with_spaces counts all Unicode code points (letters, punctuation, line breaks, spaces, emojis). characters_without_spaces removes Unicode whitespace characters before counting.
Do contractions and hyphenated words count as one word?
Contractions (e.g., don't, I'm) count as one word. Hyphenated compounds are treated as one word when the hyphen connects alphanumeric characters without spaces (policy choice aligned with common tools and ballot rules).
How are paragraphs detected?
Paragraphs are blocks of consecutive non-blank lines separated by one or more blank lines (CommonMark definition). A blank line contains only spaces/tabs.
How is reading time calculated?
We use 200 words per minute. reading_time_seconds = (words / 200) * 60. The display string is human-friendly and may round to the nearest second.
Does this work for non-English text and emojis?
The tool accepts UTF-8 and uses Unicode-aware segmentation. For CJK or other scripts without spaces, segmentation behavior follows UAX #29; if you need language-specific tokenization, use dedicated tokenizers for that language.