# Character Limits

Every social network enforces a maximum length for post text, and Buffer
validates against that limit before a post is scheduled or published. This guide
covers the limit for each network, how Buffer counts characters, and channel-specific nuances.

On most networks Buffer counts length in UTF-16 code units, not in the number of
characters you see on screen. Most text counts one to one, but emoji and the
bold and italic Unicode letters, commonly used for LinkedIn formatting, count as
two units each. A post that looks well under the limit can still be rejected
because of this.

## Limit per network

The table below shows the character limit Buffer applies to the post `text` for
each network. Where a network also supports a first comment, its separate limit
is listed too.

| Channel | Post limit | First comment |
|---|---|---|
| Facebook (pages and groups) | 5,000 | 5,000 |
| Instagram | 2,196 | 2,200 |
| X (Twitter), Free | 280 | - |
| X (Twitter), Basic/Premium/Premium+ | 25,000 | - |
| LinkedIn (pages and profiles) | 3,000 | 1,250 |
| Pinterest | 500 | - |
| TikTok (photo and text posts) | 4,000 | - |
| TikTok (with a video attached) | 2,200 | - |
| Threads | 500 | - |
| Bluesky | 300 | - |
| YouTube (video description) | 5,000 | - |
| Google Business Profiles | 4,000 | - |
| Mastodon | Set by the server, 500 by default | - |



Some networks limit other fields as well:

- Pinterest and YouTube titles: 100 characters
- Threads topics: 50 characters, and a topic cannot contain `&` or `.`
- TikTok comments: 150 characters

On Mastodon the limit comes from the server your channel is on, so read
`maxCharacters` from the channel's `MastodonMetadata` rather than assuming 500.
Buffer caps it at 20,000 however high the server sets it. 

Attached images and videos do not use up any of your characters. The one
exception is TikTok, where attaching a video lowers the limit as shown above.


## How Buffer counts characters

On most networks Buffer measures `text` length in UTF-16 code units, the same
value you get from `string.length` in JavaScript. This matters because one
character as a reader sees it is not always one code unit:

Characters in the Basic Multilingual Plane (ordinary Latin letters, digits,
punctuation, most accented Latin, and so on) are one code unit each. Characters
outside that plane are encoded as a surrogate pair and count as two code units
each. This includes most emoji and the mathematical alphanumeric letters
(U+1D400 to U+1D7FF) that power bold and italic text on LinkedIn.

So the length Buffer validates is often higher than the number of glyphs you can
count by eye.

Some networks add their own rules on top:

| Network | How the text is counted |
|---|---|
| Facebook, Google Business Profiles, Pinterest, Threads, TikTok, YouTube | UTF-16 code units |
| LinkedIn | UTF-16 code units, and every URL counts as 24 whatever its real length |
| Instagram | UTF-16 code units, and every line break counts as 2 |
| Mastodon | UTF-16 code units, URLs count as 23, and the server part of an `@user@server.com` mention is not counted |
| X (Twitter) | X's own weighted count, where URLs are 23 and emoji are 2 |
| Bluesky | Graphemes, so an emoji counts as 1 however it is encoded. URLs count as the host plus up to 16 more characters |

### Unicode bold and italic formatting

Networks don't natively support rich text in the post body, so any bold or italic formatting
in a post is really a substitution of mathematical alphanumeric symbols. For
example, the bold H is not the letter `H` (U+0048) but 𝗛 (U+1D5DB). Each of these
substitute letters lives outside the Basic Multilingual Plane, so almost
everywhere it counts as two rather than one.

| What you type | Glyphs you see | UTF-16 networks | Bluesky | X (Twitter) |
|---|---|---|---|---|
| `Hello` (plain) | 5 | 5 | 5 | 5 |
| 𝗛𝗲𝗹𝗹𝗼 (bold) | 5 | 10 | 5 | 10 |
| 𝘏𝘦𝘭𝘭𝘰 (italic) | 5 | 10 | 5 | 10 |
| 🚀 (emoji) | 1 | 2 | 1 | 2 |
| 👨‍👩‍👧 (family emoji, ZWJ sequence) | 1 | 8 | 1 | 2 |
| `café` (precomposed é) | 4 | 4 | 4 | 4 |
| `café` (e plus combining accent) | 4 | 5 | 4 | 4 |

Styling therefore costs about half your allowance on every network except
Bluesky, which counts graphemes and charges the same for a styled letter as a
plain one. A post written entirely in bold letters reaches LinkedIn's 3,000 at
roughly 1,500 visible characters, and a free X post's 280 at roughly 140. That is
why a post that looks far short of the limit can still fail validation.

## What happens when you exceed the character limit

Exceeding the character limit is a typed mutation error. The request
returns HTTP `200` and the failure is reported in the mutation payload's
`message` field (see [Error Handling](https://developers.buffer.com/guides/error-handling.md)).

```json
{
  "data": {
    "createPost": {
      "message": "LinkedIn posts cannot exceed 3000 characters."
    }
  }
}
```

The other fields report the same way, with their own wording: `LinkedIn first
comment cannot exceed 1250 characters.`, `YouTube title cannot exceed 100
characters.`, etc. 

Because the count is in code units, a `message` like the above can appear even
when your text looks shorter than the stated number. 


## Next steps

- [Posts & Scheduling](https://developers.buffer.com/guides/posts-and-scheduling.md): creating and scheduling posts
- [Error Handling](https://developers.buffer.com/guides/error-handling.md): typed mutation errors and error codes
- [Rate Limits](https://developers.buffer.com/guides/api-limits.md): request and query limits
