Skip to content

Text Utilities

Count words and characters, change case and turn titles into URL slugs.

Runs in your browser. Nothing is uploaded.

Characters are counted as users see them (an emoji with a skin tone is 1). Runs in your browser.
or drop one here. The file is read in your browser and never uploaded.

About this tool

Text Utilities has three modes. Count reports characters as a reader sees them - grapheme clusters, taken from the browser's text segmenter, so an emoji with a skin tone modifier counts as one - next to characters without spaces, words, sentences, lines, paragraphs, UTF-8 bytes and a reading time based on 230 words a minute. Change case produces nine variants at once (camelCase, PascalCase, snake_case, kebab-case, CONSTANT_CASE, Title Case, Sentence case, lowercase, UPPERCASE), splitting on case boundaries so HTTPServer becomes http_server. Slug maps a short list of Latin letters (ß to ss, æ to ae, ø to o, ş to s, ğ to g, ç to c, ö to o, ü to u, and & to the word “and”), strips the remaining accents through Unicode NFKD normalisation and joins what survives with a hyphen or an underscore. It does not transliterate non-Latin scripts: Cyrillic, Greek, Hebrew, Arabic, Chinese and Japanese characters are not romanised, they are dropped like any other character outside A-Z, a-z and 0-9.

All three modes are pure functions running in the page: the counter uses the browser's own Intl.Segmenter for grapheme clusters, falling back to counting code points where that API is missing, and TextEncoder for the UTF-8 byte figure, while the case and slug modes use the browser's Unicode normalisation. Your text is not sent to the XGM API, not written into the URL and not stored in this browser - the address keeps only the mode, as ?mode=case or ?mode=slug, with the counter as the default that carries no parameter, so a shared link opens an empty tool. The reading-ease and grade figures are the Flesch and Flesch-Kincaid formulas computed in the page from a syllable estimate: both were fitted on English prose, so they are an estimate for English text and mean little for Turkish or Romanian. Copy, download and the JSON export are assembled from the result already on screen. The only request the page makes on its own is the page-view event sent after you accept analytics, which records the page path and the tool name, never your text.

How to use it

  1. Open the Text Utilities tool.
  2. Paste or type the input you want to inspect.
  3. Read the result, which is computed in your browser; the input is not sent to XGM.
  4. Copy the output only after checking it looks correct.
  5. Use related XGM tools if you need a broader diagnostic view.

FAQ

Why is the character count different from the one in my editor?

Most editors count UTF-16 code units, which makes an emoji two and a flag four. Here the Characters figure counts grapheme clusters through the browser's Intl.Segmenter, so 👍🏽 is one character even though it is two code points and eight UTF-8 bytes. Use the UTF-8 bytes figure when a database column or an API limit is measured in bytes; note that Without spaces is counted per code point, so the two character figures can differ on emoji.

Are Chinese or Japanese words counted correctly?

No. Words are the runs of non-whitespace in the trimmed text, so a writing system that does not put spaces between words - Chinese, Japanese, Thai - reports one word per run and a reading time to match. Characters, characters without spaces, lines and UTF-8 bytes are still accurate. Sentences are counted by splitting on . ! ? and …, so an abbreviation such as “e.g.” inflates the number.

Why did camelCase lose the accents that Title Case kept?

The identifier styles - camelCase, PascalCase, snake_case, kebab-case and CONSTANT_CASE - normalise the text to NFKD, drop the combining marks and then split on everything that is not an ASCII letter or digit, which is what makes them safe as code identifiers: “Café Ünïcödé” becomes cafeUnicode. Title Case, Sentence case, lowercase and UPPERCASE are applied to your original text and only change case, so accents, punctuation and non-Latin characters stay.

Why is my slug shorter than the title I pasted?

Max length is 80 by default; set it to 0 to switch the limit off. When a slug is longer, it is cut at the limit and then trimmed back to the last separator so it does not end mid-word - if there is no separator inside that window the hard cut stands. Each line of the input produces its own slug, so you can paste a list of titles and get a list back.

Which characters survive in a slug, and why did mine come out empty?

Only A-Z, a-z and 0-9. Everything else becomes the separator, repeated separators collapse into one and leading and trailing ones are trimmed, after & has been replaced by “and” and NFKD has decomposed accented letters and compatibility forms (é to e, fi to fi). Because non-Latin scripts are removed rather than transliterated, a title written entirely in Cyrillic, Greek or Chinese produces an empty slug - write that slug by hand, or transliterate it before pasting.

Read the full Text Utilities guide