X Character Limit (Twitter): How the 280 Is Weighted

14 min read

The X character limit is a weighted 280: links cost 23, emoji and CJK cost 2, Hindi and Arabic cost 1. I ran X's twitter-text library on sample posts to show it.

Renaissance-style painting of a walled hill town at dawn with market stalls, a red banner rising above the square

The X character limit gets quoted as “280 characters” and counted the way a word processor counts. X counts a weighted 280: its developer docs weigh Latin letters, punctuation and common symbols at 1, each emoji and each Chinese, Japanese or Korean character at 2, every link at a flat 23, and attached media at 0.

Read X’s own config file instead of a guide’s table, and the full 280 covers far more of the world’s writing than at least one 2026 explainer allows. X’s twitter-text v3 config weighs every code point from U+0000 to U+10FF at 1, and in Unicode’s block list that range runs from Basic Latin through Greek, Cyrillic, Arabic, Devanagari, Bengali, Tamil and Thai to Georgian. Dan Koe’s 21 August 2026 explainer on eden.so puts “characters from most other writing systems, including Chinese, Japanese, and Korean” at 2, which holds for Chinese, Japanese and Korean and misses Hindi, Arabic and Russian.

The second gap is that X counts code points, the numbered units Unicode assigns, rather than the letters a reader sees. The Hindi word kshatriya shows as 3 letter clusters and costs 8. Every measured X cost in this post is output from X’s open-source twitter-text library, version 3.1.0, which I ran for this post on 4 November 2026; the script is near the end.

What Is the X Character Limit?

280 weighted characters per post. X’s Counting Characters page, last modified 20 May 2026, says “Posts on X can contain up to 280 characters” and that “not all characters count equally”. Its weights, as the page showed them on 4 November 2026:

Character typeWeightMost per post
Latin, punctuation, common symbols1280
Emojis2140 emojis
CJK (Chinese, Japanese, Korean)2140 characters
Other Unicode2 (default)Varies
Any URL23, “regardless of the original length”
Attached media (via official clients)0

The same page tells developers to “Use the open-source twitter-text library to accurately count characters in your app”, and says length is calculated after Unicode Normalization Form C. Two rows of that table compress the detail: “Other Unicode” says 2 by default, but the config file behind the library weighs large parts of other Unicode at 1, and “punctuation, common symbols” is wider than the config’s weight-1 ranges.

For the LinkedIn equivalent, where LinkedIn states its limits on Help pages and in one blog post, see who states each LinkedIn character limit.

Threads counts differently again: Meta’s API docs cap a post at 500 characters and count each emoji as its UTF-8 bytes, as set out in the Threads character limit by field. For WhatsApp, where Meta’s developer docs state some limits and only guides print the 700-character status figure, see which WhatsApp character limits Meta publishes. Facebook is the opposite case to X: no Meta page I read gives a post maximum, and Meta’s developer docs give a Page’s Description 100 characters, as set out in what Meta states for each Facebook field. YouTube splits one field across two units: its Help page gives a video description 5,000 characters while its Data API counts 5,000 bytes, which the YouTube character limit by field works through for Hindi text.

How X’s Config File Weighs Each Code Point

The docs page links twitter-text’s config folder for “Character weight definitions and Unicode ranges.” Version 3 is the default in the twitter-text 3.1.0 package, and its fields read:

FieldValue in v3.jsonWhat it means
maxWeightedTweetLength280The cap, in weighted units
scale100Weights are stored as hundredths
defaultWeight200Any code point outside the ranges below costs 2
transformedURLLength23Every detected URL costs 23
emojiParsingEnabledtrueAn emoji sequence is counted as one emoji
rangesfour ranges at weight 100These code points cost 1

The four weight-1 ranges, with the characters at each end taken from Unicode’s character database:

Range in the configCode pointsWhat sits there
0 to 4351U+0000 to U+10FFBasic Latin through Georgian, including Latin-1 accents, Greek, Cyrillic, Hebrew, Arabic, the Indic scripts from Devanagari to Malayalam, and Thai
8192 to 8205U+2000 to U+200DEn quad through zero width joiner: the typographic spaces, the zero width space, the zero width non-joiner and the zero width joiner
8208 to 8223U+2010 to U+201FHyphen, en dash, em dash and the curly quotation marks
8242 to 8247U+2032 to U+2037The prime marks

Everything else costs 2. That includes Hangul Jamo, which starts at U+1100, one code point past the end of the first range, along with Chinese and Japanese characters, the currency symbols block and the arrows block.

Advertisements

The 280 Budget by Script, Sample by Sample

For this post I ran each sample through twitter-text’s parseTweet function. Non-Latin samples are described in ASCII here, with their code point counts:

ScriptUnicode blockWeightMost per postSampletwitter-text weightedLength
Latin (English)Basic Latin1280”New post: how X counts characters.” (34 characters)34
HindiDevanagari, U+0900 to U+097F1280namaste, 6 code points6
HindiDevanagari1280kshatriya, 8 code points8
BengaliBengali, U+0980 to U+09FF1280bangla, 5 code points5
TamilTamil, U+0B80 to U+0BFF1280vanakkam, 7 code points7
ArabicArabic, U+0600 to U+06FF1280marhaba, 5 code points5
RussianCyrillic, U+0400 to U+04FF1280privet, 6 code points6
JapaneseCJK Unified Ideographs2140nihongo, 3 characters6
KoreanHangul Syllables2140hangugeo, 3 syllables6
Emojivarious2140the Indian flag, 2 code points2
URLn/a23 eachn/aa 116-character UTM-tagged link23

The edges hold too. 280 repeats of the Hindi letter ka (U+0915) came back valid at 280, and 281 came back invalid. 140 repeats of the Japanese character for “sun” (U+65E5) came back valid at 280, and 141 came back invalid at 282. 140 Indian flags, 280 code points in all, came back valid at 280.

Bar chart of the most characters per X post by script: 280 for English, French and Spanish, 280 for Hindi, Bengali and Tamil highlighted, 280 for Arabic, Cyrillic and Greek, 140 for Chinese, Japanese and Korean, 140 for emoji, with a note that every link costs 23, including a 116-character UTM link and x.com

Hindi Conjuncts: Code Points vs Visible Letters

X weighs code points, and Hindi spends several code points on one visible letter cluster. kshatriya is 8 code points: U+0915 U+094D U+0937 U+0924 U+094D U+0930 U+093F U+092F. Two of them are U+094D, the Devanagari sign virama, which joins consonants into a conjunct, and one is U+093F, the vowel sign i.

WordCode pointsLetter clusters (Intl.Segmenter, Node 22)X cost (twitter-text)
kshatriya838
namaste636
family emoji (man, woman, girl, boy)712

The clusters column comes from Node’s Intl.Segmenter with ICU 78.3, which splits each word into the units a reader takes in. Emoji go the other way: X’s emoji counting rules say “Zero-width joiners (ZWJ) combine emojis visually but don’t add to the count”, and the 7-code-point family sequence costs 2.

For Hindi copy, the practical rule is to budget by code points:

  • Each consonant, vowel sign, virama and nasal sign is one code point and costs 1.
  • A conjunct such as ksha (U+0915 U+094D U+0937) costs 3, though it reads as one letter.
  • A Hindi post still gets the full 280 code points, against 140 characters for a post in Japanese.

Yes, at 23 characters per link, whatever the URL’s length. X’s URL handling rules say “All URLs are wrapped with t.co shortener and count as 23 characters” and that this “applies to any valid URL detected in post text.” In twitter-text:

Link as typedIts lengthX cost
https://swapbiswas.com/blog/x-character-limit/?utm_source=x&utm_medium=social&utm_campaign=t1_launch_webinar_2026-0911623
https://x.com1323
swapbiswas.com, typed with no https://1423
x.com, typed with no https://523

For a marketer, a UTM string costs nothing extra on X: the full source, medium and campaign tags fit at no cost, and the rules for naming them are in my campaign naming convention. A domain typed as plain text, with no https://, is detected as a link too, so naming your site in the copy costs 23 even when it is 5 letters long.

A launch post with one tagged link, worked through in twitter-text:

PartTextCost
Copy”Our launch webinar is live. Save your seat: “44
Linkthe 116-character UTM link above23
Hashtag, with a space either side” #B2BSaaS “10
Emojirocket2
Total79, leaving 201 of 280

The prompt for a 280-character tweet in my ChatGPT prompts for marketing needs the same arithmetic when the tweet carries a link: ask for 256 characters of text, since a space and the link add 24. The image X shows on that link’s card is a separate question, and my OG image size checks cover what X’s docs do and do not publish about it.

Do Spaces, Emoji, Hashtags and Mentions Count?

All four count. X’s special cases list sets out two exceptions: @mentions auto-populated at the start of a reply, and attached media.

ItemX’s ruletwitter-text result
Spaces and line breaksWeight 1, like any Basic Latin code point”a”, two spaces, “b”, a line break, “c” = 6
Emoji”All emojis count as 2 characters, regardless of complexity”Flag 2, thumbs up with skin tone 2, family 2
Hashtags”Count normally (# + tag text)“#launch = 7
@mentions you type”count normally""@example hello” = 14
@mentions auto-filled at the start of a reply”don’t count”The library counts whatever string it is given, so leave these out of the string
Attached media”counts as 0 characters” via official clientsNot part of the text
Accented lettersCounted after NFC normalizationcafe with a combining accent (5 code points) = 4

Media costing 0 means an image or video attached through X’s official clients never eats into the 280; for the same post cross-posted to LinkedIn, the image and video specs are in my LinkedIn post size reference.

Symbols That Cost 2, From the Rupee Sign to the Ellipsis

X’s docs put “punctuation, common symbols” at 1, but the config’s weight-1 ranges inside General Punctuation stop at U+201F, apart from the primes. Characters past that fall back to the default of 2, and so do currency signs outside the first range; the dollar, pound and yen signs sit inside it and cost 1:

CharacterCode pointUnicode blocktwitter-text cost
Em dashU+2014General Punctuation1
Right single quotation mark (curly apostrophe)U+2019General Punctuation1
BulletU+2022General Punctuation2
Horizontal ellipsisU+2026General Punctuation2 (three typed dots cost 3)
Indian rupee signU+20B9Currency Symbols2
Euro signU+20ACCurrency Symbols2
Rightwards arrowU+2192Arrows2
e with circumflex and dot below, as in Vietnamese “Viet”U+1EC7Latin Extended Additional2 (the word costs 5)

For Indian pricing copy, the rupee sign followed by 1,999 cost 7, against 8 for “Rs 1,999” with its space. A list pasted with U+2022 bullets costs 2 per bullet, while a hyphen used as a bullet costs 1.

Advertisements

Does X Premium Increase the Character Limit?

X’s own API docs confirm long posts exist without stating their cap. X’s data dictionary describes a note_tweet object that “Contains the full text of a Post for long-form Posts (>280 characters)”, and gives None, Basic, Premium and PremiumPlus as example values of a user’s subscription_type. X’s Help Center page on X Premium, help.x.com/en/using-x/x-premium, answered a plain request made for this post on 4 November 2026 with a 403 and a “Just a moment…” browser check, so I cannot quote X on which tiers get long posts or how long they run.

The guides I read disagree:

GuideDate on the pageLong-post figureTiers it names
Dan Koe, eden.so21 August 202625,000”on any Premium tier”; calls 4,000 “the 2023 launch number”
Vadym Petryshyn, PostoryLast checked 31 August 202625,000”any paid X tier allows 25,000”
FreeQuickUtility Team15 May 202625,000Rows for “X Premium (Blue)” and “X Premium+”; no row for Basic
UtilHQ Team4 January 20264,000”Premium subscribers can write up to 4,000 characters”

twitter-text does not cover long posts: v3.json holds one maximum, 280, and the library marked a 281-letter string invalid. Treat any long-post figure as a guide’s claim until X’s Help Center can be read.

Twitter Character Limit History in X’s Old Configs

The twitter-text config folder keeps the earlier counting rules next to v3:

ConfigCapWeightsURLs
v1.json140Every character 1 (scale 1, default weight 1, no ranges)23
v2.json280The same four weight-1 ranges as v3, default 223
v3.json280Same as v223, plus “emojiParsingEnabled”: true

The move from v1 to v2 is the move from a flat 140 to a weighted 280. What v3 adds is emoji parsing: run under the v2 config, twitter-text counts the family sequence as 11 and the Indian flag as 4, against 2 each under v3.

Count a Post Yourself in Node

The npm registry lists twitter-text 3.1.0 as the latest version, published on 31 March 2020, and X’s docs still name it as “the official twitter-text library” on the implementation section. Install it with npm install twitter-text in an empty folder, save this as count.cjs and run node count.cjs:

const { parseTweet } = require('twitter-text');
const cp = (...c) => String.fromCodePoint(...c);
const kshatriya = cp(0x915, 0x94D, 0x937, 0x924, 0x94D, 0x930, 0x93F, 0x92F);
const link = 'https://swapbiswas.com/blog/x-character-limit/?utm_source=x&utm_medium=social&utm_campaign=t1_launch_webinar_2026-09';
const tests = { kshatriya, nihongo: cp(0x65E5, 0x672C, 0x8A9E), flag: cp(0x1F1EE, 0x1F1F3), rupee: cp(0x20B9), link, 'x.com': 'x.com', ka281: cp(0x915).repeat(281) };
for (const [name, s] of Object.entries(tests)) { const r = parseTweet(s); console.log(name, r.weightedLength, r.valid); }

The output on Node 22, 4 November 2026:

kshatriya 8 true
nihongo 6 true
flag 2 true
rupee 2 true
link 23 true
x.com 23 true
ka281 281 false

String.fromCodePoint builds the Hindi, Japanese and flag strings from their code point numbers, so the script runs the same in any editor. Swap in your own post text and read weightedLength against 280.

Recheck the X Character Limit Each Quarter

X last modified its Counting Characters page on 20 May 2026, the latest twitter-text release on npm dates from March 2020, and the X Premium page in X’s Help Center returned a browser check to a 4 November 2026 request made for this post. Recheck all three each quarter: a new config version would change the weights, and a readable Help Center page would settle the long-post figure.

Until then, the X character limit is 280 weighted units per X’s own config, with Hindi, Bengali, Tamil, Arabic and Cyrillic at 1 per code point, Chinese, Japanese, Korean and emoji at 2, and every link at 23. Run your next Hindi or emoji-heavy post through parseTweet before you publish it.

Next read Threads Character Limit: 500 Per Post, 10,000 Attached The Threads character limit is 500 per post and 10,000 in a text attachment. Here is each Threads field, its limit, and whether Meta or only a guide states it.

Frequently Asked Questions

Does a link count toward the character limit on X?

Yes. X's developer docs say every URL counts as 23 characters, whatever its length. In X's twitter-text library, a 116-character UTM-tagged link and the bare domain x.com each counted as 23.

Do spaces count in an X post?

Yes. A space weighs 1, the same as a letter, and so does a line break. twitter-text counted the string a, two spaces, b, a line break and c as 6.

How many characters can you post in Hindi on X?

280. Devanagari sits inside the code point range X's twitter-text config weighs at 1, and twitter-text marked 280 Hindi code points valid and 281 invalid. Count code points, not the letters you see: the 8-code-point word kshatriya costs 8.

Do emojis count as 2 characters on X?

Yes. X's docs say all emojis count as 2 regardless of complexity, and twitter-text counted a flag, a skin-tone thumbs up and a 7-code-point family emoji at 2 each.

Does X Premium increase the character limit?

X's API data dictionary describes long-form posts of more than 280 characters, but X's Help Center page on X Premium was not readable on 4 November 2026. Guides disagree: eden.so says 25,000 on any Premium tier and Postory says 25,000 on any paid tier, while UtilHQ says 4,000.

Advertisements
Swapnil Biswas

Written by Swapnil Biswas

Senior Product Marketing Manager at TestMu AI

I write the brief. Then I build it. I love AI enough to build the tools and automations I market with.