X (Twitter) Character Counter

Count posts like the platform: links cost 23, emoji count as 2, the rest is plain graphemes. Tweet 280, bio 160, name 50 limits.

Counting runs locally in your browser. There is no submit button and your draft never leaves the page.

0/280
—

280/160/50 are the standard free-tier limits. Premium accounts get higher tweet limits and X occasionally adjusts grapheme weights — for edge cases, verify in the official app.

How It Works

The counter reproduces the platform's weighting instead of naive string length. First it finds every http:// or https:// token and charges a flat 23 for each — the t.co shortener makes link length irrelevant. The remaining text is walked as grapheme clusters, and any cluster starting with a code point above U+FFFF costs 2 while everything else costs 1.

The UTF-16 trap
JavaScript's .length counts 16-bit code units, so an emoji like a single smiling face reports length 2 and a family emoji built from five code points reports far more. Naive counting also splits surrogate pairs in half; this tool walks whole clusters so cutting the count down never corrupts a character.
The t.co 23 rule
Every link is rewritten through the service's shortener when posted, so a 5-character URL and a 300-character tracking monolith both cost exactly 23. The counter strips URL tokens before weighing text and separately reports how many links it detected.
Grapheme counting with Intl.Segmenter
Where the browser supports Intl.Segmenter, flags, skin-tone modifiers and ZWJ families are treated as one visible character, matching what you see. Older engines fall back to code-point iteration via Array.from, which is still surrogate-safe, only slightly stricter on combined emoji.

Frequently Asked Questions

Do markdown or hidden formatting change the count?

No. X stores posts as plain text, so markdown markers, bold syntax or invisible styling count as the literal characters you typed. The only things counted differently from raw length are links — normalized to 23 — and characters outside the Basic Multilingual Plane, weighted at 2.

Why do emoji count as two characters?

JavaScript strings are UTF-16, and most emoji live above the Basic Multilingual Plane, where one visible character occupies two 16-bit code units — a surrogate pair. X weights those code points 2 in its own counter, and this page matches by walking grapheme clusters with Intl.Segmenter (with a code-point fallback where it is missing).

Does it handle threads or long posts?

It counts one block of text against one limit — that is exactly how threads work: each post in a thread gets its own budget, so check posts one at a time. Long-form posts are a separate premium feature with a much larger limit; this counter does not model them.

Is 280 the right limit for my account?

280 is the standard free-tier limit for tweets, 160 for profile bios and 50 for display names — all three are built into the toggle. Premium accounts get larger tweet limits, and X occasionally tests more characters per grapheme. For edge cases, verify the counter in the official app before posting.

Is anything uploaded to a server?

No. Counting is a few lines of vanilla JavaScript running in your browser — there is no submit button, no storage and no network request attached to your text. Drafts stay on your device.