Как скрейпить YouTube с прокси: публичные данные, InnerTube API и ротация IP

Практическое руководство по извлечению публичных данных YouTube — метаданные видео, комментарии, транскрипты — с использованием InnerTube API и резидентных прокси для обхода блокировок Google.

Как скрейпить YouTube с прокси: публичные данные, InnerTube API и ротация IP
В этой статье

YouTube — второй по посещаемости сайт в мире и крупнейший публичный архив видео. Для исследователей медиа, аналитиков креатор-экономики и команд мониторинга брендов это бесценный источник: просмотры, тренды, комментарии, субтитры. Но извлечь эти данные масштабно — задача нетривиальная. Google защищает платформу агрессивно, а официальный API быстро упирается в квоты.

Важно: эта статья посвящена исключительно доступу к публичным данным. Соблюдайте Условия использования YouTube, применимое законодательство (CFAA в США, GDPR в ЕС) и права создателей контента. Никогда не распространяйте скрейпенные транскрипты или защищённый контент.

Когда YouTube Data API v3 достаточно — а когда нет

YouTube Data API v3 — официальный способ получать данные программно. Для многих задач он работает отлично: базовые метаданные видео, поиск по ключевым словам, статистика каналов. Но у него есть жёсткие ограничения.

Квоты и стоимость

Каждый проект получает 10 000 единиц квоты в день. Разные методы стоят по-разному:

МетодСтоимость единицЗапросов/день при лимите 10K
videos.list1~10 000
search.list100~100
commentThreads.list1~10 000
playlistItems.list1~10 000

Проблема — search.list. Сто единиц за запрос означает, что вы можете сделать лишь ~100 поисковых запросов в день. Для мониторинга трендов в реальном времени этого катастрофически мало.

Где API подводит

  • Комментарии масштабно: API отдаёт до ~20 комментариев за запрос, требует пагинации, и для канала с миллионами комментариев вы исчерпаете квоту за часы.
  • Раннее обнаружение трендов: API кэширует данные и не даёт субминутного обновления. Скрейпинг страниц трендов быстрее.
  • Мониторинг рекламы: API не предоставляет данные о рекламных вставках — это доступно только через воспроизведение.
  • Транскрипты: API не отдаёт субтитры. Совсем.

Какие данные доступны без входа в аккаунт

YouTube рендерит значительную часть контента для неавторизованных посетителей. Вот что можно извлечь:

  • Метаданные видео: заголовок, описание, количество просмотров, лайков, дата публикации, длительность.
  • Страницы каналов: список видео, описание канала, количество подписчиков.
  • Потоки комментариев: первые ~20 комментариев и их ответы — через InnerTube API.
  • Транскрипты: автоматически сгенерированные и загруженные создателем субтитры.
  • Рекомендации и тренды: содержимое вкладок «В тренде», рекомендованные видео.

Данные, требующие входа: история просмотров, персональные рекомендации, приватные плейлисты, уведомления, данные о рекламе.

InnerTube API — скрытый интерфейс YouTube

YouTube использует внутренний API под названием InnerTube для всех запросов данных на фронтенде. Когда вы открываете страницу видео, браузер делает POST-запрос к эндпоинтам вроде /youtubei/v1/next и /youtubei/v1/player. Эти эндпоинты возвращают JSON с гораздо более богатыми данными, чем публичный API.

Ключевые эндпоинты

ЭндпоинтНазначениеМетод
/youtubei/v1/nextКомментарии, рекомендации, связанное содержимоеPOST
/youtubei/v1/playerМетаданные видео, форматы стримингаPOST
/youtubei/v1/searchРезультаты поискаPOST
/youtubei/v1/browseСтраницы каналов, плейлисты, трендыPOST

Continuation-токены

InnerTube использует continuation-токены для пагинации. Первый запрос к /youtubei/v1/next с ID видео возвращает первые ~20 комментариев и continuation-токен. Каждый последующий запрос с этим токеном отдаёт следующую порцию. Это позволяет обойти ограничения API и извлекать комментарии масштабно.

Почему нужны резидентные прокси

Google — один из самых агрессивных детекторов ботов. Если вы делаете сотни запросов к YouTube с дата-центерных IP-адресов, вы быстро столкнётесь с:

  • CAPTCHA — Google выдаёт страницу с капчей вместо JSON.
  • HTTP 429 — Rate limit, иногда на весь IP-диапазон.
  • Постоянная блокировка — IP попадает в чёрный список на часы или дни.

Google особенно строго фильтрует диапазоны дата-центров (AWS, GCP, Azure, Hetzner, OVH). Это не теория — это наблюдаемая практика. Запросы с DC-IP получают CAPTCHA в 5–10 раз чаще, чем с резидентных.

Резидентные прокси решают эту проблему, потому что каждый запрос приходит с реального IP-адреса домашнего или мобильного провайдера. Google не может массово блокировать такие IP без ущерба для легитимных пользователей.

Для YouTube скрейпинга оптимальная стратегия — ротация IP на каждый запрос (per-request rotation), чтобы ни один IP не накапливал подозрительную активность.

Практика: скрейпинг YouTube с Python и резидентными прокси

Извлечение транскриптов с youtube-transcript-api

Библиотека youtube-transcript-api — самый простой способ получить субтитры. Но при массовом извлечении Google тоже блокирует. Подключаем прокси:

from youtube_transcript_api import YouTubeTranscriptApi
import random

# ProxyHat residential proxy with per-request rotation
PROXY_URL = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"

proxies = {
    "http": PROXY_URL,
    "https": PROXY_URL,
}

video_ids = ["dQw4w9WgXcQ", "jNQXAC9IVRw", "9bZkp7q19f0"]

for vid in video_ids:
    try:
        transcript = YouTubeTranscriptApi.get_transcript(
            vid,
            languages=["en", "ru"],
            proxies=proxies
        )
        full_text = " ".join([entry["text"] for entry in transcript])
        print(f"{vid}: {len(full_text)} chars")
    except Exception as e:
        print(f"{vid}: error — {e}")

Извлечение комментариев через InnerTube

Этот пример обращается к /youtubei/v1/next, извлекает первые комментарии и следует по continuation-токенам:

import requests
import json
import time

PROXY_URL = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"
proxies = {"http": PROXY_URL, "https": PROXY_URL}

INNER_TUBE_HEADERS = {
    "Content-Type": "application/json",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                  "AppleWebKit/537.36 (KHTML, like Gecko) "
                  "Chrome/125.0.0.0 Safari/537.36",
    "Origin": "https://www.youtube.com",
    "Referer": "https://www.youtube.com/",
}

INNER_TUBE_CONTEXT = {
    "context": {
        "client": {
            "clientName": "WEB",
            "clientVersion": "2.20240530.01.00",
            "hl": "en",
            "gl": "US",
        }
    }
}

def fetch_initial_comments(video_id, max_pages=5):
    """Fetch comments via InnerTube /youtubei/v1/next."""
    url = "https://www.youtube.com/youtubei/v1/next"
    payload = {**INNER_TUBE_CONTEXT, "videoId": video_id}
    session = requests.Session()
    session.proxies.update(proxies)

    resp = session.post(url, headers=INNER_TUBE_HEADERS,
                        json=payload, timeout=15)
    resp.raise_for_status()
    data = resp.json()

    comments = []
    continuation_token = None

    # Extract comments and continuation token from response
    for renderer in data.get("contents", {}).get(
        "twoColumnWatchNextResults", {}
    ).get("results", {}).get("results", {}).get("contents", []):
        if "itemSectionRenderer" in renderer:
            section = renderer["itemSectionRenderer"]
            for item in section.get("contents", []):
                if "commentThreadRenderer" in item:
                    cr = item["commentThreadRenderer"]["comment"][
                        "commentRenderer"
                    ]
                    comments.append({
                        "author": cr.get("authorText", {}).get("simpleText", ""),
                        "text": cr.get("contentText", {}).get("runs", [{}])[0].get("text", ""),
                        "likes": cr.get("voteCount", {}).get("simpleText", "0"),
                    })
                if "continuationItemRenderer" in item:
                    continuation_token = item[
                        "continuationItemRenderer"
                    ]["continuationEndpoint"][
                        "continuationCommand"
                    ]["token"]

    # Follow continuation tokens
    pages = 1
    while continuation_token and pages < max_pages:
        time.sleep(1.5)  # polite delay
        cont_payload = {
            **INNER_TUBE_CONTEXT,
            "continuation": continuation_token,
        }
        resp = session.post(url, headers=INNER_TUBE_HEADERS,
                            json=cont_payload, timeout=15)
        resp.raise_for_status()
        cdata = resp.json()

        for action in cdata.get("onResponseReceivedEndpoints", []):
            for item in (action.get("appendContinuationItemsAction", {})
                         .get("continuationItems", [])):
                if "commentThreadRenderer" in item:
                    cr = item["commentThreadRenderer"]["comment"][
                        "commentRenderer"
                    ]
                    comments.append({
                        "author": cr.get("authorText", {}).get("simpleText", ""),
                        "text": cr.get("contentText", {}).get("runs", [{}])[0].get("text", ""),
                        "likes": cr.get("voteCount", {}).get("simpleText", "0"),
                    })
                if "continuationItemRenderer" in item:
                    continuation_token = item[
                        "continuationItemRenderer"
                    ]["continuationEndpoint"][
                        "continuationCommand"
                    ]["token"]
                    break
            else:
                continuation_token = None

        pages += 1

    return comments

comments = fetch_initial_comments("dQw4w9WgXcQ", max_pages=3)
print(f"Extracted {len(comments)} comments")

Метаданные видео через player-эндпоинт

def fetch_video_metadata(video_id):
    """Get video metadata via InnerTube /youtubei/v1/player."""
    url = "https://www.youtube.com/youtubei/v1/player"
    payload = {
        **INNER_TUBE_CONTEXT,
        "videoId": video_id,
    }
    session = requests.Session()
    session.proxies.update(proxies)

    resp = session.post(url, headers=INNER_TUBE_HEADERS,
                        json=payload, timeout=15)
    resp.raise_for_status()
    data = resp.json()

    video_details = data.get("videoDetails", {})
    return {
        "title": video_details.get("title", ""),
        "channel": video_details.get("author", ""),
        "views": video_details.get("viewCount", "0"),
        "length_seconds": video_details.get("lengthSeconds", "0"),
        "description": video_details.get("shortDescription", ""),
        "keywords": video_details.get("keywords", []),
        "is_live": video_details.get("isLiveContent", False),
    }

meta = fetch_video_metadata("dQw4w9WgXcQ")
print(json.dumps(meta, indent=2, ensure_ascii=False))

Node.js: скрейпинг комментариев с InnerTube

Для команд на JavaScript — аналогичный подход с node-fetch и прокси через HTTPS-агент:

import fetch from 'node-fetch';
import { HttpsProxyAgent } from 'https-proxy-agent';

const PROXY_URL = 'http://user-country-US:PASSWORD@gate.proxyhat.com:8080';
const agent = new HttpsProxyAgent(PROXY_URL);

const INNER_TUBE_CTX = {
  context: {
    client: {
      clientName: 'WEB',
      clientVersion: '2.20240530.01.00',
      hl: 'en',
      gl: 'US',
    },
  },
};

async function fetchComments(videoId, maxPages = 3) {
  const url = 'https://www.youtube.com/youtubei/v1/next';
  const headers = {
    'Content-Type': 'application/json',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
      + 'AppleWebKit/537.36 Chrome/125.0.0.0 Safari/537.36',
    Origin: 'https://www.youtube.com',
    Referer: 'https://www.youtube.com/',
  };

  let payload = { ...INNER_TUBE_CTX, videoId };
  const comments = [];
  let continuationToken = null;

  for (let page = 0; page < maxPages; page++) {
    const resp = await fetch(url, {
      method: 'POST',
      headers,
      body: JSON.stringify(payload),
      agent,
    });
    const data = await resp.json();

    const endpoints = data.onResponseReceivedEndpoints
      || data.contents?.twoColumnWatchNextResults
          ?.results?.results?.contents || [];

    for (const endpoint of (Array.isArray(endpoints) ? endpoints : [endpoints])) {
      const items = endpoint.appendContinuationItemsAction
        ?.continuationItems
        || endpoint.itemSectionRenderer?.contents
        || [];
      for (const item of items) {
        if (item.commentThreadRenderer) {
          const cr = item.commentThreadRenderer.comment.commentRenderer;
          comments.push({
            author: cr.authorText?.simpleText ?? '',
            text: cr.contentText?.runs?.[0]?.text ?? '',
            likes: cr.voteCount?.simpleText ?? '0',
          });
        }
        if (item.continuationItemRenderer) {
          continuationToken = item.continuationItemRenderer
            .continuationEndpoint.continuationCommand.token;
        }
      }
    }

    if (!continuationToken) break;
    payload = { ...INNER_TUBE_CTX, continuation: continuationToken };
    await new Promise(r => setTimeout(r, 1500));
  }

  return comments;
}

const comments = await fetchComments('dQw4w9WgXcQ', 3);
console.log(`Extracted ${comments.length} comments`);

Стратегии ротации IP и обхода ограничений

Per-request ротация

Для YouTube оптимальна ротация на каждый запрос. ProxyHat поддерживает это по умолчанию — каждый HTTP-запрос через один и тот же аккаунт получает новый IP из пула резидентных адресов.

Если вам нужна sticky-сессия (например, для последовательного извлечения комментариев с одного IP, чтобы избежать несогласованности данных), используйте флаг сессии:

# Sticky session — один IP на 10 минут
PROXY = "http://user-session-myvid01-country-US:PASSWORD@gate.proxyhat.com:8080"

Геотаргетинг

YouTube показывает разный контент в зависимости от страны. Для мониторинга трендов в конкретном регионе укажите гео-параметр:

# Тренды Германии
PROXY = "http://user-country-DE:PASSWORD@gate.proxyhat.com:8080"

Это особенно важно для SERP-трекинга и сравнения трендов между рынками.

Rate limiting: практические рекомендации

  • 1–2 секунды между запросами с одного IP — минимум вежливости.
  • Не более 50–100 запросов с одного IP за короткий период.
  • Ротируйте User-Agent — используйте пул реальных UA Chrome/Firefox.
  • Обрабатывайте 429 и CAPTCHA — экспоненциальная задержка и смена IP.

Риски фингерпринтинга

Google анализирует не только IP, но и паттерны запросов:

  • TLS-фингерпринт — библиотека requests на Python использует TLS-стек, отличающийся от Chrome. Google может это обнаружить. Используйте curl_cffi или tls_client для имитации реального браузера.
  • Порядок заголовков — InnerTube-запросы должны точно повторять порядок заголовков Chrome.
  • Паттерн доступа — если вы запрашиваете 100 видео подряд без единого клика по рекомендациям, это подозрительно. Вставляйте «шумовые» запросы.

Сравнение подходов к извлечению данных YouTube

МетодДанныеМасштабБлокировкиСложность
YouTube Data API v3Метаданные, поиск, комментарииОграничен квотамиНетНизкая
InnerTube API + проксиМетаданные, комментарии, рекомендации, трендыВысокийУмеренныеСредняя
youtube-transcript-api + проксиТранскриптыСреднийУмеренныеНизкая
Браузерная автоматизация (Puppeteer/Playwright)Все видимые данные + рекламаНизкийВысокиеВысокая
Официальные отчёты YouTube AnalyticsПолная аналитика собственного каналаНеограниченНетНизкая (только свои данные)

Этический скрейпинг: когда использовать официальные API

Скрейпинг — мощный инструмент, но не всегда правильный. Вот принципы, которых мы рекомендуем придерживаться:

  1. Сначала проверьте API. Если YouTube Data API v3 покрывает ваши потребности — используйте его. Это стабильнее, законнее и надёжнее.
  2. Не перераспределяйте скрейпенный контент. Транскрипты, описания и комментарии — интеллектуальная собственность создателей. Извлечение для анализа — одно, перепродажа или публикация — другое.
  3. Соблюдайте robots.txt. YouTube разрешает некоторые пути и запрещает другие. Уважайте эти правила.
  4. Не пытайтесь обойти paywall или авторизацию. Если данные требуют входа — они не являются публичными.
  5. Минимизируйте нагрузку. Не делайте запросов больше, чем нужно. Кэшируйте результаты.
  6. Учитывайте GDPR и CCPA. Комментарии пользователей содержат персональные данные. Если вы извлекаете комментарии из ЕС или Калифорнии — вы несёте ответственность за их обработку.

Практическое правило: если вы анализируете тренды для внутреннего исследования — вы на устойчивой почве. Если вы перепродаёте данные или публикуете их без согласия — вы на тонком льду.

Подробнее об этике и практике скрейпинга — в нашем руководстве по веб-скрейпингу.

Key Takeaways

  • YouTube Data API v3 подходит для базовых задач, но квота в 10 000 единиц/день — жёсткое ограничение, особенно для поиска и масштабного извлечения комментариев.
  • InnerTube API (/youtubei/v1/next, /youtubei/v1/player, /youtubei/v1/browse) — более мощный и гибкий способ получения публичных данных, но требует имитации реального клиента.
  • Резидентные прокси необходимы для масштабного скрейпинга YouTube — Google агрессивно блокирует дата-центерные IP-диапазоны.
  • Ротация IP на каждый запрос — оптимальная стратегия для YouTube; sticky-сессии — для последовательного извлечения с одного IP.
  • Геотаргетинг позволяет видеть региональные тренды и рекомендации — критически важно для медиа-аналитики.
  • Транскрипты доступны через youtube-transcript-api с прокси, но не через официальный API.
  • Этика прежде масштаба: не перераспределяйте контент создателей, соблюдайте ToS, GDPR и CCPA, используйте API когда возможно.

Готовы начать извлечение данных YouTube с надёжными резидентными прокси? Ознакомьтесь с тарифами ProxyHat и доступными локациями — более 190 стран для точного геотаргетинга.

Часто задаваемые вопросы

Зачем нужны резидентные прокси для скрейпинга YouTube?

Google агрессивно блокирует запросы с IP-адресов дата-центров (AWS, OVH, Hetzner и др.), выдавая CAPTCHA или HTTP 429. Резидентные прокси используют IP реальных домашних и мобильных провайдеров, что значительно снижает риск блокировки, поскольку Google не может массово блокировать такие IP без ущерба для легитимных пользователей.

Что такое InnerTube API YouTube?

InnerTube — внутренний API YouTube, который фронтенд использует для загрузки данных. Ключевые эндпоинты: /youtubei/v1/next (комментарии, рекомендации), /youtubei/v1/player (метаданные видео), /youtubei/v1/browse (каналы, тренды). Он возвращает более детальные данные, чем публичный Data API v3, но требует имитации реального клиентского запроса.

Можно ли получить транскрипты видео через YouTube Data API v3?

Нет, YouTube Data API v3 не предоставляет доступ к субтитрам и транскриптам. Для этого нужно использовать библиотеку youtube-transcript-api (Python) или извлекать данные через InnerTube player-эндпоинт, который содержит информацию о доступных субтитрах.

Какие данные YouTube доступны без авторизации?

Без входа в аккаунт доступны: метаданные видео (заголовок, описание, просмотры, лайки), страницы каналов, потоки комментариев, транскрипты, рекомендации и тренды. Недоступны: персональные рекомендации, история просмотров, приватные плейлисты и данные о рекламе.

Легален ли скрейпинг публичных данных YouTube?

Извлечение публично доступных данных для внутреннего анализа, как правило, допустимо, но зависит от юрисдикции. Необходимо соблюдать Условия использования YouTube, законодательство (CFAA в США, GDPR в ЕС), права создателей контента и не перераспределять скрейпенные данные. Если YouTube Data API покрывает ваши потребности — предпочтительнее использовать его.

Готовы начать?

Резидентные, ISP и мобильные прокси в 148+ странах. Создайте бесплатный аккаунт.

Создать бесплатный аккаунт
← Вернуться в Блог