YouTube Shorts API
A channel's Shorts are a tab of the channel endpoint: POST the channel with tab shorts and the answer is a paginated list of its Shorts, newest first, each with a url the transcript and batch endpoints accept as-is. A single Short transcribes like any video: send its youtube.com/shorts/<id> URL to the transcript endpoint. A creator who posts only Shorts has an empty Videos tab, so this is the call that finds their uploads.
Each page of Shorts is one credit; a page trimmed to nothing by since_video_id costs nothing, so polling for new Shorts is free. Failed requests are free.
On this platform
- The Shorts listing carries no duration or publish time, so both are null on every row, as the example shows.
- since_video_id works here too: a page with nothing newer than the Short you name costs nothing.
- A monitor can watch the same tab: create it with tab shorts to get each new Short by webhook.
/api/v2/transcripts/channelidempotentList a channel's or profile's videos, Shorts, streams or playlists
Resolve a creator into a paginated list of videos (metadata only), newest first. A channel or profile that does not exist answers 404 not_found; an existing one with no uploads answers 200 with an empty list. The platform is read from the input: a YouTube channel, or a TikTok or Instagram profile URL. Every row's url is accepted by the transcript and batch endpoints as-is. Pass since_video_id to get back only the items newer than one you've already seen - a page with nothing new is free, which makes this safe to poll on a schedule. A YouTube channel also takes tab (its Shorts, live streams, playlists or podcasts instead of its videos), sort (popular or oldest first) and query (search inside the channel). The playlists and podcasts tabs answer with data.kind playlist_list, whose rows' urls the playlist endpoint accepts as-is.
Body parameters
channelstringrequiredtab"videos" | "shorts" | "live" | "playlists" | "podcasts"optionalsort"newest" | "popular" | "oldest"optionalquerystring (1-200 characters)optionallimitinteger (1–50)optionalcursorstringoptionalsince_video_idstringoptionalRequest example
Responses
{
"ok": true,
"request_id": "req_…",
"data": {
"kind": "video_list",
"source": "channel_videos",
"platform": "youtube",
"videos": [
{
"videoId": "SHlrUAkkWI0",
"url": "https://www.youtube.com/watch?v=SHlrUAkkWI0",
"title": "Lex trains w/ Khabib Nurmagomedov | Exclusive Footage at UFC PI",
"duration": null,
"channel": "Lex Fridman",
"publishedAt": null,
"stats": {
"plays": 64000
}
},
{
"videoId": "1WrrOJJ8-5g",
"url": "https://www.youtube.com/watch?v=1WrrOJJ8-5g",
"title": "High salaries for AI engineers: The talent war in AI",
"duration": null,
"channel": "Lex Fridman",
"publishedAt": null,
"stats": {
"plays": 89000
}
}
],
"next_cursor": "eyJvIjoxMH0"
},
"usage": {
"credits_spent": 1,
"balance": 656,
"bytes": 0
}
}Every YouTube endpoint
Frequently asked questions
- How do I get the transcript of one YouTube Short?
- Send its URL (youtube.com/shorts/<id>) or the bare id to the transcript endpoint, exactly as for a normal video. Captions are read first and the audio is transcribed when there are none; a Short is short, so it comes back inline.
- How do I list every Short on a channel?
- POST the channel to the channel endpoint with tab shorts and page with cursor until next_cursor is null. Each page costs 1 credit. The Videos tab does not include Shorts, which is why a Shorts-only creator looks empty without it.
- Why are duration and publishedAt null on Shorts rows?
- The Shorts listing YouTube serves carries neither, so the API returns null rather than a guess. Fetching a Short's transcript returns its real duration.
- Can I be told when a channel posts a new Short?
- Yes. Create a monitor on the channel with tab shorts. Each check reports the new Shorts by webhook or in the events list, optionally with their transcripts.