Last updated:

Bluesky Character Limit and Posting Tips

11 min read

Bluesky is a social network built on the AT Protocol, a decentralized framework. It began as a project announced inside Twitter in 2019 by co-founder Jack Dorsey, and in February 2024 it dropped the invite-only requirement and opened to the public. The post character limit is 300 characters, but the way Bluesky counts those "300 characters" is fundamentally different from other social platforms. This article dives into the AT Protocol's technical specifications and covers effective posting strategies.

Grapheme Cluster Counting - Bluesky's Unique Character Calculation

Bluesky counts characters using "grapheme clusters," the smallest unit of text that a human perceives as a single character, as defined by Unicode Standard Annex #29 (UAX #29). This approach differs fundamentally from how X and Threads count characters.

Consider the skin-tone emoji "👋🏽." Internally, it consists of two Unicode code points: U+1F44B (waving hand) and U+1F3FD (skin tone modifier). X counts this as 2 characters, but Bluesky counts it as 1 grapheme cluster. Similarly, the flag emoji "🇯🇵" is composed of two Regional Indicator code points (U+1F1EF + U+1F1F5), yet Bluesky counts it as a single character.

This becomes even more significant with complex emoji. The family emoji "👨‍👩‍👧‍👦" consists of 7 code points (4 emoji + 3 ZWJ connectors), but Bluesky counts it as just 1 character. X counts every emoji as a flat 2 characters regardless of complexity, so this emoji costs 2 there. For emoji-heavy posts, Bluesky's lower per-emoji count still lets you fit more information.

The same three emoji in one post - what they cost on Bluesky and on X
Emoji in the postInternal code pointsBluesky cost (grapheme cluster)X cost (flat 2 per emoji)
👋🏽 Waving hand with skin toneU+1F44B + U+1F3FD (2 code points)1 character2 characters
🇯🇵 FlagU+1F1EF + U+1F1F5 (2 code points)1 character2 characters
👨‍👩‍👧‍👦 Family4 emoji + 3 ZWJ (7 code points)1 character2 characters
All three together11 code points3 characters6 characters

Identical wording can still leave you a different amount of room, because the emoji cost differs. The limits are 300 characters on Bluesky and 280 on X. Counting by grapheme cluster means Bluesky charges a single character no matter how complex the emoji is inside.

Bluesky Character Limits

ElementCharacter LimitCounting MethodNotes
Post300 charactersGrapheme clustersA 3,000-byte UTF-8 limit applies alongside it
Display Name64 charactersGrapheme clustersShown on profile
Bio256 charactersGrapheme clustersProfile description
Reply300 charactersGrapheme clustersSame as posts
Handle253 charactersCharacter countFollows the form of a DNS domain name
List Name64 bytesUTF-8 byte countThe only field with no grapheme limit
List Description300 charactersGrapheme clustersList description text
ALT Text2,000 charactersGrapheme clustersFor accessibility

One row in this table behaves unlike the others: the list name is capped in UTF-8 bytes, not grapheme clusters. It is the only field with no grapheme limit at all. An ASCII list name therefore fits about 64 characters, while a script whose characters take 3 bytes each in UTF-8 runs out around 21 characters. If a list name is silently rejected even though it looks short, the byte count is usually the reason.

The post body has a two-layer structure. Alongside the 300 grapheme clusters, the record also has to fit within 3,000 bytes of UTF-8. For Latin text the grapheme limit is always the one you hit first. Even for a script at 3 bytes per character, 300 characters comes to roughly 900 bytes, so the byte limit works less as a limit you write up against and more as a backstop for pathological input.

The handle is counted in characters rather than bytes, and its 253-character ceiling comes from the form of a DNS domain name: a handle is resolved as a domain, so it inherits the shape of one. ALT text allows up to 2,000 characters, which is enough for a detailed image description without turning into a second post body.

Where the 300-Character Limit Is Defined - The Line Between Protocol and App

The 300-character cap is not a rule enforced somewhere deep in the network. It sits in the schema that defines what a post record is: the post type declares a maximum number of grapheme clusters for its text field, and that declared value is what gets checked when a post is written to a repository. In other words, the limit is data in a published definition rather than a constant buried in server code.

From a user experience perspective, the limit lines up neatly with migration from X's 280-character limit. The extra 20 characters address the "I wish I could write just a bit more" need while maintaining the brevity that defines short-form social media.

Because the value lives in a schema, two things follow. Any change to it shows up as a diff in that definition, so it is something you can track rather than guess at. And another application built on the AT Protocol can define its own record type with a different ceiling entirely. The 300-character cap is a Bluesky application decision, not a constraint the protocol imposes on everyone.

Facets - Bluesky's Rich Text Processing and Its Impact on Character Count

Bluesky posts use a feature called "Facets" for rich text processing. Facets attach metadata such as links, mentions (@), and hashtags to post text, and they directly affect character counting.

Facets themselves consume no characters: they are byte ranges recorded next to the text, not extra text. What does consume characters is the text they point at. A URL written in the post body is counted exactly as written - "https://example.com/very-long-path/to/article" is 45 characters and costs all 45. There is no mechanism here like X's, where every URL is folded into one fixed character cost regardless of its real length.

A link card (external site preview) is a different matter, because the card's URL is stored in a separate field of the record from the post text. That copy of the URL therefore sits outside the 300 characters of the body. The catch is that attaching a card does not remove anything from your text: if you leave the URL string in the body as well, that occurrence still costs its full length.

Mentions (@username) count only the displayed text portion. For instance, "@alice.bsky.social" consumes 18 characters. Mentioning users with long handles can eat into your character budget significantly.

5 Tips for Effective 300-Character Posts

  1. Lead with your conclusion. At 300 characters, a post is short enough that nearly all of it is visible in the timeline, so what actually decides whether someone reads on is the first line or two. Put the point there rather than building up to it.
  2. Cut unnecessary modifiers. Removing words like "very," "really," and "basically" saves 5 to 10 characters each. In longer phrases, replacing "is able to" with "can" saves 7 characters.
  3. Use line breaks for readability. Since mobile viewing dominates, adding blank lines every 3 or 4 lines improves scannability. Note that line breaks count as 1 character each, so don't overdo it.
  4. Let the link card carry the URL. Because the card's URL goes into a separate field from the post text, keeping a long URL string out of the body frees that space for your summary. Attach the card, then write the body as if the link were already there.
  5. Check your character count with Character Counter before posting. Grapheme cluster counting is difficult to calculate manually, so a tool check gives you confidence.

Common Posting Mistakes and How to Avoid Them

Here are pitfalls Bluesky users frequently fall into, along with their causes and solutions.

Pro Tips

Comparison with Other Platforms - Mind the Counting Differences

PlatformCharacter LimitCounting MethodURL Handling
Bluesky300 charactersGrapheme clustersNo shortening; a URL in the body costs its full length
X (Twitter)280 (Premium: 25,000)NFC-normalized code pointsURLs: fixed 23 chars (t.co shortening)
Threads500 charactersUnicode code pointsURLs count toward limit
Mastodon500 characters (varies by server)Server implementation dependentURLs: fixed 23 chars

A simple character count comparison suggests Bluesky's 300 is only 20 more than X's 280, but the two platforms charge for different things. Grapheme cluster counting favors Bluesky whenever a post is full of emoji or combining characters. URL handling runs the other way: X folds any link into a fixed 23 characters, while Bluesky charges the full length of whatever you typed. Which platform leaves you more room therefore depends on what the post is made of. See our SNS character limit comparison for more details.

Conclusion

Bluesky's 300-character limit balances the AT Protocol's decentralized architecture with short-form social media usability. By understanding its technical features - grapheme cluster counting, which charges a single character however complex an emoji is inside; URLs, which are counted at the length you write them because nothing shortens them; and a ceiling that lives in a published schema definition rather than in hidden server code - you can maximize the value of every character. Combine these with Bluesky-specific features like custom feeds and domain handles to craft concise, engaging posts. Check your character count with Character Counter before posting to avoid exceeding the limit.

Share this article