Bluesky character counter
Counts a post the way the Bluesky app does: by grapheme (what you see as one character), with links shortened first. Everything runs in your browser; nothing is sent anywhere.
รฉ or an emoji) that isn't shortened, followed by another link. A quirk in
the app's link shortening then puts the later link on the wrong bytes, so the posted text comes out garbled
(see below). Adding https:// in front of the first link, or removing the special characters from it, avoids it.What gets posted
| Link as typed | Shown in the post as | Characters |
|---|
Other counts
| Graphemes in the app (links shortened) | |
| Graphemes as typed (no shortening: what an API client sends unless it shortens links itself) | |
| UTF-8 bytes as typed (limit 3000) | |
| Unicode code points | |
JavaScript .length (UTF-16 units) |
How Bluesky counts characters
What is the Bluesky character limit?
300 per post. The post record allows at most 300 graphemes and 3000 UTF-8 bytes of text. The app shows the grapheme count next to the Post button and won't let you post while it's over 300.
Do emoji count as one character?
Yes, if you see one symbol. Bluesky counts graphemes, so ๐, ๐ซ๐ท and ๐จโ๐ฉโ๐ง each count as 1, even though the family emoji is 5 code points and 18 bytes. Accented letters typed as two code points (e + โฬ) also count as 1.
Do links count against the 300?
Only their short form. Before counting, the app replaces each link that starts with http:// or
https:// with the host + the first 13 characters of the path + ..., if the path
(counting the leading /, query and #fragment) is longer than 15 characters. That short text is what gets posted. The link itself still goes to the full URL.
Links typed without https:// (like example.com/some/long/path) are not shortened and count in full.
Hosts with accents become punycode (xn--...) and non-ASCII path characters become %XX codes.
My text is too long. Can I make it a thread?
Yes: the thread splitter cuts long text into posts that each fit, counted the same way as here, and breaks at paragraphs and sentences where it can.
What else changes when I post?
Leading blank lines and trailing whitespace are trimmed, and 3 or more line breaks in a row become 2.
My post fits in the app but fails through the API. Why?
The 300 limit is checked on the text you send. The app sends the shortened text; a script that sends the raw text with full URLs can go over. Shorten link text yourself and keep the full URL in the link facet. facet-check builds those facets with the right byte offsets.