Bluesky

Bluesky Character Counter

Bluesky gives you exactly 300 graphemes per post — and if you've ever hit a mysterious "Post is too long" error when your draft looked perfectly short, this tool is what you were missing. It counts graphemes the exact way Bluesky's AT Protocol does, so what you see here is what Bluesky's servers will accept or reject.

Every field you write on Bluesky is covered: posts (300 graphemes), your bio (256), your display name (64), direct messages (1,000), image and video alt text, and pronouns. No account needed, no ads, no waiting.

This counter uses Intl.Segmenter, the same grapheme segmentation the AT Protocol itself now uses natively — Bluesky replaced its older graphemer-based counting with Intl.Segmenter to fix a Devanagari counting bug. It is the only type of counter that gives you an accurate count for emoji, accented characters, and non-Latin scripts — a counter that counts characters or bytes will give you a different, incorrect number for emoji-heavy or multilingual posts.
0 / 300
graphemes
0words
0lines
0emoji
0 / 3,000utf-8 bytes
ℹ️ Bluesky counts graphemes, not characters. Every emoji — including complex family, flag, and skin-tone emoji — counts as 1 grapheme. This is more generous than Twitter/X where emoji count as 2 characters.
ℹ️ URLs pasted as plain text count at their full grapheme length — Bluesky has no t.co wrapper, and the "URLs count as 22 characters" claim you may have read is a Twitter leftover. The official app does shorten long-path display text before counting: check any link with the URL cost estimator below.
URL cost estimator — what the official Bluesky app counts
0 / 64 graphemes
0 / 640bytes
Display name supports emoji and any Unicode characters. Many users include credentials, pronouns, or emoji in their display name.
0 / 256 graphemes
0 / 2,560bytes
Your Bluesky bio supports plain text only — no bold, italic, or rich formatting. URLs in your bio count at full grapheme length with no shortening, and line breaks cost 1 grapheme each.
0 / 20 graphemes
0 / 200bytes
The pronouns field (20 graphemes, 200 bytes) is defined in the AT Protocol's app.bsky.actor.profile lexicon. The official app hasn't surfaced it in its profile editor yet — third-party clients and browser extensions already read it.
0 / 1,000 graphemes
0words
0 / 10,000utf-8 bytes
Bluesky DMs allow up to 1,000 graphemes — over 3x the post limit. DMs use the same grapheme counting method as posts.
0 / 2,000 graphemes
The official Bluesky app allows 2,000 graphemes of alt text per image, and posts can carry up to 4 images. The AT Protocol lexicon itself sets no cap — 2,000 is an app-level limit, raised from 1,000 after accessibility feedback.
0 / 2,000 graphemes
Video alt text shares the same 2,000-grapheme app-level cap as images and GIFs. The app.bsky.embed.video lexicon previously capped it at 1,000 graphemes, but that cap was removed — the official app now enforces the same limit it uses for image alt text.
Each post in a Bluesky thread gets its own independent 300-grapheme budget — there is no overall thread length limit. The splitter breaks at sentence boundaries first, then word boundaries, so no post ever exceeds 300 graphemes.
Your text never leaves your browser. Nothing is uploaded or stored.

Every Bluesky Character Limit in One Place

Read directly from the official AT Protocol lexicons at bluesky-social/atproto on GitHub

Bluesky enforces different limits for different fields. The grapheme limit is the number you will feel every time you write. The byte ceiling is a secondary backstop that only activates when you write post text heavy with complex emoji or non-Latin scripts.

Field Grapheme Limit Byte Ceiling Notes
Post 300 3,000 bytes Same limit for posts, replies, and quote posts
Bio (profile description) 256 2,560 bytes Front-load your niche and value in the first line
Display name 64 640 bytes Separate field from your handle
Direct message 1,000 10,000 bytes chat.bsky.convo.defs lexicon
Hashtag (each) 64 640 bytes Includes the # symbol
Image alt text 2,000 No protocol cap App enforces 2,000; the lexicon has no cap
Video alt text 2,000 No protocol cap App-level limit, same as images — the lexicon cap was removed
GIF alt text 2,000 No protocol cap Same app-level limit as image and video alt
Pronouns 20 200 bytes app.bsky.actor.profile lexicon
Handle (.bsky.social prefix) 3–18 chars DNS rules Left label before .bsky.social
Handle (custom domain) 253 chars total DNS rules Each label max 63 chars per DNS spec
List name No grapheme cap 64 bytes The only Bluesky field measured in bytes only
Feed name 24 240 bytes app.bsky.feed.generator lexicon
Starter pack name 50 500 bytes app.bsky.graph.starterpack lexicon
List, feed & starter pack descriptions 300 3,000 bytes Same cap across all three lexicons
DM group chat name 50 No byte cap App-level limit (MAX_GROUP_NAME_GRAPHEME_LENGTH)
Composer draft 1,000 No byte cap App-level limit per drafted post (MAX_DRAFT_GRAPHEME_LENGTH)
Report reason 2,000 No byte cap App-level limit (MAX_REPORT_REASON_GRAPHEME_LENGTH)
Tags array (hidden tags) 8 tags max N/A Separate from inline hashtags in text
Post languages 3 languages max N/A app.bsky.feed.post lexicon
Media per post 4 images or 1 video 2 MB per image · 300 MB video Videos up to 10 minutes in the official app

Four fields deserve a special note because they catch people off guard. List names are capped in bytes, not graphemes — the only field in this table without a grapheme allowance. 64 bytes is 64 Latin characters but only about 21 Japanese or Chinese characters, so a list name that fits in English may fail in translation. Image alt text has no protocol limit in the lexicon, but the official Bluesky app sets a 2,000-grapheme cap based on user feedback.

The hidden tags array (8 tags max) is separate from the hashtags you type inline in your post text. Those inline hashtags only consume your 300 graphemes. The 8-tag limit applies to a separate metadata field the official app does not expose to users yet. And the rate limit budget is 5,000 points per hour and 35,000 points per day, with each post creation costing 3 points — a theoretical ceiling of about 1,666 posts per hour — per the official Bluesky protocol services documentation. Plan scheduled content around the point budget, not a fixed post count.

All Bluesky Character Counters

Dedicated counters for every Bluesky field

You are here
Bluesky Character Counter
Count posts, replies, bios, display names, DMs, alt text, and threads against Bluesky's exact grapheme limits — with a URL cost estimator and thread splitter built in.
300 graphemes per post
Bluesky Bio Counter
Stay within the 256-grapheme bio limit. Plan your one-liner, proof line, and CTA line for your Bluesky profile.
256 graphemes

What Is a Grapheme and Why Bluesky Measures Them Instead of Characters

A grapheme is one unit of text as a human perceives it. It is defined by Unicode Standard Annex #29 (UAX #29) as the smallest visible unit of a written language. The word "character" is ambiguous: to a JavaScript engine, "character" usually means a UTF-16 code unit. To a server, it might mean a UTF-8 byte. To a human being reading a screen, it means a single visible symbol.

Bluesky chose graphemes deliberately. The AT Protocol's app.bsky.feed.post lexicon specifies two simultaneous ceilings: maxGraphemes: 300 and maxLength: 3000 (bytes). Whichever ceiling you hit first, your post is rejected. For almost every writer in a Latin alphabet, the 300-grapheme limit is the only constraint you will ever encounter. The 3,000-byte ceiling is a backstop for extreme cases: 300 family emoji ZWJ sequences (each one grapheme but 25 UTF-8 bytes) would total 7,500 bytes, exceeding the byte cap long before reaching 300 graphemes.

This is why a naive character counter gives you the wrong number for emoji-heavy posts, and why that wrong number causes real post failures. Bluesky enforces its limits at the API level, not just in the composer UI. A post that looks fine in a counter that measures bytes or code units can be silently rejected when it hits Bluesky's servers.

What Each Character Type Costs on Bluesky

Character Type Graphemes UTF-8 Bytes Example
Latin letter, number, space, punctuation 1 1 a, 5, ?, space
Accented letter (precomposed) 1 2 é, ñ
CJK character (Chinese, Japanese, Korean) 1 3 語, か, 한
Basic emoji 1 4 🙂, 🚀, ✨
Flag emoji (regional indicator pair) 1 8 🇵🇰, 🇯🇵
Skin-tone modified emoji 1 8 👋🏽
ZWJ sequence (family, professional) 1 25+ 👨‍👩‍👧‍👦, 🧑🏽‍💻
Line break (newline) 1 1 Each newline in post text

The practical consequence: a post written entirely in Japanese kanji can contain 300 full Japanese characters and be a valid Bluesky post. That same 300 characters costs 900 UTF-8 bytes but is still well under the 3,000-byte cap. Compare that to a post with 300 family emoji ZWJ sequences: 300 graphemes but 7,500 bytes. In that extreme case, you would hit the 3,000-byte cap at roughly 120 graphemes. Real-world posts almost never approach either extreme. Standard text with a handful of emoji hits the grapheme limit first, every time.

The graphemer Library vs. Intl.Segmenter: The Counting Discrepancy Bluesky Already Fixed

One edge case worth knowing, because older guides still cite it as an open problem: the AT Protocol's server-side validation originally used a JavaScript library called graphemer for its grapheme counting, and graphemer follows an older version of the Unicode segmentation rules than modern browsers do. For most scripts the two produce identical counts. But for some Indic scripts (Hindi, Bengali, Tamil), a single visible conjunct cluster could count as 3 graphemes under graphemer and as 1 in Intl.Segmenter, the current standard used by browsers and the official Bluesky app. The mismatch was documented as issue #4321 in the bluesky-social/atproto repository, opened October 30, 2025.

Bluesky has since fixed it. The AT Protocol's validation code now uses Intl.Segmenter directly, with the unicode-segmenter package — which also follows current Unicode — as its fallback for older environments. Server-side counting and browser-side counting now agree, including for Devanagari and other Brahmic scripts. The practical upshot: a counter built on Intl.Segmenter, like this one, matches the protocol's own counting, which is exactly the standard we count with.

Do URLs Count Toward the Bluesky Character Limit?

Yes, URLs count toward your 300-grapheme budget. But the exact cost depends on how you paste them, and this is the single most useful piece of practical knowledge for any Bluesky content creator. There are three distinct scenarios, and most guides only describe one of them.

Scenario 1: URL as plain text in your post body

When you paste a URL directly into a Bluesky post and do not generate a link card, the URL counts at its full grapheme length, approximately one grapheme per character for standard ASCII URLs. A UTM-tagged tracking URL like https://textcountify.com/article?utm_source=bluesky&utm_medium=social&utm_campaign=launch2026 is 93 characters long. That single URL consumes almost one third of your entire 300-grapheme post budget.

Scenario 2: URL as shortened display text in the official Bluesky app

The official Bluesky app at bsky.app runs a link-shortening function before counting your graphemes. If a URL's path runs longer than 15 characters, the app rewrites the display text to: domain + first 13 characters of path + ellipsis. The full URL is preserved in the rich-text facet (so the link still works), but the composer counts the shortened display text against your 300.

This means URL cost on Bluesky is variable, based on your domain length, not fixed at 22 or 23 characters. Those numbers come from Twitter's t.co shortening logic. Bluesky has no equivalent of t.co.

URL Raw Length Cost After App Shortening
https://bsky.app 16 chars 8 graphemes (short path, no shortening)
https://bsky.app/about 22 chars 14 graphemes (path under 15, no shortening)
https://textcountify.com/bluesky-character-counter 50 chars 32 graphemes
https://example.com/article?utm_source=bluesky&utm_campaign=launch 66 chars 27 graphemes

Third-party Bluesky clients do not all apply this shortening. Some count the raw URL against your grapheme budget. Your post may appear over the limit in a third-party scheduler but succeed perfectly on bsky.app. When in doubt, check your final count in the official Bluesky composer before concluding your post is too long.

Scenario 3: The link card technique (zero grapheme cost)

Pro Tip: Paste your URL into the Bluesky post composer. Wait for the link card preview to appear (the card showing the page title, thumbnail, and description). Then delete the URL text from the post body. The link card stays attached to your post. The URL is now costing you zero graphemes, and your full 300-grapheme budget is free for your actual message.

The link card is stored as an embedded record in the post, not as text in the post body. Deleting the URL from the text does not remove the card. Your post goes out with a rich preview and a zero-grapheme URL cost. For any post that includes a link, this technique should be your default workflow.

Important: The "URLs count as 22 characters" claim you will see on some Bluesky character counter pages is borrowed from Twitter's t.co shortening rule. It does not apply to Bluesky. Bluesky has no equivalent of t.co. Using that figure will give you a miscounted budget.

Bluesky vs Other Platforms: Character Limit Comparison

If you are coming from Twitter/X, Threads, or any other platform, here is exactly how Bluesky's limits compare for the same type of content.

Platform Post Limit How It Counts Key Notes
Bluesky 300 graphemes Unicode graphemes (UAX #29) Equal limit for all users, no paid upgrade
Twitter/X (free) 280 characters Weighted character units CJK = 2 units, emoji = 2 units
Twitter/X Premium 25,000 characters Weighted character units Paid tier only
Threads 500 characters Characters Meta platform, no grapheme distinction
Mastodon 500 characters (default) Characters Server-dependent, some servers allow more
LinkedIn 3,000 characters Characters More generous for long-form posts
Instagram 2,200 characters Characters Feed truncates long posts at roughly 125 characters
Discord 2,000 characters Characters Per message limit
Reddit (post body) 40,000 characters Characters Essentially unlimited for practical purposes
Facebook 63,206 characters Characters No practical limit for most content

Why Bluesky's 300 Graphemes Feels Bigger Than Twitter's 280 Characters

The headline numbers are 300 vs 280. The practical difference is larger, especially for emoji-heavy writers and non-Latin writers.

Emoji: On Twitter, an emoji counts as 2 character units. On Bluesky, any emoji, including a complex ZWJ family sequence, counts as 1 grapheme. A post with 10 emoji has 10 more usable units on Bluesky than on Twitter for the same visual content.

CJK and non-Latin scripts: Twitter weights Japanese, Chinese, and Korean characters at 2 units each. On Twitter's free tier, a post written entirely in Japanese effectively has a 140-character equivalent limit. On Bluesky, a Japanese character costs 1 grapheme, same as a Latin letter. A full 300-grapheme Japanese post is valid. This is one of Bluesky's most significant but least discussed advantages for non-English writers and global brands.

No paid upgrade to unlock more: Twitter charges for 25,000 characters per post. Bluesky's 300-grapheme limit is equal for all users. This is a deliberate design principle of the AT Protocol, not a business limitation. The intended answer for longer thoughts is native threads, where each post gets its own 300-grapheme budget.

How Long Are Bluesky Posts in Practice?

In a sample of 2,135 real Bluesky posts from 264 accounts, analyzed in July 2026 via the public app.bsky.feed.getAuthorFeed endpoint, the numbers tell a different story than the anxiety around the 300-grapheme limit suggests.

Metric Finding
Median post length 117 graphemes
Posts at 140 graphemes or fewer 55.6% of all posts sampled
Posts at 280 graphemes or more 12.2% of all posts sampled
Posts that actually hit the 300-grapheme ceiling 1.6% of all posts sampled
Accounts with no bio at all 52.2% (from a separate 3,712 account sample)
Median bio length (among accounts that wrote one) 118 graphemes (out of 256 available)

The practical conclusion: the 300-grapheme limit is almost never the actual constraint for most writers. Over half of Bluesky posts would have fit inside Twitter's pre-2017 140-character limit. The limit becomes relevant mostly for content marketers crafting dense, link-plus-hashtag posts, non-Latin writers with longer words, or anyone trying to squeeze a full thought into one post instead of a thread.

The bio data is more striking. More than half of all Bluesky accounts have no bio. Among accounts that wrote one, the median was 118 graphemes of the 256 available. If you have a bio at all, and it is over 50 graphemes, you are already ahead of the majority of the platform. That is not a motivational statement; it is what the data from 3,712 real accounts shows.

Budgeting Your 300 Graphemes: URLs, Mentions, and Hashtags

Every element in your post consumes graphemes from the same 300-unit budget. Here is how to plan before you write.

Mentions

A mention like @alice.bsky.social is 18 graphemes. The full handle, including the @ symbol and the .bsky.social domain suffix, counts in full. Long custom domain handles can be even more expensive: @their-full-name.journalist.com might cost 30 or more graphemes before you have written a single word of your actual message. When you need to mention multiple people with long handles, consider using one mention and tagging others in a reply post.

Hashtags

A hashtag counts at its full grapheme length including the # symbol. #BlueskyTips is 12 graphemes. #SocialMedia is 12 graphemes. Two standard-length hashtags at the end of a post consume roughly 25 to 30 graphemes before you account for the space before each one. If you routinely add two or three hashtags, budget 30 to 45 graphemes for them and write your core message within the remaining 255 to 270 graphemes.

One well-chosen hashtag consistently outperforms three generic ones for discoverability. Hashtags on Bluesky are detected automatically from your post text as rich-text facets. There is no separate hashtag field. Whatever you type with a # prefix becomes a tagged link, consuming its full grapheme length from your budget.

Line breaks

Each line break in your post costs 1 grapheme. A post with ten short punchy lines (a common Bluesky style) uses 9 graphemes in line breaks alone. Posts over 25 lines are collapsed behind a "Show more" fold in the Bluesky feed, a behavior defined in the app source as MAX_POST_LINES = 25. This is not a character limit. Your text is fully there; readers just need to tap to see it. But if engagement matters, front-loading your hook before line 26 matters more than total character count for this style of writing.

Pro Tip: Budget your 300 graphemes before you write: set aside your URL cost (0 graphemes if you use the link card technique), your mention costs (18+ per handle), your hashtag costs (12 to 15 per tag), and your line break count. Write the core message in whatever remains. For a post with one link card, two short hashtags, and one mention, your real writing budget is roughly 255 graphemes.

Cross-Posting to Bluesky from Twitter, Threads, and Other Platforms

Bluesky's 300 graphemes sits between Twitter's 280 and Threads' 500. Here is what that means for each cross-posting workflow.

Twitter/X to Bluesky

A tweet at 280 characters almost always fits in a Bluesky post. The 20-grapheme difference is a comfortable buffer for most content. The exceptions are emoji-heavy posts: because Twitter counts emoji as 2 units and Bluesky counts them as 1 grapheme, a tweet at exactly 280 units that contains 10 emoji is actually only 270 graphemes on Bluesky (10 of those Twitter units were the second half of emoji pairs). These posts fit even more comfortably on Bluesky than they did on Twitter.

The risk direction is reversed: a tweet with heavily accented text or Indic script characters may fit on Twitter's weighted system but behave differently on Bluesky's grapheme count depending on which Unicode rules apply. Run every cross-post through the Twitter character counter and this Bluesky counter before assuming it transfers cleanly.

Threads to Bluesky

Threads allows 500 characters. Any Threads post over 300 characters needs editing for Bluesky. Common adaptation strategies: cut secondary context that is not essential to the hook, replace long calls to action with short ones, move hashtags to the end so they can be cut first if needed, and split longer posts into Bluesky threads where each post gets its own 300-grapheme budget. Our Threads character counter applies the same live check on the Threads side.

LinkedIn to Bluesky

LinkedIn posts can run to 3,000 characters. Adapting a LinkedIn post for Bluesky almost always means extracting the core argument or hook into one 300-grapheme post, linking to the full LinkedIn post with a link card (zero grapheme cost), and letting readers click through for the full text.

Bluesky Bio and Display Name: Making the Most of 256 and 64 Graphemes

The bio (256 graphemes)

Your Bluesky bio is your most-read content after your display name. It supports up to 256 graphemes. Compared to Twitter's 160-character bio and Instagram's 150-character bio, 256 graphemes is generous. But given that 52% of Bluesky accounts have no bio and the median bio is 118 graphemes, the ceiling is not the challenge. Deciding what to put there is.

Front-load your bio. The first line is what appears in profile previews before a reader taps to expand. Put your niche, role, or value proposition in the first 60 graphemes. Use the remaining space to add specifics, a call to action, or a link (which counts at full grapheme length in the bio, unlike the link card trick in posts). Line breaks count as 1 grapheme each. Bluesky bios support plain text only: no bold, no italic, no markdown formatting. For counted bio templates, a live search snippet preview, and link cost variants for the same 256 grapheme budget, use our dedicated Bluesky bio character counter.

The display name (64 graphemes)

Your display name is the bold name above your handle in the feed. 64 graphemes is enough for "First Last" plus a short descriptor or emoji. Emoji in your display name count as 1 grapheme each. A verification checkmark emoji, a flag, and a short tagline can all coexist comfortably within 64 graphemes. The display name is not your handle: it can contain spaces, emoji, and any Unicode character. Your handle has stricter rules (see the handle section below).

Bluesky Handle Character Limits and Custom Domain Verification

Standard handles (.bsky.social)

The left-label portion of a standard .bsky.social handle (the part before .bsky.social) must be between 3 and 18 characters. It can contain lowercase letters, numbers, and hyphens only. No underscores, no spaces, no capital letters, no special characters beyond hyphens. The full handle including the domain suffix can be up to 253 characters total, following standard DNS length rules.

Handles are case-insensitive in the AT Protocol, meaning @alice.bsky.social and @Alice.bsky.social resolve to the same account. But the convention is all lowercase. When you mention someone with a long handle, you pay the full grapheme cost in your post text.

Custom domain handles: Bluesky's unique identity verification feature

Bluesky is the only major social platform where you can use your own domain name as your handle, and doing so constitutes verified identity at the protocol level, with no application, no follower threshold, and no fee.

The mechanism is a DNS TXT record. You add _atproto.yourdomain.com as a TXT record pointing to your Bluesky DID, then set your handle to @yourdomain.com. Anyone who visits your profile and sees that handle can verify your identity by checking that the DNS record exists. A journalist whose handle is @nytimes.com is verifiably the New York Times account. A developer whose handle is @saif.dev is verifiably linked to that domain.

Custom domain handles follow standard DNS rules: the full handle can be up to 253 characters total, and each dot-separated segment (label) can be up to 63 characters. This is a meaningfully different constraint than the 3 to 18 character limit of the .bsky.social label. There is no other major social platform where brand and individual verification works this way.

Bluesky Threads: Writing Long-Form Content Within the 300-Grapheme Limit

When your idea does not fit in 300 graphemes, threads are the native answer. Each post in a Bluesky thread gets its own independent 300-grapheme budget. There is no overall thread length limit. A thread can be as long as you need.

Replies do not share a character budget with the original post. Post 1 gets 300 graphemes. Post 2 gets another 300. Post 10 gets another 300. The budget resets per post, not per thread. A ten-post thread gives you up to 3,000 graphemes of total content, presented as a cohesive narrative.

Strong thread structure follows a simple rule: each post should work as a standalone unit. Do not cut a sentence mid-thought across two posts. End each post with enough momentum that a reader who encounters it mid-scroll still wants to continue. Front-load post 1 with the hook: the most compelling sentence goes first, because that is what determines whether readers tap to expand the thread.

Quote posts follow the same 300-grapheme limit as standalone posts. When you quote someone else's post, your commentary must fit in 300 graphemes. The quoted post is embedded separately and does not consume your grapheme budget.

Why Bluesky Has a 300-Grapheme Limit

Bluesky's 300-grapheme limit is not arbitrary and it is not a legacy decision inherited from Twitter's 140-character era. It is a deliberate constraint embedded in the AT Protocol, the open, decentralized protocol that powers Bluesky. The AT Protocol is designed to be run by many different operators, not just Bluesky Social PBC. Keeping post records small reduces the storage and bandwidth requirements for every server in the federated network.

The limit applies equally to all users by architectural design. Unlike Twitter/X, there is no paid tier that unlocks more characters. One of the most-supported feature requests on the AT Protocol GitHub (issue #2551, opened June 2024) asks for a limit increase to 500. It remains open with no resolution. Bluesky's data suggests why: fewer than 2% of posts actually hit the ceiling. The intended tool for longer thoughts is the thread.

There was one announced change: on April 1, 2025, Bluesky jokingly announced it was lowering the limit to 299 characters for one day. That post still ranks in search results for "Bluesky character limit" questions. The limit has been and remains 300 graphemes.

Bluesky in 2026: Why the Character Limit Matters More Now

Bluesky has grown significantly. The platform reached 46 million registered users by August 2026, up from roughly 10 million in September 2024. Daily active users are estimated at roughly 3 to 3.5 million, and TechCrunch reported 10.4 million monthly active users on the Bluesky mobile app in June 2026, as the platform's focus expands beyond text posts. The United States accounts for the largest share of users, followed by Japan and Brazil.

The migration cohort matters for content strategy. Former Twitter/X users, including journalists, academics, developers, and tech-adjacent professionals, form the dominant growth segment. The Boston Globe reported 3 times more traffic referrals from Bluesky than from Threads, and 4.5 times more conversions to paying digital subscribers. These are not casual scrollers. They read, click, and subscribe.

The average bsky.app session lasts 7 minutes and 37 seconds with 5.41 pages per visit, per SimilarWeb estimates from mid-2026. Users are engaged. Writing carefully within 300 graphemes for this audience is not a formatting constraint. It is how you reach an audience that responds to good writing.

How to Use the Bluesky Character Counter

The tool is divided into five tabs — Post, Profile, DM, Alt Text, and Thread Splitter — each with its own text areas, a live grapheme counter, and a color-coded progress indicator. Here is what each one does.

  • Post tab (300-grapheme limit). Type or paste your Bluesky post draft. The counter shows graphemes used against the 300 limit, with words, lines, an emoji breakdown, and a live UTF-8 byte readout of the 3,000-byte backstop ceiling alongside. Drafts that run past 25 lines get a fold warning, because the Bluesky feed collapses long posts behind a "Show more" link and Bluesky's own composer blocks posting at 301 graphemes. The URL cost estimator underneath shows exactly what the official app will count for any link you paste.
  • Profile tab (display name 64, bio 256, pronouns 20). The three text fields of a Bluesky profile, side by side. Remember that line breaks in your bio cost 1 grapheme each and that profile previews typically show only the first line.
  • DM tab (1,000-grapheme limit). Check longer direct messages before sending. The DM tab also shows word count.
  • Alt Text tab (image, GIF, and video alt text — 2,000 each). Write and measure alt text against the accessibility limit before you attach media. Images, GIFs, and videos all share the same 2,000-grapheme app-level cap.
  • Thread Splitter. Paste a long draft and it splits into 300-grapheme posts at sentence boundaries, each with its own copy button — the fastest way to turn a long passage into a Bluesky thread.

Each tab has a Copy button that copies the current text to your clipboard and a Clear button that resets the field. The tool works on desktop and mobile. Dark mode is supported and remembers your preference. And as with everything on TextCountify, your text never leaves your browser.

Frequently Asked Questions

Common questions about Bluesky's grapheme limits and how counting works

The Bluesky post character limit is 300 graphemes per post. A grapheme is one unit of text as a human perceives it (defined by Unicode Standard Annex #29). This limit applies equally to original posts, replies, and quote posts. There is a secondary ceiling of 3,000 UTF-8 bytes, but for standard text and typical emoji use, the grapheme limit is the only one you will encounter.
Bluesky counts graphemes, not characters. The AT Protocol's post schema specifies maxGraphemes: 300, not maxLength in characters. This distinction matters because one emoji, regardless of how complex, counts as 1 grapheme. A naive character counter will give you a different, often incorrect count for emoji-heavy or multilingual posts.
Yes. On Bluesky, every emoji counts as 1 grapheme, including complex ZWJ sequences (family emoji, skin-tone modified emoji, professional emoji with modifiers), flag emoji (which are two regional indicator symbols internally), and multi-codepoint emoji. This is more generous than Twitter, which counts emoji as 2 character units each.
This usually happens when you used a counter that measures raw characters or bytes instead of graphemes. Bluesky enforces its limits at the API level, not just in the composer UI. A post that appears fine in a non-grapheme-aware counter can be rejected by the server if it contains complex emoji or non-Latin characters that count differently. Use a counter that explicitly uses grapheme counting (like Intl.Segmenter) to avoid this.
Yes, but the cost depends on how you use them. A URL pasted as plain text counts at its full grapheme length. In the official Bluesky app, the URL display text is shortened to domain plus the first 13 characters of the path plus an ellipsis (for paths over 15 characters), and the composer counts that shortened form. The most efficient technique: paste your URL, wait for the link card to appear, then delete the URL from the post body. The link card stays and your URL costs zero graphemes from your post budget.
No. That rule comes from Twitter's t.co link shortening system. Bluesky has no equivalent of t.co. URLs on Bluesky cost their actual display length, which is variable based on your domain name, not a fixed 22 or 23 characters.
The Bluesky bio (profile description) allows up to 256 graphemes with a secondary ceiling of 2,560 UTF-8 bytes. This is more generous than Twitter's 160-character bio and Instagram's 150-character bio. Bluesky bios support plain text only, no markdown or formatting. Line breaks count as 1 grapheme each. URLs in the bio count at their full grapheme length.
The Bluesky display name allows up to 64 graphemes. It supports emoji, spaces, and any Unicode characters. It is a separate field from your handle and can be updated at any time without changing your handle.
Direct messages on Bluesky allow up to 1,000 graphemes (10,000 UTF-8 bytes). This limit is defined in the chat.bsky.convo.defs lexicon of the AT Protocol.
The official Bluesky app allows up to 2,000 graphemes of alt text per image. The AT Protocol lexicon itself sets no cap on the alt field for images. The 2,000 limit is an app-level decision, and the app's source comments note that WCAG recommends approximately 100 characters but the limit was increased based on user feedback. Video and GIF alt text follow the same 2,000-grapheme app-level limit — the lexicon sets no cap on either.
Yes. Every space counts as 1 grapheme. Every line break counts as 1 grapheme. Punctuation counts. There is no free allowance for any element in your post text. The only way to include a URL without consuming graphemes is the link card technique described above.
Each individual hashtag on Bluesky is limited to 64 graphemes (640 UTF-8 bytes). This includes the # symbol. However, hashtags you type inline in your post also consume graphemes from your 300-grapheme post budget. The 64-grapheme cap per hashtag is a separate lexicon-level rule from the 300-grapheme post cap.
Yes. Bluesky is the only major social platform that supports domain-verified handles. You set a DNS TXT record at _atproto.yourdomain.com pointing to your Bluesky DID, then update your handle to @yourdomain.com. The handle is verified at the protocol level. Custom domain handles follow DNS length rules: up to 253 characters total, with each dot-separated label up to 63 characters.
Bluesky gives free users 300 graphemes. Twitter/X gives free users 280 character units. Twitter's paid Premium tier unlocks 25,000 characters. Bluesky has no paid tier that changes the limit. The practical difference in usable space is larger than 300 vs 280 suggests, because Bluesky counts emoji as 1 grapheme while Twitter counts them as 2 units each.
No indication of a change as of September 2026. The most-supported GitHub issue requesting a limit increase (atproto issue #2551, filed June 2024) has been open for over two years with no resolution. The post-length data suggests why: fewer than 2% of posts actually reach the ceiling. For longer content, Bluesky's answer is native threads, where each post gets its own 300-grapheme budget.
There is no fixed daily post count on Bluesky. The AT Protocol rate limit system is points-based: creating a post costs 3 points, and each account gets a budget of 5,000 points per hour and 35,000 points per day, per the official Bluesky protocol services documentation. That works out to a theoretical ceiling of about 1,666 posts per hour and 11,666 posts per day — far beyond what any human poster approaches. Tools that cite a hard 100-post daily limit are describing their own scheduler setting, not a Bluesky rule.
Saif ul Rehman
Saif — Founder of TextCountify

I built TextCountify because I was tired of switching tabs to check character limits while managing social media content and SEO work. Every limit on this page is verified against official platform documentation monthly. If something is wrong, tell me directly — I read every message.

More about TextCountify →