YouTube Channel Scraper retrieves a channel's metadata and public content through SerpApi. Collect videos, Shorts, live streams, podcasts, playlists, or community posts, with titles, links, view counts, thumbnails, and other available details.
Get structured JSON for applications or Markdown for LLMs and AI agents, without managing HTML parsing or proxies. This guide uses engine=youtube_channel to target one channel. It is different from YouTube Search Scraper, which searches across YouTube.
Send a GET request identifying the channel:
https://serpapi.com/search?engine=youtube_channel&channel_id=UCUgIHlYBOD3yA3yDIRhg_mg&tab=videos&sort=latest&gl=us&hl=en&api_key=YOUR_SERPAPI_API_KEY
- Register at SerpApi to get your API key. Replace
YOUR_SERPAPI_API_KEYin the examples and keep your key private; never commit it. - Use
channel_id. Supply a handle without the URL or@, such asserpapi, or a raw channel ID beginning withUC. - All examples use SerpApi's raw channel ID,
UCUgIHlYBOD3yA3yDIRhg_mg. The Python and JavaScript examples also settab=videos,sort=latest,gl=us, andhl=en; the minimal cURL examples use the defaults. The documentation notes that requests using raw IDs are faster than requests using handles. - The official parameter table marks
channel_idoptional; these examples always supply it to select a specific channel.
JSON is the default, so no output parameter is needed:
curl --get https://serpapi.com/search \
-d engine="youtube_channel" \
-d channel_id="UCUgIHlYBOD3yA3yDIRhg_mg" \
-d api_key="YOUR_SERPAPI_API_KEY"These minimal commands print the API response directly, including any error message. For values containing spaces or special characters, use --data-urlencode instead of -d. The Python and JavaScript examples below include error handling for automation.
The official YouTube Channel API documentation explicitly supports json (default), md (Markdown), and html (raw source for debugging).
Use JSON for individual fields and pagination tokens. Use Markdown for text-based workflows, LLMs, and AI agents. Set output=md on https://serpapi.com/search and keep the channel parameters unchanged. Markdown is text, not a JSON object, and its layout is not a guaranteed copy of the JSON schema.
curl --get https://serpapi.com/search \
-d engine="youtube_channel" \
-d channel_id="UCUgIHlYBOD3yA3yDIRhg_mg" \
-d output="md" \
-d api_key="YOUR_SERPAPI_API_KEY"Read Markdown as text, not with response.json() or getJson. Inspect error responses rather than treating them as channel content.
Install requests, then save the Python example as main.py:
python3 -m pip install requestsimport requests
SERPAPI_API_KEY = "YOUR_SERPAPI_API_KEY"
params = {
"api_key": SERPAPI_API_KEY,
"engine": "youtube_channel",
"channel_id": "UCUgIHlYBOD3yA3yDIRhg_mg",
"tab": "videos",
"sort": "latest",
"gl": "us",
"hl": "en",
"output": "json",
}
response = requests.get("https://serpapi.com/search", params=params, timeout=60)
response.raise_for_status()
data = response.json()
if "error" in data:
raise RuntimeError(data["error"])
print(data)For Markdown, keep the imports and parameter definitions above and replace the request and response-handling lines with:
params["output"] = "md"
response = requests.get("https://serpapi.com/search", params=params, timeout=60)
response.raise_for_status()
if "application/json" in response.headers.get("Content-Type", ""):
raise RuntimeError(response.text)
print(response.text)The content-type guard surfaces an unexpected JSON response instead of silently accepting an API error as Markdown.
Install the SerpApi JavaScript package. Save this CommonJS example as index.cjs:
npm install serpapiconst { getJson } = require("serpapi");
async function main() {
const data = await getJson({
api_key: "YOUR_SERPAPI_API_KEY",
engine: "youtube_channel",
channel_id: "UCUgIHlYBOD3yA3yDIRhg_mg",
tab: "videos",
sort: "latest",
gl: "us",
hl: "en",
timeout: 60000,
});
if (data.error) throw new Error(data.error);
console.log(data);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});The SDK's timeout is in milliseconds, and getJson selects JSON. Rejected requests and API errors are surfaced rather than replaced with empty results.
For Markdown, use this standalone Node.js 18+ example instead. It uses built-in fetch, requires no package, and reads the response as text:
async function main() {
const params = new URLSearchParams({
api_key: "YOUR_SERPAPI_API_KEY",
engine: "youtube_channel",
channel_id: "UCUgIHlYBOD3yA3yDIRhg_mg",
tab: "videos",
sort: "latest",
gl: "us",
hl: "en",
output: "md",
});
const response = await fetch(`https://serpapi.com/search?${params}`, {
signal: AbortSignal.timeout(60000),
});
const text = await response.text();
if (!response.ok) throw new Error(`SerpApi HTTP ${response.status}: ${text}`);
if ((response.headers.get("content-type") || "").includes("application/json")) {
throw new Error(`Expected Markdown, received JSON: ${text}`);
}
console.log(text);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});Use a GET request from any language, or explore SerpApi integrations.
| Name | Description | Requirement |
|---|---|---|
engine |
Must be youtube_channel. |
Required |
api_key |
Your private SerpApi API key. | Required |
channel_id |
Handle such as serpapi, or raw channel ID beginning with UC. Raw IDs are faster. |
Listed as optional in the API docs; supplied here to select a channel |
gl |
Two-letter country code, such as us, uk, or fr. |
Optional |
hl |
Language code, such as en or fr; regional forms such as en-gb and es-419 are supported. |
Optional |
tab |
Content tab; default videos. See supported values below. Cannot combine with search_query. |
Optional |
sort |
Sort values depend on the tab. Cannot combine with search_query, tab=podcasts, or tab=posts. |
Optional |
search_query |
Search within this channel; matching videos and playlists appear in search_results. Remove both tab and sort. |
Optional |
about |
false (default) or true. Adds channel information such as country, join date, total views, and external links by making an extra request to YouTube. Cannot combine with next_page_token. |
Optional |
next_page_token |
Continuation token from the previous response's serpapi_pagination.next_page_token. |
Optional |
output |
json (default), md, or html. |
Optional |
no_cache |
false (default) permits matching cached responses; true fetches fresh results. Cache expires after one hour. Cannot combine with async. |
Optional |
async |
false (default) waits for results; true submits for later retrieval through the Searches Archive API. Do not combine with no_cache or use with Ludicrous Speed enabled. |
Optional |
zero_trace |
Enterprise-only storage opt-out; false (default) or true. |
Optional |
json_restrictor |
Select JSON fields with the JSON Restrictor. Keep pagination fields if collecting more pages. | Optional |
Matching cached searches are free and do not count toward monthly searches. The code examples use synchronous requests.
tab |
JSON results key | Allowed sort values |
|---|---|---|
videos (default) |
videos_results |
latest (default), popular, oldest |
shorts |
shorts_results |
latest (default), popular, oldest |
streams |
streams_results |
latest (default), popular, oldest |
podcasts |
podcasts_results |
Omit sort |
playlists |
playlists_results |
dd (default: date added, newest), lad (last video added) |
posts |
posts_results |
Omit sort |
A channel may not expose every tab or every field. To search within the channel, omit tab and sort entirely and send, for example, search_query=python; read the mixed search_results array instead of videos_results.
- Make an initial JSON request and read
serpapi_pagination.next_page_token. - Pass that exact value as
next_page_tokenin the next request. Keep the channel, localization, and applicable tab/sort or channel-search parameters consistent. - Remove
aboutbefore adding the token:aboutandnext_page_tokencannot be used together. Collect extended channel metadata on the initial request if needed. - Continue with each newly returned token. Stop when none is returned, guard against repeated tokens, and impose a page limit to control costs.
Use tokens only when the response supplies them; do not assume every tab has another page. There is no documented fixed page size or numeric page offset. Treat tokens as opaque values and let the client URL-encode them. The search API uses sp for pagination, but this channel engine uses next_page_token, not sp or page_token.
The response may also include serpapi_pagination.next. When following a returned URL, retain authentication and enforce the documented parameter constraints, including removing about for continuation requests.
The following is a field guide, not a literal API response. Descriptive strings indicate types and meaning. It shows the default videos shape, with extended channel fields that require about=true when available.
{
"search_metadata": {
"id": "String: SerpApi search ID",
"status": "String: Processing, Success, or Error"
},
"channel_results": {
"title": "String: channel title",
"handle": "String: channel handle",
"description": "String: channel description",
"keywords": "String: channel keywords",
"external_id": "String: raw UC-prefixed channel ID",
"link": "String: channel URL",
"rss_link": "String: channel video feed URL",
"subscribers_text": "String: displayed subscriber count",
"subscribers": "Integer: parsed subscriber count",
"videos_text": "String: displayed video count",
"video_count": "Integer: parsed video count",
"thumbnail": "String: channel thumbnail URL",
"thumbnails": [
{
"url": "String: thumbnail URL",
"width": "Integer: pixels",
"height": "Integer: pixels"
}
],
"country": "String: additional about information",
"joined_date": "String: displayed join date",
"total_views_text": "String: displayed total channel views",
"total_views": "Integer: parsed total channel views",
"links": [
{
"title": "String: external link title",
"link": "String: external URL"
}
]
},
"videos_results": [
{
"position": "Integer: position on the page",
"title": "String: video title",
"link": "String: YouTube video URL",
"serpapi_link": "String: video details API URL",
"video_id": "String: YouTube video ID",
"description": "String: description when available",
"views": "String: displayed view count",
"extracted_views": "Integer: parsed view count",
"published_date": "String: publication label",
"length": "String: duration label",
"thumbnail": {
"static": "String: static image URL",
"rich": "String: preview image URL when available"
}
}
],
"filters": [
{
"title": "String: filter label",
"selected": "Boolean: whether selected",
"serpapi_link": "String: filter request URL"
}
],
"serpapi_pagination": {
"next_page_token": "String: continuation token",
"next": "String: next request URL"
}
}| JSON key | Available data |
|---|---|
shorts_results |
Flat array of Shorts with position, title, link, video_id, views, extracted_views, and thumbnails. Unlike search Shorts, these are not nested shorts sections. |
streams_results |
Streams with live/upcoming flags. Live streams can have watching/extracted_watching; upcoming streams can have waiting/extracted_waiting and scheduled_for; past streams can have views/extracted_views, published_date, and length. |
podcasts_results |
Podcast playlists with playlist_id, title, link, last_updated, episodes, and extracted_episodes. |
playlists_results |
Playlists with playlist_id, title, link, last_updated, video_count, and extracted_video_count. These describe playlists, not a complete expansion of every video. |
posts_results |
Community posts with post_id, author, text, published_date, votes/extracted_votes, comments_count/extracted_comments_count, and optional video/image attachment. |
search_results |
Mixed matches with type=video or type=playlist. Video fields include video_id and view counts; playlist fields include playlist_id, video counts, and available preview videos. |
error |
API failure message; check before consuming results. |
The official channel response schema describes all tab-specific fields. channel_results is a single object, not the channel matches array returned by engine=youtube. The channel video array is videos_results, not the search engine's video_results. Channel video views is a display string; use extracted_views for numeric work. Optional fields may be absent, and publication dates may be relative labels rather than timestamps.
Pass a returned video_id as v to engine=youtube_video for full video details and available comments. See YouTube Video Scraper and the Video API documentation.
For available transcript text, use engine=youtube_video_transcript with the same ID as v. See YouTube Video Transcript Scraper and the Transcript API documentation.
These are separate API requests, not data guaranteed in the channel listing. Authenticate any returned serpapi_link follow-up with your own key.
- Track changes in publicly displayed channel subscriber counts and upload activity through periodic snapshots.
- Compare a creator's videos, Shorts, streams, and playlists using the appropriate tab and sorting options.
- Search within a channel for relevant videos, then supply its content listing to an AI agent as Markdown.
For pagination, use the current official parameter next_page_token documented above, rather than the tutorial prose's page_token wording.
Feel free to reach out via contact@serpapi.com.
