Bluesky Character Limit 2026: 300 per Post, and How Links Count

A Bluesky post holds 300 characters, counted as graphemes. How emoji and links count, the limits for alt text, bio and video, and how to fit a thread.

A Bluesky post card with a character counter reading 300 and a long link shortened to its domain and a few characters

Guide · By PostBoost team · · Markdown

Short answer: a Bluesky post holds 300 characters. Bluesky counts graphemes, what a reader sees as one character, so every emoji counts as 1. Links are cheaper than they look: Bluesky keeps only a short form of the link in the text (domain plus 13 characters and "..."), so an 80-character tracking link costs 27. Paste a draft into the free social media character counter to see the Bluesky count next to X, Threads and the others.

Every Bluesky limit in one table

Bluesky is open source, so its limits are written down in two public places: the protocol schema (the "lexicon" every app must follow) and the code of the official app. The table says which one each number comes from.

where limit source
Post text 300 graphemes and 3,000 bytes Protocol: app.bsky.feed.post
Images per post 4, up to 2 MB each Protocol: app.bsky.embed.images
Video per post 1, up to 10 minutes and 300 MB in the official app App code: constants.ts
Alt text per image 2,000 characters App code: constants.ts
Display name 64 graphemes Protocol: app.bsky.actor.profile
Bio (profile description) 256 graphemes Protocol: app.bsky.actor.profile
One hashtag 64 graphemes Protocol: app.bsky.richtext.facet

The numbers above were read from the source on 15 October 2026. Video is the one that has moved: it launched at 60 seconds in 2024, went to 3 minutes in March 2025 (TechCrunch), and the official app's code now allows 10 minutes. Guides that say 60 seconds or 3 minutes are out of date. The post limit is 300 in both the protocol and the app.

How Bluesky counts the 300

Graphemes, not bytes or code points. A grapheme is what you would call one character when reading. "é" is 1, a flag is 1, and a family emoji made of four people and three invisible joiners is still 1. X counts each emoji as 2, so an emoji-heavy post can fit on Bluesky and fail on X.

There is also a 3,000-byte ceiling. It almost never matters: 300 characters of English take about 300 bytes, and 300 Japanese characters take 900. It only bites on posts made mostly of complex emoji. That family emoji is 25 bytes, so 120 of them hit the byte limit while the counter still shows 120 of 300.

Links count as their short form. When the Bluesky app publishes a post, it replaces each link in the text with a short version and keeps the full address as a clickable link behind it. The short version is the domain, then the first 13 characters of the rest, then "...". The full rule is a few lines in the app's url-helpers.ts:

you write Bluesky shows and counts characters
https://example.com/about example.com/about 17
https://example.com/blog/how-we-ship-weekly?utm_source=bluesky&utm_medium=social (80) example.com/blog/how-we-... 27

So long UTM-tagged links are fine on Bluesky: the tracking parameters still reach your analytics, and they do not eat into the 300. The reader sees the domain, so a recognisable domain matters more than a short path.

Mentions and hashtags count in full. @yourname.bsky.social is 21 characters of your 300. Unlike Mastodon, Bluesky does not drop the server part of a handle. A custom-domain handle such as @example.com is shorter and easier to read.

When 300 is not enough: write a thread

A Bluesky post cannot be longer than 300 characters, so a longer idea becomes a thread of replies, each with its own 300. Three habits make a thread read well:

  • Make the first post stand alone. The feed usually shows the first post on its own. Put the point there and the detail below.
  • Split at sentences, not at the limit. A post that stops mid-sentence at character 300 reads like a mistake.
  • Put the link where it is useful. On Bluesky a link costs only its short form, so it can sit in the first post. If the same thread also goes to X, keep the link in the last post there: in PostBoost a part with a link counts as an X link post (why one link in the last post is cheapest).

The free thread maker splits long text into numbered posts for Bluesky (pick Bluesky as the network) at paragraph and sentence breaks, and never cuts a word or a link.

How PostBoost handles Bluesky limits

PostBoost checks Bluesky's rules in the composer, before the post is scheduled.

  • Same counting as Bluesky. The counter for a Bluesky account counts an emoji as 1 and a link as the short form Bluesky will show, so https://example.com/blog/how-we-ship-weekly?utm_source=bluesky&utm_medium=social counts as 27, not 80. When PostBoost publishes, it shortens the link in the text the same way and keeps the full address as the clickable link.
  • Hard limit. A Bluesky post over 300 characters shows "Maximum of 300 characters allowed." for that account, and the post cannot be scheduled until it is shorter. The same check allows up to 4 photos, or 1 video, or 1 GIF, and says "Combining different media types (videos, photos, GIFs) is not allowed." if you mix them.
  • Threads. Click Add Post to add the next post of the thread. Each post is checked against the 300 on its own (an error reads "Post #2 - Maximum of 300 characters allowed."), and PostBoost publishes them as replies, in order. If the same post also goes to a Facebook, Instagram or LinkedIn account, the button reads Add first comment instead; create a version for the Bluesky account and add the thread posts there.
  • Link cards. When a post has no image or video, PostBoost attaches a link card for the first link in it, with the title, description and image the linked page provides.
  • Suggestions, not blocks. The composer flags images without alt text and suggests adding a hashtag, because people find posts on Bluesky by hashtag. Mentions of existing handles such as @name.bsky.social and hashtags become working links on Bluesky. You can ignore any suggestion and still schedule.

To check one draft against Bluesky and every other network you post to, paste it into the free social media post checker: it applies the same length and media rules and shows what each network will reject.

Check a thread with the API before you schedule it

The REST API runs the same rules. POST /posts/validate is a dry run: it checks length, media and the other network rules for each account and creates nothing. On Bluesky, each item after the first in content is the next post of the thread:

curl -X POST "https://postboost.co/app/api/$WORKSPACE_UUID/posts/validate" \
  -H "Authorization: Bearer $POSTBOOST_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "accounts": [15],
    "schedule": true,
    "date": "2026-10-20",
    "time": "15:00",
    "timezone": "Europe/Berlin",
    "versions": [{
      "account_id": 0,
      "is_original": true,
      "content": [
        { "body": "We now ship every Friday. Here is what changed in our release process, and what broke on the way." },
        { "body": "The write-up, with the checklist we use: https://example.com/blog/how-we-ship-weekly?utm_source=bluesky&utm_medium=social" }
      ]
    }]
  }'

The endpoint answers 200 either way; read valid. If one post of the thread is over 300 characters for the Bluesky account, valid is false and errors holds the length error for that account. Send the same body to POST /posts to schedule it for real (validatePost, createPost).

When you want to plan Bluesky posts and threads with the limits checked for you, start free and connect your Bluesky account.

Do this in PostBoost

Free tools for this guide

FAQ

What is the Bluesky character limit?

300 characters per post. Bluesky counts graphemes, meaning what a reader sees as one character, so an emoji counts as 1 even when it is built from several code points. The protocol also caps a post's text at 3,000 bytes, which only matters for posts made mostly of complex emoji.

Do links count toward the 300 characters on Bluesky?

Only their short form. Bluesky stores and shows a link as the domain plus the first 13 characters of the rest, followed by three dots, and keeps the full address behind it. An 80-character link with UTM parameters costs 27 characters of the 300.

Do emoji count as 1 or 2 characters on Bluesky?

1. Bluesky counts graphemes, so a single emoji, a flag or a family emoji built from several code points each count as one character. X counts the same emoji as 2.

What is the Bluesky alt text limit?

2,000 characters per image in the official Bluesky app. Write what the image shows and why it is in the post; a sentence or two is enough for most images.

How long can a Bluesky bio and display name be?

The profile description (bio) holds 256 characters and the display name 64, both counted as graphemes. These limits are set in Bluesky's protocol schema.

Can I write a longer post on Bluesky?

Not in one post. Split the text into a thread: each reply has its own 300 characters. In PostBoost, click Add Post in the composer to add the next post of the thread, and PostBoost publishes them as replies in order.

What happens in PostBoost if a Bluesky post is too long?

The composer shows "Maximum of 300 characters allowed." for the Bluesky account and will not schedule the post until you shorten it. A REST API call is rejected the same way, and the validate endpoint reports it without creating anything.

Sources

Related guides

Try PostBoost free

API, webhooks and MCP on every plan, including Free. No credit card required.