Skip to content
SocialsForAI
Menu

Bluesky character limit

300 graphemes. An emoji family counts as one.

Bluesky limits post text by graphemes, what a reader sees as one character, plus a 3,000-byte ceiling. Here is how both work, with counted examples.

The short answer Β· Updated Nov 1, 2026

Bluesky posts are limited to 300 graphemes and 3,000 bytes of text, as defined in the app.bsky.feed.post lexicon. A grapheme is one user-perceived character, so a multi-part emoji like πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦ counts once. Links count at their full length, and images don't count. Most posts only ever hit the 300-grapheme limit.

Bluesky: live. Posting to Bluesky works on the API today.

How Bluesky counts, with examples
TextGraphemes (limit 300)UTF-8 bytes (limit 3,000)
hello55
cafΓ©45
πŸ‘14
πŸ‘πŸ½ (skin tone)18
πŸ‡ΊπŸ‡Έ18
πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦ (family, 7 code points)125
γ“γ‚“γ«γ‘γ―δΈ–η•Œ721
A 56-character https URL5656

Limits from the app.bsky.feed.post lexicon, read 2026-11-01. Counts computed with Intl.Segmenter, the same segmentation our API and counter use.

What is the Bluesky character limit?

300 graphemes. The text field of the app.bsky.feed.post lexicon, the schema every Bluesky post follows, sets maxGraphemes: 300 and maxLength: 3000, the second measured in UTF-8 bytes. A post must satisfy both.

The text may be empty if the post has an embed such as images, per the lexicon's description of the field. Through our API, a post with neither text nor media fails preflight with empty_post.

What is a grapheme?

A grapheme, formally an extended grapheme cluster, is what a reader sees as a single character, however many Unicode code points it's built from. Γ© written as e plus a combining accent is two code points and one grapheme. A flag is two regional-indicator code points and one grapheme. The family emoji πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦ is four people joined by three zero-width joiners: seven code points, 11 JavaScript string units, 25 bytes, one grapheme.

Browsers and Node.js expose this as Intl.Segmenter with granularity: "grapheme". That's what our Bluesky character counter and our API's preflight use. text.length in JavaScript counts UTF-16 units instead and over-counts every emoji.

javascript
const seg = new Intl.Segmenter("en", { granularity: "grapheme" });
const graphemes = (s) => [...seg.segment(s)].length;
const bytes = (s) => new TextEncoder().encode(s).length;

graphemes("πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦");   // 1   ("πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦".length is 11)
bytes("πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦");       // 25
graphemes("γ“γ‚“γ«γ‘γ―δΈ–η•Œ"); // 7

When does the 3,000-byte limit matter?

Almost never. 3,000 bytes over 300 graphemes allows an average of 10 bytes per grapheme. English is 1 byte per character, accented Latin letters 2, Japanese and Chinese 3, so 300 Japanese characters use only 900 bytes.

Only emoji-heavy text gets near it. The family emoji is 25 bytes, so 120 of them are exactly 3,000 bytes and 121 are 3,025: over the byte limit while only 121 of 300 graphemes. Our preflight checks both limits, so a post over 3,000 bytes fails with text_too_long and a message that gives the byte count, before anything is sent.

Do images count toward the 300?

No. Images are a separate embed, not part of the text. The app.bsky.embed.images lexicon allows up to 4 images per post, each at most 2,000,000 bytes, with optional alt text. Through our API, pass them in media with an alt field and they're uploaded as blobs before the post is created. Video isn't supported yet.

What happens if a post is over 300 graphemes?

With our API, nothing is sent to Bluesky. Preflight returns a 422 preflight_failed with a text_too_long issue, for example "Text is 303 characters; Bluesky allows 300." and the fix "Shorten it by 3+ characters, or set platform_options.bluesky.text to a shorter version." Send dry_run: true to check without publishing.

Bluesky is one of five networks live on our API today; the Bluesky API page covers connecting with an app password and posting. For agents, our Bluesky MCP server exposes the same check through the create_post tool.

How do I fit a post into 300 graphemes?

Bluesky's math rewards different edits than X's does.

  • Shorten URLs. On Bluesky every character of a link counts, so a 90-character tracking link is 30% of the post.
  • Keep emoji. They count 1 each here, not 2 as on X, so they're cheap.
  • Drop redundant hashtags; each costs its full length including the #.
  • When crossposting, check both counts. A 294-grapheme post with one 34-character link fits Bluesky but weighs 283 on X, 3 over. Emoji-heavy text goes the other way: 100 emoji are 100 graphemes on Bluesky but 200 on X. See crossposting and the X character limit.

Questions

What developers ask

What is the character limit on Bluesky?

300 graphemes, with a second ceiling of 3,000 bytes of UTF-8 text. Both are defined on the text field of the app.bsky.feed.post lexicon. A grapheme is one character as a reader sees it, so complex emoji count once. In practice only emoji-heavy posts ever reach the byte limit.

Do links count toward Bluesky's limit?

Yes, at their full length. Unlike X, which counts every URL as 23, Bluesky counts the URL text as written, so a 60-character link uses 60 of your 300 graphemes. Use a short URL if you need the room; the link is still clickable because it's stored as a facet.

Do emoji count as one character on Bluesky?

Yes. Each emoji is one grapheme, including skin-tone variants, flags and multi-person family emoji. That's a difference from X, where every emoji counts as 2. Emoji do take 4 to 25 bytes each, which only matters against the 3,000-byte ceiling in very emoji-heavy posts.

Why does my Bluesky count differ from string length?

JavaScript's .length counts UTF-16 code units, so a single emoji reports 2 to 11 and Bluesky reports 1. Count with Intl.Segmenter at grapheme granularity, which is what our Bluesky character counter and our API's preflight use, and you'll match Bluesky.

Do images count toward the Bluesky character limit?

No. Images are attached as an embed, separate from the text. Bluesky allows up to 4 images per post, each at most 2,000,000 bytes per the app.bsky.embed.images lexicon, and alt text for each. All 300 graphemes stay available for text.

Can I post more than 300 characters on Bluesky?

Not in one post. The 300-grapheme limit is part of the post record schema, so it applies whichever app or API client creates the post. Through our API, a longer text fails preflight with text_too_long and an exact overage. Split the content into separate posts or write a shorter Bluesky version with platform_options.

Get an API key and send your first post in five minutes.