YouTube channel videos API: list and search any channel

YouTube channel videos API: list and search any channel

By TranscriptAPI TeamPublished March 30, 2026Last updated June 13, 202610 min read

YouTube channels are goldmines of organized content. A single channel can have thousands of videos, all categorized by topic, sorted by date, and waiting to be analyzed.

But getting that data programmatically? That's where things get messy.

The YouTube Data API v3 makes you jump through hoops. You need to find the channel's "uploads" playlist ID, then paginate through that playlist, then make separate calls for video details. It's three API calls minimum just to list videos from one channel.

TranscriptAPI gives you dedicated channel endpoints that handle all of this in a single call. List videos, search within channels, resolve channel identifiers, and monitor new uploads.

There are four channel-related endpoints in total. Two are free. Two cost 1 credit per request. This guide shows you how to use each one with working code examples.

Three different channel identifier formats converging into a single canonical ID badge.
Handles, URLs, IDs — all resolve to the same thing.

Resolving channel identifiers

Here's a problem you've probably hit before. YouTube channels have multiple URL formats. The same channel can be reached at least four different ways.

The channel resolve endpoint (free)

Before you can list a channel's videos, you need a consistent channel ID. YouTube uses the UC... format internally, but users share channels in all sorts of formats.

TranscriptAPI's resolve endpoint converts any format to a canonical channel ID. And it's free. Zero credits.

curl "https://transcriptapi.com/api/v2/youtube/channel/resolve?input=@mkbhd" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response:

{
  "channel_id": "UCBcRF18a7Qf58cCRy5xuWwQ",
  "resolved_from": "@mkbhd"
}

Supported URL formats

The resolve endpoint handles all of these:

  • Handle URLs: youtube.com/@mkbhd

  • Channel ID URLs: youtube.com/channel/UCBcRF18a7Qf58cCRy5xuWwQ

  • Custom URLs: youtube.com/c/mkbhd

  • Legacy user URLs: youtube.com/user/marquesbrownlee

If you pass a UC... ID directly, the resolution is instant since no lookup is needed.

I recommend always running inputs through the resolve endpoint first. Your users might paste any of these formats, and you don't want to write parsing logic for all of them.

Have you ever had a user paste a channel URL that broke your code?

Resolve in Python

Here's the resolve call in Python:

import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://transcriptapi.com/api/v2"
headers = {"Authorization": f"Bearer {API_KEY}"}

# Resolve any channel format to a UC... ID
response = requests.get(
    f"{BASE_URL}/youtube/channel/resolve",
    params={"input": "@mkbhd"},
    headers=headers
)

channel_data = response.json()
channel_id = channel_data["channel_id"]
print(f"Resolved to: {channel_id}")
# Output: Resolved to: UCBcRF18a7Qf58cCRy5xuWwQ

Use this resolved ID in all subsequent calls for consistency. Store it in your database alongside the original input so you only resolve once per channel.

A grid of video thumbnail cards with pagination arrows, representing a paginated channel list.
Pagination is the secret to not timing out on huge channels.

Listing all videos from a channel

This is the endpoint you'll use most. Pass a channel handle (or resolved ID) and get back a paginated list of every public video.

The channel videos endpoint

curl "https://transcriptapi.com/api/v2/youtube/channel/videos?channel=@mkbhd" \
  -H "Authorization: Bearer YOUR_API_KEY"

Each response includes video metadata: title, URL, publish date, thumbnail, duration, and view count. You get roughly 100 videos per page, and each page costs 1 credit.

The response also includes a continuation_token and a has_more boolean so you know when to stop paginating.

Pagination for large channels

Some channels have thousands of videos. TED has over 5,200. Here's how to paginate through them all:

import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://transcriptapi.com/api/v2"
headers = {"Authorization": f"Bearer {API_KEY}"}

all_videos = []
params = {"channel": "@TED"}

while True:
    response = requests.get(
        f"{BASE_URL}/youtube/channel/videos",
        params=params,
        headers=headers
    )
    data = response.json()
    all_videos.extend(data["videos"])

    if not data.get("has_more"):
        break

    # Next page uses continuation token only
    params = {"continuation": data["continuation_token"]}

print(f"Total videos: {len(all_videos)}")

A channel with 1,000 videos takes about 10 page requests. That's 10 credits, or about 5 cents on the monthly plan.

Here's what I like about this approach: you don't need to know the channel's "uploads playlist" ID. You don't need a separate API call for video details. Everything comes back in one clean response per page.

Cost breakdown for large channels

Channel sizePages neededCredits usedCost (monthly plan)100 videos11$0.005500 videos55$0.0251,000 videos1010$0.055,000 videos5050$0.25

The channel resolve step is free, so it doesn't add to your costs.

Compare that with the YouTube Data API v3, where listing 1,000 videos costs hundreds of quota units across multiple API calls. And you have a daily cap of 10,000 units total across all operations.

A magnifying glass over a grid of video thumbnails with two highlighted as matches.
Search inside a single channel — without scraping the web.

Searching within a channel

What if you don't need every video? Maybe you just want videos about a specific topic from a channel with 2,000 uploads.

The channel search endpoint

The /youtube/channel/search endpoint lets you search within a single channel's video catalog. It costs 1 credit per search.

response = requests.get(
    f"{BASE_URL}/youtube/channel/search",
    params={
        "channel": "@3blue1brown",
        "q": "linear algebra",
        "limit": 10
    },
    headers=headers
)

results = response.json()
for video in results:
    print(f"{video['title']}")

This is much cheaper and faster than listing all videos and filtering client-side.

When to use channel search vs channel videos

Use channel search when you: - Know what topic you're looking for - Want results from a specific channel about a specific subject - Need to find videos fast without paginating through everything

Use channel videos when you: - Need the complete video catalog - Want to analyze publishing frequency or content strategy over time - Are building a full index of a channel's content

Do you usually need all videos from a channel, or just specific ones?

Channel search parameters

The channel search endpoint accepts these parameters:

ParameterTypeRequiredDescriptionchannelstringYes@handle, channel URL, or UC... IDqstringYesYour search querylimitintegerNo1-50 results (default: 30)

The channel parameter is flexible. You can pass @3blue1brown, youtube.com/@3blue1brown, or UCYO_jab_esuFRV4b17AJtAw. All three work. TranscriptAPI resolves the channel internally.

A notification bell over a channel thumbnail, representing new upload monitoring.
The free endpoint for knowing when a creator uploads.

Monitoring new videos with channel latest (free)

You might not need the full history. Sometimes you just want to know when a channel uploads something new.

Want to automate this completely? Our YouTube monitoring agent tutorial shows how to build a full Slack-integrated pipeline on top of this endpoint.

The channel latest endpoint

The /youtube/channel/latest endpoint returns the 15 most recent videos from any channel. It's free, powered by RSS, and includes exact publish timestamps.

curl "https://transcriptapi.com/api/v2/youtube/channel/latest?channel=@mkbhd" \
  -H "Authorization: Bearer YOUR_API_KEY"

You get titles, URLs, publish dates, view counts, and ratings. All for zero credits.

Setting up a monitoring workflow

Here's a simple pattern for tracking new uploads:

import requests
import json
from pathlib import Path

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://transcriptapi.com/api/v2"
headers = {"Authorization": f"Bearer {API_KEY}"}

TRACKED_FILE = "tracked_videos.json"

def load_tracked():
    if Path(TRACKED_FILE).exists():
        return json.loads(Path(TRACKED_FILE).read_text())
    return []

def save_tracked(video_ids):
    Path(TRACKED_FILE).write_text(json.dumps(video_ids))

def check_for_new_videos(channel):
    response = requests.get(
        f"{BASE_URL}/youtube/channel/latest",
        params={"channel": channel},
        headers=headers
    )
    latest = response.json()
    tracked = load_tracked()

    new_videos = [v for v in latest if v["videoId"] not in tracked]

    if new_videos:
        for video in new_videos:
            print(f"New upload: {video['title']}")
            # Pull transcript, send notification, etc.
            transcript = requests.get(
                f"{BASE_URL}/youtube/transcript",
                params={"video_url": video["videoId"]},
                headers=headers
            )
            if transcript.status_code == 200:
                process_transcript(transcript.json())

        tracked.extend([v["videoId"] for v in new_videos])
        save_tracked(tracked)

# Run hourly via cron
check_for_new_videos("@mkbhd")

The monitoring check itself costs nothing. You only spend credits when you pull transcripts from new videos. That's a smart way to keep costs low while staying on top of content.

A dashboard with abstract charts and trend lines, representing a channel analysis tool.
Every channel is a dataset waiting to be analyzed.

Building a channel analysis tool

Now let's put these endpoints together for something practical.

Content audit

Want to understand a channel's content strategy? List all videos and analyze the patterns.

import requests
from collections import Counter

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://transcriptapi.com/api/v2"
headers = {"Authorization": f"Bearer {API_KEY}"}

# Get all videos
all_videos = []
params = {"channel": "@hubaborherman"}

while True:
    response = requests.get(
        f"{BASE_URL}/youtube/channel/videos",
        params=params,
        headers=headers
    )
    data = response.json()
    all_videos.extend(data["videos"])
    if not data.get("has_more"):
        break
    params = {"continuation": data["continuation_token"]}

# Analyze publishing patterns
print(f"Total videos: {len(all_videos)}")

# Group by year
years = Counter()
for v in all_videos:
    year = v["publishDate"][:4]
    years[year] += 1

for year, count in sorted(years.items()):
    print(f"  {year}: {count} videos")

Competitive channel comparison

Compare two or more channels side by side:

  1. List videos from each competitor channel

  2. Compare publishing frequency (who posts more often?)

  3. Search each channel for your key topics (who covers what?)

  4. Pull transcripts from overlapping topics to compare depth and angle

This kind of analysis would take days manually. With TranscriptAPI's channel endpoints, you can automate the data collection part and spend your time on the actual analysis.

Full pipeline: channel videos to transcripts

Here's the complete pattern. List a channel's videos, then pull transcripts from each one:

import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://transcriptapi.com/api/v2"
headers = {"Authorization": f"Bearer {API_KEY}"}

# Step 1: List all videos (channel/videos)
all_videos = []
params = {"channel": "@lexfridman"}

while True:
    resp = requests.get(
        f"{BASE_URL}/youtube/channel/videos",
        params=params,
        headers=headers
    )
    data = resp.json()
    all_videos.extend(data["videos"])
    if not data.get("has_more"):
        break
    params = {"continuation": data["continuation_token"]}

# Step 2: Get transcripts for each video
for video in all_videos[:10]:  # Start with first 10
    t_resp = requests.get(
        f"{BASE_URL}/youtube/transcript",
        params={
            "video_url": video["videoId"],
            "format": "text",
            "send_metadata": True
        },
        headers=headers
    )
    if t_resp.status_code == 200:
        data = t_resp.json()
        print(f"Got transcript for: {data.get('title', 'Unknown')}")
    elif t_resp.status_code == 422:
        print(f"No captions for: {video['videoId']}")

This costs 1 credit per page of channel videos plus 1 credit per transcript. Failed transcript requests (like 422 for no captions) cost 0 credits. You only pay for what works.

For a deeper dive into pulling transcripts from entire channels, see our guide on extracting transcripts from YouTube channels.

Error handling for channel endpoints

Channel endpoints can fail in predictable ways. Here's how to handle them:

  • 404: The channel doesn't exist or was deleted. Check the channel URL

  • 422: Invalid channel format. Make sure you're passing a valid handle, URL, or UC... ID

  • 429: You've hit the rate limit. Monthly plans allow 200 requests per minute. Annual plans allow 300. Check the Retry-After header

  • 408/503: Temporary server issue. Retry with exponential backoff

import time

def get_channel_videos_safe(channel, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(
            f"{BASE_URL}/youtube/channel/videos",
            params={"channel": channel},
            headers=headers,
            timeout=30
        )
        if response.status_code == 200:
            return response.json()
        if response.status_code in (408, 429, 503):
            wait = int(response.headers.get("Retry-After", 2 ** attempt))
            time.sleep(wait)
            continue
        response.raise_for_status()
    return None

Remember: failed requests are never charged. If a request returns any error code, that's 0 credits.

Frequently asked questions

Can I get subscriber counts or channel analytics from these endpoints?

No. TranscriptAPI's channel endpoints focus on video listing and search. For channel-level analytics like subscriber counts and total views, you'd need the YouTube Data API v3 or a third-party analytics platform. TranscriptAPI gives you the content data; analytics tools give you the audience data.

How many credits does it cost to list a channel with 1,000 videos?

About 10 credits. Each page returns roughly 100 videos, so 1,000 videos is 10 pages at 1 credit each. The channel resolve step is free. On the monthly plan at $5/1,000 credits, that's 5 cents.

Can I list videos from a YouTube channel I don't own?

Yes. TranscriptAPI can list videos from any public YouTube channel. Private and unlisted videos won't appear in the results, but everything the channel has made public is accessible.

What's the difference between channel/latest and channel/videos?

Channel latest (free) returns the 15 most recent uploads via RSS. It's perfect for monitoring and costs nothing. Channel videos (1 credit per page) returns the complete video catalog with pagination. Use latest for detecting new content. Use videos for full catalog access.

Can I combine channel endpoints with transcript extraction?

Yes, and this is one of the most common workflows. List videos from a channel, then pull transcripts for each one. Both endpoints use the same API key, same authentication, same credit system. See the "full pipeline" section above for a complete code example.

Start exploring YouTube channels

TranscriptAPI's channel endpoints make it simple to list, search, and monitor YouTube channel content. No Google Cloud setup. No quota management. No complex playlist-to-channel ID mapping.

Two of the four channel endpoints are completely free:

  • Channel resolve normalizes any handle or URL to a UC... channel ID

  • Channel latest returns the 15 most recent uploads with exact timestamps

The paid endpoints (channel videos and channel search) cost 1 credit per request.

Sign up at transcriptapi.com and get 100 free credits to start. No credit card required. Try listing your favorite channel's videos and see how fast it comes back.

Which channel would you analyze first?

For the full API reference including transcript extraction, search, and playlists, see our complete developer guide.

Frequently Asked Questions

Do I need a channel ID, or can I pass a @handle directly?
You can pass a @handle, a channel URL, a username, or a UC-format channel ID directly to any TranscriptAPI channel endpoint — it resolves the format internally, so there's no separate lookup step. A free resolve endpoint exists if you specifically want the canonical channel ID back, but it's optional, not a required first step.
Why use TranscriptAPI's channel endpoints instead of the YouTube Data API v3?
The YouTube Data API v3 takes at least three separate calls just to list a channel's videos — find the uploads playlist, paginate it, then fetch video details — and requires a Google Cloud project, OAuth, and a daily quota. TranscriptAPI's channel-videos endpoint does it in one call, returns paginated results with a continuation token, and accepts whatever channel identifier you already have. It's dramatically easier and drops straight into an existing workflow.
How does pagination work when listing a channel with thousands of videos?
Each response includes a continuation token and a has-more flag. While more pages remain, you pass the token back on the next call to fetch the following page. Each page returns roughly 100 videos and costs 1 credit, so a 1,000-video channel takes about 10 page calls (10 credits). Store the token between calls and you can pause and resume the job safely.
Share