TL;DR, Quick Answer
9 min readTikTok's Content Posting API caps a video caption at 2200 UTF-16 runes, a photo post title at 90, and a photo post description at 4000. TikTok never defines what a UTF-16 rune is, and the two plausible readings disagree on every emoji. A photo title a person reads as 79 characters counts as 86 under one reading and 96 under the other, so the same string passes or fails depending on which one TikTok implemented.
What is the TikTok caption character limit?
The documented TikTok caption character limit is 2200 UTF-16 runes for a video caption and 90 UTF-16 runes for a photo post title, plus a separate 4000-rune description field that only photo posts have. All three numbers come from TikTok's Content Posting API reference, and all three are stated in runes rather than characters. Everything below describes the API, because that is the only place TikTok publishes a number.
The word "caption" is not a field name anywhere in the API. On a video, the caption goes in title. On a photo post, title is a short headline and the caption text belongs in description. Same app, same creator, same act of writing a caption, two field names whose limits sit a factor of twenty-four apart.
| Post type | Endpoint | Caption field | Documented maximum | Second text field |
|---|---|---|---|---|
| Video, direct post | /v2/post/publish/video/init/ | title | 2200 UTF-16 runes | none |
| Photo, direct post | /v2/post/publish/content/init/ | title | 90 UTF-16 runes | description, 4000 UTF-16 runes |
| Video, to drafts | /v2/post/publish/inbox/video/init/ | none | not applicable | none |
The third row catches people out. The upload endpoint that drops a video into the creator's TikTok inbox accepts no text at all. Its request body holds source, video_size, chunk_size, total_chunk_count and video_url, and nothing else. TikTok tells integrators "You should inform users that they must click on inbox notifications to continue the editing flow in TikTok and complete the post." If your scheduler posts through that endpoint, the caption never leaves your database.
What is a UTF-16 rune?
TikTok does not say. The phrase "UTF-16 runes" appears in the field descriptions with no definition, no link and no example, and it welds together two units from two different traditions. A rune is Go's name for a Unicode code point. UTF-16 is an encoding whose unit of measure is the code unit, and astral characters take two of them. So "UTF-16 rune" reads as either "code point" or "UTF-16 code unit", and those are different numbers.
They are the same number for plain English. They diverge for anything above U+FFFF, which is where all the pictographic emoji live.
| Text | What a reader counts | Code points | UTF-16 code units |
|---|---|---|---|
Hello | 5 | 5 | 5 |
cafΓ© with precomposed U+00E9 | 4 | 4 | 4 |
cafΓ© with e plus U+0301 | 4 | 5 | 5 |
γγγ«γ‘γ― | 5 | 5 | 5 |
| π | 1 | 1 | 2 |
| π©βπ©βπ§βπ¦ | 1 | 7 | 11 |
Non-Latin scripts are not the problem people assume they are. Japanese kana sit in the Basic Multilingual Plane, so five kana cost five under both readings. What costs double is anything encoded above U+FFFF: emoji, historic scripts, some CJK extension blocks, mathematical alphanumerics.
I read the ambiguity as pointing at code units, because that is the number a server gets for free: String.prototype.length in JavaScript and String.length() in Java both return code units. That is a guess about TikTok's implementation, not something TikTok states, so treat 2200 and 90 as ceilings you stay under rather than targets you hit.

How much does one emoji cost against the limit?
Between 1 and 11, and the reader sees a single glyph either way. The cost is the number of code points in the emoji under one reading, and the sum of their UTF-16 widths under the other. Every code point above U+FFFF is 2 code units wide. Zero width joiners and variation selectors are 1 each.
| Emoji | Code point sequence | Reader counts | As code points | As UTF-16 units |
|---|---|---|---|---|
| π | U+1F341 | 1 | 1 | 2 |
| π | U+1F600 | 1 | 1 | 2 |
| β©οΈ | U+26E9 U+FE0F | 1 | 2 | 2 |
| β€οΈ | U+2764 U+FE0F | 1 | 2 | 2 |
| ππ½ | U+1F449 U+1F3FD | 1 | 2 | 4 |
| π³οΈβπ | U+1F3F3 U+FE0F U+200D U+1F308 | 1 | 4 | 6 |
| π©βπ©βπ§βπ¦ | U+1F469 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 | 1 | 7 | 11 |
The torii gate is the odd one. It is a BMP symbol carrying a variation selector, so both readings agree on 2 while the reader sees 1. The family emoji is the expensive one at 11 code units, which on a 90-rune photo title is more than a tenth of the field.
A photo title that passes one reading and fails the other
Take this photo post title: Autumn in Kyoto: the twelve quiet corners we walked before dawn, day 1 πππ―πππβ©οΈπ©βπ©βπ§βπ¦. It is 71 characters of ASCII and eight emoji. A person reading it counts 79 things, comfortably inside 90.
| Segment | Reader counts | As code points | As UTF-16 units |
|---|---|---|---|
| ASCII body | 71 | 71 | 71 |
| πππ―πππ | 6 | 6 | 12 |
| β©οΈ | 1 | 2 | 2 |
| π©βπ©βπ§βπ¦ | 1 | 7 | 11 |
| Total | 79 | 86 | 96 |
Read "UTF-16 runes" as code points and the title is 86, which fits. Read it as UTF-16 code units and it is 96, which does not. One string, one documented limit of 90, two defensible readings, opposite answers. Swap the family emoji for πͺ U+1F46A and the same title falls to 87 under the strict reading and publishes under both.
- 86 code points
- 96 UTF-16 units
- fails the 90-rune title under the strict reading
- 80 code points
- 87 UTF-16 units
- fits under either reading
Why does the same caption break on a photo post?
Because a video caption has 2200 runes to spend and a photo title has 90. A tool that stores one caption per scheduled post and maps it to title on both endpoints is fine for the video and 24 times over budget for the photo. Either it trims the string before sending, dropping most of the caption with no warning, or TikTok rejects the call.
If TikTok rejects it, the response is not specific. Neither reference publishes a named error for an over-length caption. The catch-all is invalid_param at HTTP 400, described as "Check error message for details", and the rest of the documented codes cover other ground: spam_risk_too_many_posts, reached_active_user_cap, url_ownership_unverified, privacy_level_option_mismatch, scope_not_authorized, rate_limit_exceeded. Length validation has to happen in your code, because the API will not tell you which field was too long.
The right mapping treats photo posts as two fields rather than one. Keep the headline short in title and put the caption body in description, which at 4000 runes is the roomiest text field in the whole Content Posting API. The field named description on a photo post holds nearly twice what the field named title holds on a video. The names are backwards relative to the sizes.
AdaptlyPost
Start 7-Day FREE Trial
All-platform analytics
Social Inbox
AI-powered assistant
Hashtags are a second asymmetry. TikTok documents parsing for the video field only, in a sentence that ships with a typo: "Hashtags (#) and mentions (@) will be matched, or deliminated by spaces or new lines." No equivalent sentence appears on the photo reference for either field. Whether a #tag typed into a photo description becomes a real tag is undocumented, so test it on a SELF_ONLY post first.

How do you count a TikTok caption before you send it?
Compute all three numbers and validate against the largest. Intl.Segmenter gives you the reader's count in Node and in the browser without a dependency, and the other two are built in.
const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
const readings = (text) => ({
reader: [...segmenter.segment(text)].length,
codePoints: [...text].length,
utf16Units: text.length,
});
const LIMITS = { videoTitle: 2200, photoTitle: 90, photoDescription: 4000 };
const fits = (text, field) => readings(text).utf16Units <= LIMITS[field];text.length is the strict reading, so validating against it keeps you safe under either interpretation. Do not reach for Buffer.byteLength(text, 'utf8') here. UTF-8 bytes are a third unit, charging 3 per kana and 4 per astral emoji, and nothing in TikTok's documentation asks for them. That rule belongs to Threads. Mixing the two up rejects captions TikTok would have accepted.
Is the in-app caption limit the same as the API limit?
TikTok does not publish an in-app figure, so there is nothing to compare. The Content Posting API reference states 2200, 90 and 4000 for the three API fields and says nothing about the composer inside the app. The help center articles that would cover it sit at URLs I could not reach. Numbers circulating for the in-app composer trace back to marketing posts rather than to TikTok, so I am not repeating them.
Treat the two as separate until TikTok documents otherwise. A caption typed in the app and a caption sent through /v2/post/publish/video/init/ travel different paths, and only one of them has a published number.
One further constraint is documented, on a different page. TikTok's content sharing guidelines require that "API Clients must allow users to enter or select the following metadata for a post: a. Title", and that "Preset text, including any text in the title field or hashtags, should be allowed to be edited by the user before posting content." A tool that generates a caption and posts it with no chance to edit is out of compliance however many runes it used.
Where adaptlypost fits
adaptlypost posts to TikTok through the same Content Posting API, so 2200, 90 and 4000 apply to a scheduled post exactly as they apply to a hand-typed one. Platform limits are TikTok's. What scheduling changes is when you learn about them, because a caption drafted in a content calendar can be measured days before its send time rather than at the moment the API returns invalid_param.
The mismatch gets sharper the moment one draft goes to several networks, which is the ordinary case in multi-platform posting. Each network defines its own counting unit, so a caption sized for one is not automatically safe on the next. If you write with the AI caption writer, the useful habit is to keep the emoji at the end, where trimming them costs you nothing.
For scheduling, see the TikTok post scheduler. For the endpoints, see TikTok posting API, and for what the posts did afterwards, TikTok analytics.
Frequently Asked Questions
What is the maximum TikTok caption length in the API?
2200 UTF-16 runes for a video caption, which TikTok's Content Posting API reference puts in the title field of /v2/post/publish/video/init/. Photo posts are different: title is capped at 90 UTF-16 runes and description at 4000, both on /v2/post/publish/content/init/.
What does TikTok mean by UTF-16 runes?
TikTok does not define the term. A rune is Go's word for a Unicode code point, while UTF-16 measures in code units, and the two readings differ for every character above U+FFFF. Validate against the code unit count, which is text.length in JavaScript, because it is the larger of the two and keeps you inside the limit under either reading.
Why is the TikTok photo caption limit only 90 characters?
The 90-rune cap is on title, which is a headline field on photo posts rather than the caption. The caption body belongs in description, which allows 4000 UTF-16 runes. A tool that maps one stored caption to title on both video and photo endpoints hits the 90 and has nothing to do but truncate.
How many characters does an emoji use in a TikTok caption?
Between 1 and 11 depending on how it is built. A single-code-point emoji like π costs 1 as a code point and 2 as UTF-16 code units. The four-person family emoji π©βπ©βπ§βπ¦ is seven code points welded by zero width joiners, which is 7 or 11 depending on the reading, from something the reader sees as one glyph.
What error does TikTok return when a caption is too long?
TikTok publishes no named error for an over-length caption. The catch-all is invalid_param at HTTP 400, documented as "Check error message for details", and the other published codes cover spam risk, quotas, unverified URL ownership, privacy mismatch and authorization. Check the length yourself before you call the endpoint.
AdaptlyPost
Start 7-Day FREE Trial
All-platform analytics
Social Inbox
AI-powered assistant
Is the TikTok in-app caption limit the same as the API limit?
TikTok does not publish a figure for the in-app composer, so the two cannot be compared from documentation. The 2200, 90 and 4000 figures are stated for API fields only, in the Content Posting API reference. Any in-app number you find elsewhere is not sourced from TikTok.
Can you add a caption when posting a TikTok video to drafts?
The endpoint that posts a video to a creator's TikTok inbox, /v2/post/publish/inbox/video/init/, has no caption field at all. Its request body only takes source, video_size, chunk_size, total_chunk_count and video_url. TikTok expects the creator to add a caption inside the app after tapping the inbox notification, since a caption sent through your scheduler never reaches this endpoint's payload.
Does TikTok parse hashtags on a photo post the same way as on a video?
TikTok documents hashtag and mention parsing only for the video title field, in a sentence describing hashtags and mentions as "matched, or deliminated by spaces or new lines." No matching sentence appears on the photo post reference for either title or description. Whether a #tag typed into a photo caption becomes a clickable tag is undocumented, so test it on a SELF_ONLY post before relying on it.
Can a scheduling tool post a TikTok caption without letting you edit it first?
TikTok's content sharing guidelines rule this out. They require API clients to let users enter or select a title, and state that preset text in the title field or hashtags must be editable before posting. A tool that generates a caption and posts it without a chance to edit is out of compliance regardless of how many runes it used.
Should you count a TikTok caption in UTF-8 bytes?
UTF-8 byte counting is the wrong unit for TikTok. TikTok's documented limits are stated in UTF-16 runes, not bytes, and UTF-8 charges 3 bytes per kana character and 4 per astral emoji, numbers nothing in TikTok's documentation asks for. That byte-counting rule belongs to Threads; mixing the two up rejects captions TikTok would have accepted.
Put this into practice with AdaptlyPost
Was This Article Helpful?
Let us know what you think!
See us more often in Google
One click marks AdaptlyPost as a preferred source, so our articles sit higher in your Top Stories, AI Mode, and AI Overviews.
Before you go...
AdaptlyPost
Schedule your content across all platforms
Manage all your social media accounts in one place with AdaptlyPost.
All-platform analytics
Social Inbox
AI-powered assistant
Related Glossary Terms


The TikTok AI Generated Label Is Two Different Labels
The TikTok AI generated label comes two ways: a creator label you apply with is_aigc, and an auto label from AI effects or C2PA that you cannot remove.


Meta Sets the Instagram API alt_text Character Limit at 1,000
Meta caps the Instagram API alt_text character limit at 1,000 and scopes the field to still images. Reels and stories accept no alt text at all.


Why the Threads Character Limit Counts Emoji as UTF-8 Bytes
The Threads character limit is 500, but Meta counts each emoji as its UTF-8 byte length, so one family emoji costs 25. Here is how to count a post correctly.
Related Articles


Compare TikTok Creator Fund Requirements and Alternatives
Weigh the TikTok Creator Fund requirements and alternatives before applying: eligibility thresholds, realistic per-view earnings, and programs that pay more.


What Is TikTok Live Studio? Complete Setup Guide
A free desktop app with multi-camera support, screen sharing, and overlays. What is TikTok live studio capable of, and who meets the requirements.


The X Authenticity Rule: Can I Post the Same Content to Multiple Accounts?
Can I post the same content to multiple accounts? X bans identical posts from accounts one person runs, permits localized versions, and caps you at ten.

