glossary

How the Bluesky Character Limit Works in Graphemes

Taras Shynkarenko
Taras Shynkarenko
β€’Updated: β€’6 min read
How the Bluesky Character Limit Works in GraphemesHow the Bluesky Character Limit Works in Graphemes

TL;DR

6 min read

The AT Protocol's own lexicon for a Bluesky post, app.bsky.feed.post, sets the Bluesky character limit at 300 grapheme clusters and 3000 UTF-8 bytes per post. A full link or a full @handle counts toward that limit with no shortening, since the protocol stores mentions and links as offsets into the same text rather than as separate objects. A display name is capped at 64 graphemes and a profile description at 256 graphemes, and a thread is built by chaining separate posts through a reply field rather than by extending any single post's limit.

What is the Bluesky character limit?

The Bluesky character limit is exactly 300 grapheme clusters per post, a hard boundary the AT Protocol's own lexicon for app.bsky.feed.post sets directly, alongside a separate cap of 3000 bytes measured in UTF-8, checked 9 September 2026. Both numbers apply to the same field at once, so a post has to fit inside whichever limit it hits first, though a grapheme cap of 300 is the one almost every post reaches before the byte cap becomes relevant. Every post created through Bluesky's official app or through any client built on the AT Protocol has to satisfy both numbers, since the lexicon defines the record format itself rather than a rule any one client chooses to enforce.

A close-up of a phone screen typing an emoji, illustrating how a single visible character can count differently than raw code units.

Which cap binds first
300-grapheme limit
  • Reached first by almost every post
  • Counts the way a reader actually sees the text
3000-byte limit
  • Rarely reached, since most characters use fewer than ten bytes each
  • Only becomes relevant with heavy multi-byte content
Both caps apply to the same app.bsky.feed.post field, but the grapheme cap is the one almost every post hits first.

What is a grapheme, and why does Bluesky count that way?

A grapheme is a single unit of text the way a reader perceives it, which is not always the same as a single character in the way a computer stores that text. The AT Protocol's own client library documentation, published in the @atproto/api package on GitHub, gives the example of a family emoji, "πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘§", which a JavaScript .length check reports as 25 separate units but which the library's .graphemeLength method reports as exactly 1, matching what a person actually sees on screen. Bluesky counts the 300-limit using that second, human-facing method rather than the raw code-unit count a programming language uses internally, which is why an emoji-heavy post can look short and still use meaningfully more of the limit than plain text of the same visible length.

TextJavaScript length (UTF-16 units)Grapheme length
Hello55
πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘§251

Yes, a full link or a full @handle counts toward the 300-grapheme limit in its complete, visible form, with no automatic shortening applied. The AT Protocol's own @atproto/api documentation describes mentions and links as facets, metadata that marks a byte range inside the post's own text rather than a separate field replacing that text, so the URL or handle characters are part of what gets counted, not something layered on top of it. A post that needs to link somewhere has to budget grapheme space for the full URL itself, unlike a platform that swaps a long link for a fixed-length short code before counting.

What are Bluesky's profile name and bio limits?

A Bluesky display name is capped at 64 graphemes and 640 bytes, and a profile description, the bio field, is capped at 256 graphemes and 2560 bytes, both set directly in the AT Protocol's lexicon for app.bsky.actor.profile, checked 9 September 2026. Both limits follow the same grapheme-plus-byte structure as a post, so the same emoji behavior that affects a 300-character post applies to a display name or bio written with emoji in it. A profile that wants the longest possible plain-text bio has almost ten times more room than a single post allows.

FieldGrapheme limitByte limit (UTF-8)
Post text3003000
Display name64640
Profile description (bio)2562560

A person writing across several notebook pages, echoing how a long thought gets split into a chain of linked posts.

How do threads work around the character limit?

A thread is built by publishing several separate posts and linking each one to the last through a reply field, not by extending any single post past 300 graphemes, per the same app.bsky.feed.post lexicon. That reply field requires both a root reference, pointing at the first post in the thread, and a parent reference, pointing at the post being replied to, so every post in a thread carries its own full address back to where the thread began. Writing past the limit means splitting the writing into multiple posts and posting them as replies to each other in order, the same mechanic used for any ordinary reply chain.

Chaining posts into a thread
Post one is written and published normally, capped at 300 graphemes
Post two sets its reply.parent to post one and reply.root to post one
Post three sets its reply.parent to post two and reply.root back to post one
Clients render the chain as a single thread using those root and parent references
Structure per the AT Protocol's app.bsky.feed.post lexicon, checked 9 September 2026.

What happens if a post goes over the limit?

A post that exceeds 300 graphemes or 3000 bytes does not get created as a single app.bsky.feed.post record, since both numbers are constraints the lexicon itself enforces on that record type rather than a warning a client shows after the fact. Bluesky's own app and every AT Protocol client that follows the lexicon block submission at that boundary, which is why the practical workaround is always a thread, chaining additional posts through the reply field, rather than any setting that raises the limit. Writing toward the limit deliberately, rather than discovering it mid-post, is the difference between a clean thread and a post that gets cut awkwardly at the boundary.

Bluesky is one of five platforms RedReplier watches for brand mentions and buying-intent conversations, alongside Reddit, X, Facebook and Hacker News, and the same 300-grapheme boundary applies to every post RedReplier surfaces from Bluesky search. The exact query syntax for finding those posts in the first place is covered in Bluesky search operators, and the identifier that keeps a saved search matching an account even after it changes its handle is explained in AT Protocol DIDs. A tool that posts on your behalf through the API hits the same 300-grapheme record limit, and connecting one securely is covered in Bluesky app passwords.

Frequently Asked Questions

Is the Bluesky character limit 300 characters or 300 graphemes?

It is 300 graphemes, not 300 raw characters in the way a programming language counts them by default. A single visible emoji can occupy far more than one unit under a raw character count, so Bluesky counts using grapheme clusters, which match what a person actually sees.

Does pasting a long URL use up more of the 300-grapheme limit than a short one?

Yes. The AT Protocol stores a link's full text as part of the post and marks it with a facet rather than replacing it with a shortened code, so every character of the URL counts toward the 300-grapheme limit.

What is the byte limit alongside the 300-grapheme limit?

Bluesky's post lexicon also caps a post at 3000 bytes measured in UTF-8. Almost every post reaches the 300-grapheme limit before it reaches the byte limit, since most characters use fewer than ten bytes each.

How long can a Bluesky display name be?

A display name is capped at 64 graphemes and 640 bytes, per the AT Protocol's lexicon for a Bluesky profile. That is separate from the profile description field, which allows up to 256 graphemes.

How long can a Bluesky bio be?

A Bluesky profile description, the bio field, is capped at 256 graphemes and 2560 bytes, according to the AT Protocol's own profile lexicon. That gives a bio close to ten times the space a single post allows.

Can I write one long post on Bluesky by turning off the character limit?

No. The 300-grapheme and 3000-byte caps are enforced by the post record's own lexicon definition, not by an app-level setting a user can change. Writing past the limit means splitting the text across multiple posts connected through the reply field, forming a thread.

RedReplier
RedReplier

Get Started

Reddit, X, Bluesky & HN

Real-time intent alerts

Unlimited AI replies

Ranked by buyer intent

A hashtag counts toward the 300-grapheme limit in its full, unshortened form, the same as a link or an @handle. Every character in the hashtag text takes up grapheme space against the post's limit. That's true whether the hashtag is short or long, since Bluesky doesn't compress it before counting.

Does the 300-grapheme limit apply to third-party Bluesky apps, or just the official app?

The 300-grapheme and 3000-byte caps come from the AT Protocol's own lexicon for app.bsky.feed.post, not from a rule only the official app enforces. Every post created through the Bluesky app or through any client built on the protocol has to satisfy both numbers, because the lexicon defines the record format itself. A third-party client enforces the identical limit rather than one of its own choosing.

What is a facet in a Bluesky post?

A facet is metadata inside a post record that marks a byte range within the post's own text, the mechanism the AT Protocol uses for a mention or a link. It doesn't replace the URL or @handle with a separate field, so the marked characters remain part of the text that counts toward the 300-grapheme limit. That's why a full link costs exactly as much grapheme space as the same text typed as plain words.

Does every post in a Bluesky thread need its own root and parent reference?

Each post in a thread carries a reply field with two references, a root pointing at the first post in the thread and a parent pointing at the post it directly replies to. Even the third or fourth post in a chain sets its root back to that original first post, not to the post before it. That structure is what lets a client render the whole chain as a single thread.

See us more often in Google

One click marks RedReplier as a preferred source, so our articles sit higher in your Top Stories, AI Mode, and AI Overviews.

Before you go...

RedReplier

RedReplier

Catch every buyer asking for what you sell

RedReplier watches Reddit, X, Bluesky and Hacker News in real time, ranks every thread by buyer intent, and drafts your reply, so you get there first.

Reddit, X, Bluesky & HN

Real-time intent alerts

Unlimited AI replies

Ranked by buyer intent

Related Articles