🔢 Character Counter
Counts what you actually see, not UTF-16 units — so an emoji counts as one, not two. Includes X's weighted count, real SMS encoding limits, and the byte size.
Encoding
- Visible characters (graphemes)
- 0
- Unicode code points
- 0
- UTF-16 units (JavaScript length)
- 0
- UTF-8 bytes
- 0
Platform limits
What Character Counter Does
Counting characters sounds trivial and is the thing most counters get wrong, because "character" means four different things and only one of them is what you see on screen.
Take a thumbs-up emoji. To you it is one character. In Unicode it is one code point. In JavaScript — and therefore in most character counters, which use the obvious `length` property — it is two. A family emoji is one visible character, seven code points, eleven UTF-16 units and twenty-five bytes. A flag is one character reported as four. If your text contains any emoji, most counters are overstating its length, sometimes by a factor of ten.
The platform limits are usually wrong too, in a way that matters more. X does not count one per character: Latin letters weigh 1, but Chinese, Japanese, Korean and emoji weigh 2, and every URL counts as a flat 23 however long it really is. So 140 Japanese characters fills the 280 limit exactly, and pasting a 200-character tracking URL costs you 23.
And SMS has a cliff rather than a limit. One character outside the GSM 7-bit alphabet — an emoji, a curly quote pasted from Word, an em dash — forces the whole message into 16-bit encoding and cuts the limit from 160 to 70. This tool counts what you see, shows the other three figures alongside, and applies each platform's real rule rather than a flat number.
How to Use Character Counter
- Paste or type your text — everything updates live
- Read the visible character count, which treats each emoji as one character
- Check the encoding panel if you need code points, UTF-16 units or UTF-8 bytes
- Watch the platform bars for X, SMS, meta description, title tag, Instagram and LinkedIn
Formula Used by Character Counter
The four ways to count
graphemes ≤ code points ≤ UTF-16 units ≤ UTF-8 bytes
- Grapheme
- One visible character — what a person means by "character"
- Code point
- One Unicode value. An emoji with a skin tone is two
- UTF-16 unit
- What JavaScript length returns. Anything above U+FFFF takes two
- UTF-8 byte
- Storage size — 1 to 4 bytes per code point
Worked example
The family emoji 👨👩👧👦
- Graphemes: 1
- Code points: 7 — four people joined by three zero-width joiners
- UTF-16 units: 11
- UTF-8 bytes: 25
Result: One character by any human definition, reported as 11 by most counters
How X weights characters
weight 1 for Latin and common punctuation, weight 2 for everything else, 23 per URL
- Light ranges
- U+0000–U+10FF and parts of general punctuation
- URLs
- Replaced by a fixed 23 because every link is shortened
Worked example
Three different 280-limit posts
- 280 Latin characters = 280
- 140 Japanese characters = 280
- "Check " + a 200-char URL = 6 + 23 = 29
Result: All three are valid; only the first matches a naive character count
The SMS encoding cliff
All-GSM text: 160 per message. One non-GSM character: 70 per message.
- GSM 7-bit
- Basic Latin plus a small set of symbols and accents
- UCS-2
- The 16-bit fallback, used if any character falls outside GSM
Worked example
The same message with and without a curly apostrophe
- "Its ready" — all GSM, limit 160
- "It’s ready" — the ’ is not GSM, limit 70
Result: One punctuation mark more than halves how much you can send per message
What most counters report against what you see
Every figure verified in a browser. The third column is what JavaScript's length property returns, and therefore what a large share of online counters display.
| Text | You see | Code points | UTF-16 (most counters) | UTF-8 bytes |
|---|---|---|---|---|
| a | 1 | 1 | 1 | 1 |
| é (single character) | 1 | 1 | 1 | 2 |
| é (e + combining accent) | 1 | 2 | 2 | 3 |
| 👍 | 1 | 1 | 2 | 4 |
| 👋🏽 (with skin tone) | 1 | 2 | 4 | 8 |
| 🇬🇧 (flag) | 1 | 2 | 4 | 8 |
| 👨👩👧👦 (family) | 1 | 7 | 11 | 25 |
| 日本語 | 3 | 3 | 3 | 9 |
| Hello 👍 world | 13 | 13 | 14 | 16 |
Platform limits, and how each one really counts
The number is only half the rule. Several of these count something other than characters, which is why a single flat limit is misleading.
| Platform | Limit | What it actually counts |
|---|---|---|
| X / Twitter (free) | 280 | Weighted — non-Latin counts 2, every URL counts 23 |
| SMS, single message | 160 or 70 | 160 in GSM 7-bit; 70 if any character falls outside it |
| Meta description | ~155 | Google truncates by pixel width, not character count |
| Title tag | ~60 | Roughly 600 pixels — wide letters and capitals cost more |
| Instagram caption | 2,200 | Only about the first 125 show before "more" |
| LinkedIn post | 3,000 | Around 210 show before "see more" |
Bytes per character in UTF-8
Relevant whenever a database column, an API payload or a file size is the real constraint rather than the character count.
| Script or content | Bytes per character | Example |
|---|---|---|
| Basic Latin, digits, ASCII punctuation | 1 | a, 7, ? |
| Accented Latin, Greek, Cyrillic, Hebrew | 2 | é, π, д |
| Chinese, Japanese, Korean, most others | 3 | 日, 한, ट |
| Emoji and other supplementary characters | 4 | 👍, 🎉 |
| Emoji with modifiers or ZWJ sequences | 8 to 25+ | 👋🏽, 👨👩👧👦 |
How to Read Your Result
The emoji problem is not an edge case
It would be easy to treat this as pedantry if emoji were rare. They are not — they appear in a large share of social posts, marketing copy, product names and messages. A counter reporting eleven characters for a single family emoji will tell you a 270-character post is over the limit when it is not, or that a database field will overflow when it will not. The fix has been available in every browser for years: Intl.Segmenter walks text by grapheme cluster, which is the formal name for "what a person calls a character".
Which count you need depends on the destination
There is no single correct answer, which is why all four are shown. Writing a tweet or an SMS: you want the platform's own rule. Filling a form with a maxlength attribute: that is enforced in UTF-16 units, so the browser will cut you off by the number most counters show. Sizing a database column or an API payload: that is bytes. Explaining to a person how long their text is: graphemes. Using the wrong one produces off-by-a-lot errors rather than off-by-one.
Why 140 Japanese characters equals 280 Latin ones
X doubled its limit from 140 to 280 in 2017, but only for languages that need the space. The weighting exists because Chinese, Japanese and Korean convey far more per character, so those languages kept an effective 140 while Latin scripts got 280. It is a deliberate equalization rather than a penalty. The URL rule has a different origin: every link is rewritten to a fixed-length shortener, so the length you paste is irrelevant to the count.
The smart-quote trap in SMS
This one costs real money at scale. Drafting a message in a word processor silently converts straight apostrophes to curly ones, and the curly apostrophe is not in the GSM 7-bit alphabet. That single substitution drops the per-message limit from 160 to 70, so a 150-character message that would have sent as one now sends as three — tripling the cost of a campaign for a change nobody made deliberately. The same applies to em dashes and ellipsis characters. Type directly into a plain field, or check the counter before sending.
Title and description limits are really pixel limits
Google does not truncate search snippets at a character count; it truncates at a width, roughly 600 pixels for a title. So a title of sixty narrow lowercase characters may fit comfortably while fifty-five wide ones in capitals get cut. The commonly quoted 60 and 155 figures are reasonable working approximations and nothing more. If a title matters, look at how it renders rather than trusting the count — and remember the snippet is often rewritten by Google anyway.
Counting locally is the point
Text pasted into a character counter is frequently a draft that has not been published yet — a press release, a legal notice, a message to a client. A counter has no reason to transmit it, and this one does not: the whole thing runs in the page, so it works with the network off and nothing you paste leaves the browser. That is easy to verify and worth verifying on any tool you paste unpublished work into.
Limitations & Accuracy Notes
- Grapheme counting uses the browser's own Intl.Segmenter. A very old browser without it falls back to counting code points, which is closer than UTF-16 but still splits emoji with modifiers.
- Platform limits change without notice, and paid tiers differ — X Premium allows far more than 280. Treat the bars as a guide and confirm against the platform if it matters commercially.
- The X weighting implements the published rules for character weight and URL length. X may apply additional handling to mentions, media and quoted posts that is not modeled here.
- Meta description and title limits are shown in characters because that is what people search for, but Google truncates by pixel width, so the figures are approximations rather than thresholds.
- SMS detection covers the standard GSM 7-bit alphabet. Some carriers and gateways handle the extension table differently, which can shift where the 160 boundary falls by a character or two.
- Word counting splits on whitespace, which suits languages that separate words that way. Chinese, Japanese and Thai do not, so the word count is not meaningful for them.
Frequently Asked Questions
Why do character counters disagree about emoji?
How does X actually count characters?
Why did my SMS limit drop from 160 to 70?
Is the 60-character title tag limit real?
What is the difference between characters and bytes?
Is my text uploaded anywhere?
References & Further Reading
- Unicode Standard Annex #29 — Text Segmentation — Defines the grapheme cluster — the formal specification behind counting what a reader perceives as one character, which is what Intl.Segmenter implements
- MDN — Intl.Segmenter — The browser API used here for grapheme counting, and the documented reason String.length is not a character count
- X — Counting characters — The published weighting rules implemented on this page: weight 1 for Latin ranges, 2 for everything else, and a flat 23 per URL
- Google Search Central — Control your title links in search results — Google's own guidance on titles, including that snippets are truncated for display and often rewritten