YouTube tags limit: 500 characters, commas and quotes count
snippet.tags[] has a 500-character cap, and commas plus quotes around multi-word tags count toward it. A Python tag builder that stays under the cap.

Keep the whole tag list under 500 characters, and count the separators too. YouTube's Videos resource says snippet.tags[] is a list of keyword tags, that tags may contain spaces, and that the property value has a maximum length of 500 characters, with the commas between items and the quotation marks around tags that contain spaces counting toward the limit.
That wording, read on 2026-10-03 from the Videos resource, is what the script below follows. It is a conservative tally: one comma between items and two quote characters around any tag with a space. If the API counts differently in a corner case, the headroom absorbs it. Sume does not set tags on YouTube; you send them in videos.insert.
What counts toward the 500?
Three things, according to the page: the characters of each tag, the commas between the items, and the quotation marks around any tag that contains a space. So ["ai video", "shorts"] costs more than the 14 letters it holds.
The page does not say how many tags you may send, only the total length, so the length is the only rule this post enforces.
| Item | Counts toward 500 |
|---|---|
| Each character of a tag | Yes |
| Commas between items | Yes |
| Quotes around a tag with spaces | Yes |
| Tags without spaces | No quotes added |
How do I build a list that fits?
Order the tags by importance, then add them one at a time while the running cost stays under the cap. The script below keeps a small safety margin of 10 characters and prints the cost. It runs as-is.
def cost(tags):
total = 0
for tag in tags:
total += len(tag) + (2 if " " in tag else 0)
return total + max(len(tags) - 1, 0)
def fit(candidates, limit=500, margin=10):
chosen = []
for tag in candidates:
if cost(chosen + [tag]) > limit - margin:
break
chosen.append(tag)
return chosen
wanted = ["ai video", "shorts", "how to make a short", "vertical video"] * 40
list_ = fit(wanted)
print(len(list_), cost(list_))Where do the keywords come from?
Write them from what the video says. Video inspect with transcribe: true returns the transcript of one clip at $0.01 per audio minute, and you can pull the nouns you actually use. Do not pad the list with unrelated popular terms; the page defines tags as keywords associated with the video and says nothing about how they affect distribution, so this post makes no promise on that.
What goes wrong in a batch?
The common failure is one row with a long tag that pushes the list over, which turns the whole call into an error and burns a Video Uploads quota call. Run the fit function on every row before you enqueue it, along with the title and description checks from the 5000-byte description post and the title check.
What does a good list look like?
Short and specific. Because every comma and quote costs characters, one-word tags are cheaper than phrases: a phrase with a space pays two extra characters for its quotes. Three or four phrases you really mean beat thirty fillers, and the page gives no reason to expect the long list to help.
Put the most important tag first and let the fit function cut the rest. If your list is built from a transcript, remove repeats and any tag that is only a stop word. If the same tag appears in the title, it is usually already doing its job there.
Last, treat tags as one input among several. The pages I read describe them as keywords associated with the video and name no ranking effect, so spend your effort on the title, the spoken words and the opening seconds first.
- Count characters, commas and quotes together.
- Order tags by importance before trimming.
- Keep a margin of a few characters under 500.
- Run the check on every row before it enters the upload queue.
Sources
Related posts
More in Developers
- videos.insert embeddable and publicStatsViewable for a Shorts batch
status.embeddable and status.publicStatsViewable are settable on videos.insert. Set both explicitly in a Shorts batch body and check them with a small script.
- videos.insert OAuth scope: youtube.upload or force-ssl?
videos.insert accepts four OAuth scopes; videos.getRating gained youtube.readonly on Sept 1, 2026. Which to request for a Shorts pipeline and what Sume holds.
- videos.update needs snippet.categoryId: retitle a Short safely
YouTube's videos.update requires snippet.categoryId whenever you send a snippet. How to retitle a Short from a batch without a failed call.
- Zod 4 discriminated union for Sume job and run webhooks (TypeScript)
Parse Sume job.* and format.run.terminal webhooks with one Zod 4 discriminatedUnion: typed branches, degraded runs, oversized receipts. Tested with Zod 4.
Written by Sume