YouTube
YouTube channels, videos, comments, shorts, playlists, community posts, transcripts, media files, and search through one unified API
YouTube
The widest surface on the API after LinkedIn: every tab of a channel, full video detail, threaded comments, two kinds of search, trending, transcripts and subtitle files, the raw audio/video/thumbnail streams, and batch endpoints that take a thousand ids at a time.
Base URL: /v1/youtube/...
/v1/youtube/video/subtitles (1cr caption files) and /v1/youtube/video/transcript (3cr cleaned transcript)? See Which endpoint should I use?.How do I get started with YouTube data?
1. Fetch a profile
curl "https://www.socialcrawl.dev/v1/youtube/channel?handle=MrBeast" \
-H "x-api-key: sc_your_api_key_here"2. Fetch their content
curl "https://www.socialcrawl.dev/v1/youtube/channel/videos?handle=MrBeast" \
-H "x-api-key: sc_your_api_key_here"3. Read computed fields
When an endpoint supports a computed field and the required source inputs are present, the unified response includes that optional field. Depending on the endpoint, optional fields can include engagement_rate, language, content_category, and estimated_reach. See Computed fields for formulas, clamping rules, and null semantics.
A channel has five tabs, and each has its own endpoint
GET /v1/youtube/channel/videos returns regular uploads only. Everything else on a channel lives behind its own call, and this is the single most common cause of "where did the rest of their content go":
| What you want | Endpoint |
|---|---|
| The account snapshot | GET /v1/youtube/channel |
| Regular uploads | GET /v1/youtube/channel/videos |
| Shorts | GET /v1/youtube/channel/shorts |
| Live and past streams | GET /v1/youtube/channel/lives |
| Playlists | GET /v1/youtube/channel/playlists |
| Text and image posts | GET /v1/youtube/channel/community-posts |
All five channel-scoped endpoints take either channelId or handle — one is required — and all cost 1 credit. channel additionally accepts a url. They page with continuationToken, YouTube's own token rather than the universal cursor: pass back what the previous response returned.
channel/videos returns light rows by default. Add includeExtras=true to fill in post.engagement.likes, post.engagement.comments, and post.ext.description on each row — it slows the response slightly but saves a video call per row.
# Shorts, not uploads
curl "https://www.socialcrawl.dev/v1/youtube/channel/shorts?handle=MrBeast" \
-H "x-api-key: sc_your_api_key_here"
# Uploads with engagement counts attached
curl "https://www.socialcrawl.dev/v1/youtube/channel/videos?handle=MrBeast&includeExtras=true&sort=popular" \
-H "x-api-key: sc_your_api_key_here"GET /v1/youtube/profile/full (5cr) collapses the first two rows into one call: the channel, its recent videos, and computed metrics — average engagement rate, posting cadence with the window it was measured over, the top post, and the format mix. posts sets how many videos to average over (1-100, default 25). The profile leg is the only critical one, so a failure to fetch videos still returns the profile with null post-dependent metrics and a legs[] explaining why.
Two searches, and they return different things
GET /v1/youtube/search(1cr) is the general one. It returns every content kind — videos, channels, playlists, shorts, live streams — withuploadDate,sortBy,type,duration, andregionfilters.GET /v1/youtube/search/advanced(1cr) returns videos only, but with the full filter set:published_after/published_beforewindows,license,category,event_type,video_caption,video_definition,video_dimension,video_embeddable,topic_id,locationwithlocation_radius,safe_search, and more. Reach for it when a plain keyword search is too blunt, and forsearchwhen you need channels or playlists back too.
search/advanced is the one metered endpoint here. The base page is 1 credit; includeExtras=true adds a flat 5 credits to hydrate the page with view, like, and comment counts, because that hydration is a batch call under the hood. The page caps at 50 results upstream, so the increment is a single flat +5, never a multiple — 1cr or 6cr, nothing in between.
Two more search surfaces: GET /v1/youtube/search/hashtag (1cr) reads a hashtag feed rather than a keyword query, with type=shorts to restrict it, and GET /v1/youtube/search/suggestions (1cr) returns YouTube's own autocomplete list for a partial query — the cheapest keyword-research call on the platform.
search's sortBy=popular is not a view-count sort. It is a popularity-weighted ranking, and results do not come back in descending view order — a new york search returned 9.5M, then 502.9M, then 66K views in that order, on 4 of 4 test keywords. It also caps the page at roughly 20 results and cannot be combined with type=shorts (that pair is rejected with a 400). For a view-faithful ordering use search/advanced with order=viewCount&includeExtras=true, then sort the page yourself on the returned engagement.views. Separately, search's duration filter is currently not applied by the provider and can degrade the type filter — filter client-side on post.content.duration_seconds instead.# Videos from a date window, with counts hydrated
curl "https://www.socialcrawl.dev/v1/youtube/search/advanced?query=ai%20agents&published_after=2026-06-01&order=viewCount&includeExtras=true" \
-H "x-api-key: sc_your_api_key_here"
# What does YouTube think people are searching for?
curl "https://www.socialcrawl.dev/v1/youtube/search/suggestions?query=how%20to%20train" \
-H "x-api-key: sc_your_api_key_here"One video, and everything hanging off it
GET /v1/youtube/video(1cr) — the complete record from a videourl: title, view/like/comment counts, description, tags, duration, channel, publish date. List endpoints return lighter rows without the description or tags, so this is the call when those matter.GET /v1/youtube/video/comments(1cr) — top-level comments with author, text, like count, reply count, and timestamp.order,searchTerm, andmax_resultsnarrow it.GET /v1/youtube/video/comment/replies(1cr) — one thread opened up. It takes thecontinuationTokenthatvideo/commentsreturned for that comment, not a comment id, and you keep paging until no replies remain.GET /v1/youtube/video/transcript(3cr) — the spoken words as timestamped segments with language, word count, and speech rate. A video without captions returns a404naming the reason; that is the expected result, not a failure.GET /v1/youtube/video/subtitles(1cr) — the caption track files instead: language code and name, format, and a direct download URL, auto-generated tracks included. Cheaper thantranscriptwhen you want files rather than text.GET /v1/youtube/video/sponsors(10cr) — whether a video carries a paid-promotion disclosure, plus the brands likely sponsoring it, each with supporting evidence and a confidence score. Sponsors are inferred from the description, links, promo codes, and transcript, not stated by YouTube, which is why every row carries confidence.GET /v1/youtube/video/audio(5cr),GET /v1/youtube/video/files(5cr),GET /v1/youtube/video/thumbnails(1cr) — the downloadable streams. Audio gives mime type, bitrate, quality, sample rate and channels; files gives resolution, quality label, frame rate and bitrate; thumbnails gives every available size with width, height, and format.
video/audio and video/files are time-limited. Fetch them immediately; do not store them in a database and expect them to resolve later. Store the video id and re-request when you need the bytes.# The whole comment tree on one video
curl "https://www.socialcrawl.dev/v1/youtube/video/comments?url=https://www.youtube.com/watch?v=dQw4w9WgXcQ&order=top" \
-H "x-api-key: sc_your_api_key_here"
# Then open one thread with the token that came back
curl "https://www.socialcrawl.dev/v1/youtube/video/comment/replies?continuationToken=TOKEN_FROM_PREVIOUS_RESPONSE" \
-H "x-api-key: sc_your_api_key_here"Comments from a date window
There is no date parameter on video/comments, because YouTube exposes none for comments — a server-side filter would read the same pages at the same cost. What makes a window pull work instead is that order=newest is an exact sort: rows arrive newest-first on comment.published_at with per-second timestamps, and each next page continues strictly older with no overlap.
So to pull, say, the last two years of comments on a video:
- Request
order=newest— up to 100 comments per credit. - Keep rows where
comment.published_atis on or after your cutoff. - Stop paging when the last row of a page is older than the cutoff.
The one row that can defy the sort is a pinned comment, which YouTube serves first regardless of order — so filter rows by timestamp (step 2) rather than stopping at the first old row you see, and step 3 stays correct.
curl "https://www.socialcrawl.dev/v1/youtube/video/comments?url=https://www.youtube.com/watch?v=dQw4w9WgXcQ&order=newest" \
-H "x-api-key: sc_your_api_key_here"The same shape works on the replies side: video/comment/replies rows carry the same comment.published_at, so apply the cutoff to the rows as you drain each thread.
Playlists and community posts
GET /v1/youtube/playlist and GET /v1/youtube/playlist/items (1cr each) both take a playlist_id and both return the same videos. The difference is what comes with them: playlist attaches view counts and durations, playlist/items preserves playlist order and fills in when each video was added. Pick by whether you care about the videos or the sequence.
GET /v1/youtube/community-post (1cr) takes a single post url; GET /v1/youtube/channel/community-posts lists them for a whole channel.
Trending
GET /v1/youtube/videos/trending (1cr) takes region, category, language, and max_results — this is the filterable one. GET /v1/youtube/shorts/trending (5cr) is a Shorts snapshot and takes no parameters at all, so it is one global list rather than a per-country view.
Batch: one call, up to a thousand ids
Three POST endpoints take a JSON body when you already hold ids and want to stop calling the singular endpoint in a loop:
POST /v1/youtube/videos— up to 1000 video ids, each row the same object/v1/youtube/videoreturns. Ids that do not resolve are simply absent from the list.POST /v1/youtube/channels— up to 1000 channel ids, each row the same channel object/v1/youtube/channelreturns, subscriber count included (author.followers). Ids that do not resolve are absent from the list rather than returned empty, so join onauthor.id, never on array position — the response can be shorter than the request. Note that only the singularchannelendpoint accepts a handle or URL; the batch takes bareUC…ids and rejects anything else with a400before billing.POST /v1/youtube/transcripts— up to 100 video ids, one transcript row each with the caption language it resolved to and anokor not-found status. A video without captions comes back not-found rather than failing the request, and failed ids are refunded. Flat 3cr.
videos and channels are metered per chunk of 50 ids at 5 credits a chunk: 50 ids is 5cr, 200 ids is 20cr, the full 1000 is 100cr. The charge is per chunk regardless of how many ids in it resolve, so there is no per-id refund on these two.
curl -X POST "https://www.socialcrawl.dev/v1/youtube/transcripts" \
-H "x-api-key: sc_your_api_key_here" \
-H "content-type: application/json" \
-d '{"ids":["dQw4w9WgXcQ","9bZkp7q19f0"],"language":"en"}'Subscriber counts next to search results
Search returns the video, not the creator behind it — YouTube keeps subscriber counts out of its search index, so no search surface on this API carries one and no parameter can add it. Attaching them is a join, and the key is post.ext.channel_id.
The subscriber count itself lives on author.followers, on both GET /v1/youtube/channel (1cr, and cached for 15 minutes, so a repeat lookup of the same channel inside that window is free) and POST /v1/youtube/channels (5cr per 50 ids). For a crawl, collect channel ids across the whole run, deduplicate, then batch: 23 unique channels resolve in one 5-credit call rather than 23 separate ones.
Which surface hands you the join key matters:
| Search call | Carries post.ext.channel_id? |
|---|---|
search?type=videos | Yes, on every result |
search/advanced | Yes, on every result, no includeExtras needed |
search?type=shorts | No — never. Nor post.author.* |
post.author.username, post.author.display_name, post.author.avatar_url, and post.ext.channel_id are all null on every type=shorts result — measured 0 of 98 items across three keywords, and includeExtras=true does not change it. Recover the creator by feeding the post.id values to POST /v1/youtube/videos, which returns post.ext.channel_id for all of them at 5 credits per 50.So a page of 25 Shorts costs 1cr to search, 5cr to resolve the 25 videos to 23 unique channels, and 5cr to resolve those channels to subscriber counts — 11 credits for a fully attributed page. The same page of regular videos skips the middle step: 6 credits.
# 1. Regular videos already carry the channel id
curl "https://www.socialcrawl.dev/v1/youtube/search?query=iphone17&type=videos" \
-H "x-api-key: sc_your_api_key_here"
# 2. Shorts don't — resolve post.id → channel id first
curl -X POST "https://www.socialcrawl.dev/v1/youtube/videos" \
-H "x-api-key: sc_your_api_key_here" \
-H "content-type: application/json" \
-d '{"ids":["AeBZjMXIoa4","IbDFupquJf4"]}'
# 3. Either way, deduplicate the channel ids and resolve them in one call
curl -X POST "https://www.socialcrawl.dev/v1/youtube/channels" \
-H "x-api-key: sc_your_api_key_here" \
-H "content-type: application/json" \
-d '{"ids":["UCn9l4gU5mkmmlC2eiVu0LHw","UC_x5XG1OV2P6uZZ5FSM9Ttw"]}'author.followers is YouTube's own published number, and YouTube rounds it to three significant figures above 1,000 subscribers — you will see 12,800,000 and 85,700 and 1,240, never the digit-exact figure behind them. That rounding is YouTube's, applied to everyone, so there is no exact count being withheld from you; below 1,000 subscribers it is exact. Channels at or above 1,000 subscribers also set author.ext.followers_approximate to true. A channel that hides its count entirely sets author.ext.hiddenSubscriberCount to true, which is the signal to drop it from a ratio rather than treat a zero as real.What YouTube data can I access?
28 endpoints available.
| Endpoint | Path | Credit Tier |
|---|---|---|
| Get YouTube channel info | /v1/youtube/channel | standard (1cr) |
| List a YouTube channel's community posts | /v1/youtube/channel/community-posts | standard (1cr) |
| List a YouTube channel's live streams | /v1/youtube/channel/lives | standard (1cr) |
| List a YouTube channel's playlists | /v1/youtube/channel/playlists | standard (1cr) |
| List YouTube channel shorts | /v1/youtube/channel/shorts | standard (1cr) |
| List YouTube channel videos | /v1/youtube/channel/videos | standard (1cr) |
| Get YouTube community post | /v1/youtube/community-post | standard (1cr) |
| Get YouTube playlist | /v1/youtube/playlist | standard (1cr) |
| List the videos in a YouTube playlist | /v1/youtube/playlist/items | standard (1cr) |
| YouTube profile, recent posts, and computed analytics in one call. | /v1/youtube/profile/full | standard (5cr) |
| Search YouTube | /v1/youtube/search | standard (1cr) |
| Advanced YouTube video search | /v1/youtube/search/advanced | standard (1-6cr)metered |
| Search YouTube by hashtag | /v1/youtube/search/hashtag | standard (1cr) |
| Get YouTube search suggestions | /v1/youtube/search/suggestions | standard (1cr) |
| Up to 100 YouTube video ids → one transcript per row, failed ids refunded. | /v1/youtube/transcripts | standard (3cr) |
| Get YouTube video details | /v1/youtube/video | standard (1cr) |
| List YouTube comment replies | /v1/youtube/video/comment/replies | standard (1cr) |
| List YouTube video comments | /v1/youtube/video/comments | standard (1cr) |
| Get a YouTube video's subtitle files | /v1/youtube/video/subtitles | standard (1cr) |
| Get a YouTube video's thumbnail files | /v1/youtube/video/thumbnails | standard (1cr) |
| Get YouTube video transcript | /v1/youtube/video/transcript | standard (3cr) |
| Get trending YouTube videos | /v1/youtube/videos/trending | standard (1cr) |
| Batch get YouTube channel details (up to 1000) | /v1/youtube/channels | advanced (5-100cr)metered |
| Get trending YouTube shorts | /v1/youtube/shorts/trending | advanced (5cr) |
| Get a YouTube video's audio file streams | /v1/youtube/video/audio | advanced (5cr) |
| Get a YouTube video's video file streams | /v1/youtube/video/files | advanced (5cr) |
| Batch get YouTube video details (up to 1000) | /v1/youtube/videos | advanced (5-100cr)metered |
| Detect sponsors of a YouTube video | /v1/youtube/video/sponsors | premium (10cr) |
What should I know about YouTube data?
- Everything is
GETwith query parameters except the three batch endpoints (videos,channels,transcripts), which take aPOSTJSON body - Authentication via
x-api-keyheader - Responses follow the unified SocialCrawl schema
- Channel-scoped endpoints take
channelIdorhandle; video-scoped endpoints take the videourl; playlist endpoints takeplaylist_id - Pagination is
continuationTokenon the channel, search, comments, and hashtag endpoints, andcursoronplaylist,playlist/items,videos/trending, andsearch/advanced. Pass back whatever the previous response returned rather than assuming one name hlonchannel,video, and the two id-batch endpoints sets the localisation language of the returned metadata
Official YouTube Resources
- YouTube Data API v3 — Official Google developer documentation
- YouTube Analytics API — Channel and video analytics
