DEV Community

Alex Spinov
Alex Spinov

Posted on

YouTube Has a Hidden API — Here's How to Use It (No Key, No Quotas)

Most developers use the YouTube Data API v3. It requires an API key, has strict quotas (10,000 units/day), and charges for heavy usage.

But YouTube.com itself doesn't use that API. It uses something called Innertube — an internal API that powers the YouTube website and mobile apps.

And you can use it too. No API key. No quotas. No OAuth.

What is Innertube?

Innertube is YouTube's internal API. When you visit youtube.com, every video load, every comment section, every search result — all of it goes through Innertube.

The endpoints are public (they have to be — your browser calls them). They just aren't documented.

Get Video Comments (No API Key)

import requests
import json

def get_comments(video_id, max_comments=20):
    """Get comments from a YouTube video using Innertube."""
    url = "https://www.youtube.com/youtubei/v1/next"

    payload = {
        "context": {
            "client": {
                "clientName": "WEB",
                "clientVersion": "2.20240101.00.00"
            }
        },
        "videoId": video_id
    }

    resp = requests.post(url, json=payload)
    data = resp.json()

    # Navigate the response to find comments
    # (simplified — real implementation needs continuation tokens)
    contents = data.get("contents", {})
    print(f"Got response for video {video_id}")
    return data

# Usage
data = get_comments("dQw4w9WgXcQ")
Enter fullscreen mode Exit fullscreen mode

Search YouTube (No API Key)

def search_youtube(query, max_results=10):
    """Search YouTube using Innertube."""
    url = "https://www.youtube.com/youtubei/v1/search"

    payload = {
        "context": {
            "client": {
                "clientName": "WEB",
                "clientVersion": "2.20240101.00.00"
            }
        },
        "query": query
    }

    resp = requests.post(url, json=payload)
    data = resp.json()

    # Extract video results
    results = []
    contents = (data
        .get("contents", {})
        .get("twoColumnSearchResultsRenderer", {})
        .get("primaryContents", {})
        .get("sectionListRenderer", {})
        .get("contents", []))

    for section in contents:
        items = (section
            .get("itemSectionRenderer", {})
            .get("contents", []))
        for item in items:
            video = item.get("videoRenderer", {})
            if video:
                results.append({
                    "title": video.get("title", {}).get("runs", [{}])[0].get("text", ""),
                    "videoId": video.get("videoId", ""),
                    "views": video.get("viewCountText", {}).get("simpleText", ""),
                    "channel": video.get("ownerText", {}).get("runs", [{}])[0].get("text", "")
                })
    return results[:max_results]

# Usage
videos = search_youtube("python tutorial 2024")
for v in videos:
    print(f"{v['title']}{v['views']}")
Enter fullscreen mode Exit fullscreen mode

Get Video Transcripts (No API Key)

def get_transcript(video_id):
    """Get video transcript/subtitles using Innertube."""
    # First, get the player response
    url = "https://www.youtube.com/youtubei/v1/player"

    payload = {
        "context": {
            "client": {
                "clientName": "WEB",
                "clientVersion": "2.20240101.00.00"
            }
        },
        "videoId": video_id
    }

    resp = requests.post(url, json=payload)
    data = resp.json()

    # Get captions
    captions = (data
        .get("captions", {})
        .get("playerCaptionsTracklistRenderer", {})
        .get("captionTracks", []))

    if captions:
        # Get the first caption track (usually auto-generated)
        caption_url = captions[0]["baseUrl"]
        transcript = requests.get(caption_url).text
        return transcript
    return None

transcript = get_transcript("dQw4w9WgXcQ")
print(transcript[:500] if transcript else "No captions available")
Enter fullscreen mode Exit fullscreen mode

Innertube vs YouTube Data API v3

Feature Innertube YouTube Data API v3
API key Not needed Required
Quotas None 10,000 units/day
Rate limits Soft (be polite) Strict
Comments All + replies Limited
Search Full Full
Transcripts Yes No (separate API)
Documentation None (reverse-engineered) Official docs
Stability Can change anytime Versioned

Important Caveats

  1. Innertube is undocumented — YouTube can change it anytime without notice
  2. Be respectful — don't hammer the API. Add delays between requests.
  3. No guarantees — the response format may change
  4. Terms of Service — check YouTube's ToS for your use case

Pre-Built Tools

If you don't want to parse Innertube responses yourself, I built Apify actors that do it:

All available on Apify Store — run in cloud, no setup needed.

Source code and more tools: GitHub


Have you used Innertube before? What did you build with it?

Top comments (0)