TikTok title 2,200 limit counts UTF-16: a Python length check
TikTok caps the direct post title at 2,200 UTF-16 runes. Emoji count as two, so Python len() undercounts. A short check to run before you post.

Short answer
The TikTok Direct Post reference says the video title can be up to 2,200 UTF-16 runes. Python's len() counts code points, so a string with emoji or other characters outside the basic plane is longer in UTF-16 than len() says. A caption that looks like 2,150 characters can already be over the limit.
Count in UTF-16 code units before you post: encode as utf-16-le and divide the byte length by 2.
Counting units
The table shows how a few strings count. The code-unit numbers follow from how UTF-16 encodes characters, not from a TikTok statement.
| Text | Python len() | UTF-16 units |
|---|---|---|
| abc | 3 | 3 |
| e with an acute accent (precomposed) | 1 | 1 |
| A single emoji such as a rocket | 1 | 2 |
| Ten rocket emoji | 10 | 20 |
The check
This function works for any text and refuses to let a caption through if it is over the limit. It uses only the standard library.
LIMIT = 2200
def utf16_units(text):
return len(text.encode('utf-16-le')) // 2
def check_title(text, limit=LIMIT):
n = utf16_units(text)
if n > limit:
raise ValueError(f'title is {n} UTF-16 units; limit is {limit}')
return n
if __name__ == '__main__':
print(utf16_units('abc'))
print(utf16_units('\U0001F680' * 10))
print(check_title('Launch day clip'))Where captions come from
If an agent or script writes the title, put the check at the last step before the API call. A model told to write 2,000 characters may not hit that number exactly, and the code-unit count differs from what it counts. Trim at a sentence boundary instead of cutting mid-word, then recheck.
Title text is separate from the captions burned into the video. Sume's Video Captions job burns authored or transcribed text onto the video itself with design controls such as typography.safe_width_ratio and placement.anchor_ratio, which is a different problem from the post text. Do not confuse the two: one is video content, the other is the post's title field.
- Check UTF-16 units, not code points or bytes.
- Leave a margin below 2,200 for edits.
- Trim on sentence boundaries.
- Keep the burned-in caption and the post title separate in your data model.
Related
For the init limit on the same API, see the 6 requests per minute post. TikTok can change the field limits, so check the reference page when you build.
Edge cases to test
Test with the characters your audience actually uses: emoji, accented letters, and scripts outside the basic plane. Flag emoji with skin tone modifiers or zero-width joiners are sequences of several code points, so one visible symbol can use many UTF-16 units. The check above counts units, so it handles them, but your own trimming code must not cut a sequence in half.
When you trim, cut on a boundary that is a whole character or word. Slicing at an arbitrary index in Python works on code points, so it will not split a surrogate pair, but it can split an emoji sequence into pieces that render oddly. A safe approach is to trim by words, then recount in UTF-16 units until the text fits.
Count hashtags with the rest of the title text, since you send them in the same string.
Where to run the check
Put it in two places: when the caption is drafted, so an editor sees the count while writing, and again immediately before the API call, because later edits or template insertions can push the text over. A check at only one point leaves a gap.
Return the count in your logs so a rejected post can be traced to a number rather than a guess.
Sources
Related posts
More in Developers
- Timeline audio concat limits: 20 parts, 1,800 s, one channel layout
Timeline audio concat accepts 1 to 20 parts, outputs up to 1,800 seconds and needs one channel layout. Limits, refusal codes and a request that works.
- Timeline audio 400 codes: what each refusal means and the fix
Sume timeline audio refuses bad concat and split requests with stable codes such as audio_concat_requires_parts. Each code, its cause and the fix.
- Hook and full cut from one track: overlapping Timeline audio splits
Timeline audio split ranges may overlap, up to 20 per job at $0.01. Cut a 15-second hook and the full track from one song or voice-over in a single call.
- duck_requires_audio_spine: no music ducking under silence mode
Timeline refuses soundtrack.duck_db when audio.mode is silence, since there is no voice to duck under. The fix, the other silence rules, and a check.
Written by Sume