Jak skrapować publiczne dane YouTube z proxy — kompletny przewodnik

Dowiedz się, jak wydobywać metadane, komentarze i transkrypcje z YouTube przy użyciu residential proxy, InnerTube API i Pythona — bez blokad i z poszanowaniem prawa.

Jak skrapować publiczne dane YouTube z proxy — kompletny przewodnik

Każdy zespół analityczny zajmujący się mediami wie, że YouTube to kopalnia danych: trendy, nastroje odbiorców, strategie konkurencji, monitoring reklam. Problem polega na tym, że oficjalne YouTube Data API v3 szybko wyczerpuje limity, a Google bezlitośnie blokuje masowe zapytania z datacenter. Jeśli potrzebujesz skrapować YouTube z proxy w skali, która wykracza poza pojedyncze zapytania testowe — ten przewodnik jest dla Ciebie.

Ważne zastrzeżenie: Skrapowanie danych z YouTube musi respektować Warunki Usługi YouTube (ToS), obowiązujące przepisy (CFAA w USA, GDPR w UE) oraz prawa twórców. Ten artykuł dotyczy wyłącznie publicznie dostępnych danych — metadanych, statystyk, komentarzy publicznych i transkrypcji. Nie zachęcamy do redystrybucji treści wideo, transkrypcji ani do omijania logowania w celu dostępu do treści ograniczonych.

Kiedy YouTube Data API v3 wystarcza — a kiedy nie

YouTube Data API v3 to oficjalny, udokumentowany sposób na dostęp do danych. Dla wielu zastosowań jest wystarczający. Problem pojawia się przy skali.

Limity i koszty API v3

Google przyznaje każdemu projektowi 10 000 jednostek quoty dziennie. Różne operacje zużywają różną liczbę jednostek:

OperacjaKoszt (jednostki)Max zapytań/dzień
search.list100100
videos.list110 000
commentThreads.list110 000
channels.list110 000

Widzisz problem? 100 wyszukiwań dziennie to nic dla zespołu monitorującego trendy. Jeśli śledzisz 500 kanałów i chcesz codziennie pobierać ich metadane — channels.list jest OK. Ale jeśli potrzebujesz wyszukiwać nowe trendy w czasie rzeczywistym, quota kończy się przed południem.

Kiedy scraping wypełnia lukę

  • Wątki komentarzy w skali — API zwraca max 100 komentarzy na żądanie z continuation tokenem; przy tysiącach filmów quota znika szybko.
  • Wczesne wykrywanie trendów — potrzebujesz wyszukiwań co kilka minut, a nie co kilka godzin.
  • Monitoring reklam — YouTube API nie udostępnia danych o wyświetlanych reklamach; scraping stron filmowych pozwala zbierać informacje o adPlacement.
  • Transkrypcje — API v3 nie oferuje dostępu do transkrypcji; scraping InnerTube lub użycie youtube-transcript-api to jedyne opcje.

Jakie dane YouTube są dostępne bez logowania

Bez konta Google i bez autoryzacji możesz uzyskać dostęp do:

  • Metadane filmów — tytuł, opis, liczba wyświetleń, likes, data publikacji, kategoria.
  • Strony kanałów — nazwa, opis, liczba subskrybentów, lista filmów.
  • Wątki komentarzy — komentarze najwyższego poziomu i odpowiedzi (publiczne).
  • Transkrypcje — automatycznie generowane i ręczne (jeśli włączone przez twórcę).
  • Rekomendacje — sidebar z powiązanymi filmami.

Dane za logowaniem: historia oglądania, rekomendacje spersonalizowane, komentarze prywatne, statystyki YouTube Studio. Nie próbuj omijać logowania — to narusza ToS i potencjalnie CFAA.

InnerTube API — nieoficjalny, ale potężny

YouTube używa wewnętrznego API o nazwie InnerTube do komunikacji między frontendem a backendem. Każde załadowanie strony w przeglądarce generuje żądania do endpointów takich jak:

  • /youtubei/v1/next — następna strona wyników (continuation).
  • /youtubei/v1/browse — przeglądanie kanałów i playlist.
  • /youtubei/v1/player — player response z metadanymi filmu.
  • /youtubei/v1/search — wyszukiwanie.

InnerTube zwraca czysty JSON — dużo czystszy niż parsowanie HTML. Wymaga jednak odpowiednich nagłówków i parametrów kontekstowych, które YouTube może zmieniać.

Struktura żądania InnerTube

{
  "context": {
    "client": {
      "clientName": "WEB",
      "clientVersion": "2.20250101.00.00",
      "hl": "pl",
      "gl": "PL"
    }
  },
  "videoId": "dQw4w9WgXcQ"
}

Endpointy InnerTube nie są udokumentowane i mogą się zmieniać. To oznacza, że Twój kod scrapera wymaga regularnej konserwacji — to koszt, który trzeba uwzględnić w planowaniu.

Dlaczego residential proxy są niezbędne do scrapingu YouTube

Google to jeden z najbardziej zaawansowanych systemów detekcji botów na świecie. Ich infrastruktura potrafi identyfikować ruch z datacenter z niesamowitą precyzją.

Google flaguje zakresy IP datacenter

Google utrzymuje bazy danych zakresów IP należących do dostawców cloudowych (AWS, GCP, Azure, DigitalOcean itd.). Żądania z tych zakresów są traktowane z większą podejrzliwością:

  • Rate limiting — znacznie niższe progi niż dla residential IP.
  • CAPTCHA — szybciej wyzwalane wyzwania weryfikacyjne.
  • Bloki IP — tymczasowe lub stałe blokady całych podsieci.

Residential proxy rozwiązuje ten problem, ponieważ Twoje żądania wychodzą z adresów IP przypisanych do zwykłych dostawców internetowych — dokładnie tak, jak ruch prawdziwych użytkowników.

Rotacja IP vs sticky sessions

Dla scrapingu YouTube strategia rotacji zależy od typu operacji:

  • Rotacja per-request — idealna do pobierania metadanych pojedynczych filmów. Każde żądanie z nowego IP.
  • Sticky sessions — niezbędne do paginacji komentarzy. Continuation tokens są powiązane z sesją; zmiana IP w środku paginacji często powoduje błędy.

Z ProxyHat możesz kontrolować to zachowanie przez parametry w nazwie użytkownika:

# Rotacja per-request (domyślna)
http://user-country-US:pass@gate.proxyhat.com:8080

# Sticky session na 10 minut
http://user-session-abc123:pass@gate.proxyhat.com:8080

Implementacja w Pythonie — scraping YouTube z residential proxy

Przykład 1: Pobieranie transkrypcji

Biblioteka youtube-transcript-api to najprostszy sposób na pobranie transkrypcji. Działa na publicznych danych i nie wymaga klucza API.

from youtube_transcript_api import YouTubeTranscriptApi
import requests

# Konfiguracja proxy ProxyHat
proxy_url = "http://user-country-US:pass@gate.proxyhat.com:8080"
proxies = {
    "http": proxy_url,
    "https": proxy_url,
}

# youtube-transcript-api nie ma wbudowanej obsługi proxy,
# więc używamy monkey-patching sesji requests
import youtube_transcript_api._api
original_get = youtube_transcript_api._api.requests.get

def proxied_get(url, **kwargs):
    kwargs["proxies"] = proxies
    kwargs["timeout"] = 15
    return original_get(url, **kwargs)

youtube_transcript_api._api.requests.get = proxied_get

# Pobieranie transkrypcji
video_id = "dQw4w9WgXcQ"
try:
    transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=["pl", "en"])
    for entry in transcript:
        print(f"[{entry['start']:.1f}s] {entry['text']}")
except Exception as e:
    print(f"Błąd: {e}")

Przykład 2: Metadane filmu przez InnerTube

import requests
import json

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

INNER_TUBE_URL = "https://www.youtube.com/youtubei/v1/player"

def get_video_metadata(video_id: str) -> dict:
    payload = {
        "context": {
            "client": {
                "clientName": "WEB",
                "clientVersion": "2.20250615.00.00",
                "hl": "en",
                "gl": "US",
            }
        },
        "videoId": video_id,
    }
    headers = {
        "Content-Type": "application/json",
        "User-Agent": (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/126.0.0.0 Safari/537.36"
        ),
        "Origin": "https://www.youtube.com",
        "Referer": f"https://www.youtube.com/watch?v={video_id}",
    }
    resp = requests.post(
        INNER_TUBE_URL,
        json=payload,
        headers=headers,
        proxies=proxies,
        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"),
        "length_seconds": video_details.get("lengthSeconds"),
        "description": video_details.get("shortDescription"),
        "keywords": video_details.get("keywords", []),
    }

# Użycie
meta = get_video_metadata("dQw4w9WgXcQ")
print(json.dumps(meta, indent=2, ensure_ascii=False))

Przykład 3: Paginacja komentarzy z continuation tokens

Komentarze wymagają sticky sessions — continuation token jest powiązany z sesją serwera.

import requests
import json
import time

# Sticky session — ten sam IP dla całej paginacji
proxy_url = "http://user-session-comments1:pass@gate.proxyhat.com:8080"
proxies = {"http": proxy_url, "https": proxy_url}

NEXT_URL = "https://www.youtube.com/youtubei/v1/next"

def fetch_comments(video_id: str, max_pages: int = 5) -> list:
    # Pierwsze żądanie — pobranie strony filmu z komentarzami
    payload = {
        "context": {
            "client": {
                "clientName": "WEB",
                "clientVersion": "2.20250615.00.00",
                "hl": "en",
                "gl": "US",
            }
        },
        "videoId": video_id,
    }
    headers = {
        "Content-Type": "application/json",
        "User-Agent": (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/126.0.0.0 Safari/537.36"
        ),
    }

    all_comments = []
    continuation_token = None

    for page in range(max_pages):
        if continuation_token:
            payload = {
                "context": {
                    "client": {
                        "clientName": "WEB",
                        "clientVersion": "2.20250615.00.00",
                        "hl": "en",
                        "gl": "US",
                    }
                },
                "continuation": continuation_token,
            }

        resp = requests.post(
            NEXT_URL,
            json=payload,
            headers=headers,
            proxies=proxies,
            timeout=20,
        )
        resp.raise_for_status()
        data = resp.json()

        # Ekstrakcja komentarzy z onResponseReceivedEndpoints
        comments_found = False
        for endpoint in data.get("onResponseReceivedEndpoints", []):
            renderer = endpoint.get("reloadContinuationItemsCommand") \
                or endpoint.get("appendContinuationItemsAction", {})
            items = renderer.get("continuationItems", [])
            for item in items:
                thread = item.get("commentThreadRenderer")
                if thread:
                    comment = thread.get("comment", {}).get("commentRenderer", {})
                    author = comment.get("authorText", {}).get("simpleText", "")
                    text_runs = comment.get("contentText", {}).get("runs", [])
                    text = " ".join(r.get("text", "") for r in text_runs)
                    likes = comment.get("voteCount", {}).get("simpleText", "0")
                    all_comments.append({
                        "author": author,
                        "text": text,
                        "likes": likes,
                    })
                    comments_found = True

                # Continuation token na końcu listy
                cont = item.get("continuationItemRenderer")
                if cont:
                    continuation_token = cont.get("continuationEndpoint", \
                        {}).get("continuationCommand", {}).get("token")

        if not continuation_token or not comments_found:
            break

        time.sleep(2)  # Szacunek dla serwerów YouTube

    return all_comments

comments = fetch_comments("dQw4w9WgXcQ", max_pages=3)
print(f"Pobrano {len(comments)} komentarzy")
for c in comments[:5]:
    print(f"  {c['author']}: {c['text'][:80]}...")

Przykład 4: Node.js — pobieranie metadanych z rotacją proxy

const axios = require('axios');

const proxyConfig = {
  host: 'gate.proxyhat.com',
  port: 8080,
  auth: {
    username: 'user-country-US',
    password: 'pass',
  },
};

async function getVideoMeta(videoId) {
  const payload = {
    context: {
      client: {
        clientName: 'WEB',
        clientVersion: '2.20250615.00.00',
        hl: 'en',
        gl: 'US',
      },
    },
    videoId,
  };

  const resp = await axios.post(
    'https://www.youtube.com/youtubei/v1/player',
    payload,
    {
      proxy: proxyConfig,
      headers: {
        'Content-Type': 'application/json',
        'User-Agent':
          'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' +
          'AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36',
      },
      timeout: 15000,
    }
  );

  const details = resp.data.videoDetails || {};
  return {
    title: details.title,
    channel: details.author,
    views: details.viewCount,
    description: details.shortDescription,
  };
}

getVideoMeta('dQw4w9WgXcQ')
  .then(d => console.log(JSON.stringify(d, null, 2)))
  .catch(e => console.error('Błąd:', e.message));

Porównanie: API v3 vs InnerTube scraping vs Transkrypt API

KryteriumYouTube Data API v3InnerTube scrapingyoutube-transcript-api
StabilnośćWysoka (udokumentowane)Niska (nieoficjalne)Średnia
Limity10 000 jednostek/dzieńBrak twardych (soft rate limits)Brak twardych
Dane komentarzyTak (z quota)Tak (continuation)Nie
TranskrypcjeNieTak (player response)Tak
Wymagany klucz APITakNieNie
Wymagane proxyRzadkoTak (przy skali)Tak (przy skali)
Koszt utrzymaniaNiskiWysoki (zmiany API)Średni

Zarządzanie rate limiting i fingerprintami

Google nie publikuje swoich progów rate limit dla ruchu webowego, ale z doświadczenia:

  • ~200 żądań/minutę z jednego IP — bezpieczny próg przed CAPTCHA.
  • ~50 żądań/minutę z jednego IP — zalecane dla długich sesji scrapingu.
  • Rozłóż żądania w czasie — losowe opóźnienia 1–4 sekundy między żądaniami.

Fingerprint przeglądarki

InnerTube sprawdza więcej niż tylko IP. Nagłówki HTTP, kolejność nagłówków, TLS fingerprint — to wszystko ma znaczenie. Kilka zasad:

  • Używaj realistycznego nagłówka User-Agent — najlepiej Chrome na Windows.
  • Dołączaj Origin i Referer — YouTube weryfikuje te nagłówki.
  • Rozważ biblioteki takie jak curl_cffi w Pythonie, które emulują TLS fingerprint przeglądarki.
  • Nie wysyłaj żądań z identycznymi nagłówkami w szybkim succession — dodaj losowość.

Wzorzec backoff przy CAPTCHA

import requests
import time
import random

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

def fetch_with_backoff(url, payload, headers, max_retries=3):
    for attempt in range(max_retries):
        try:
            resp = requests.post(url, json=payload, headers=headers,
                                 proxies=proxies, timeout=20)
            if resp.status_code == 429:
                wait = (2 ** attempt) + random.uniform(0, 2)
                print(f"Rate limited. Czekam {wait:.1f}s...")
                time.sleep(wait)
                continue
            # Sprawdź CAPTCHA w odpowiedzi
            if "captcha" in resp.text.lower():
                print("CAPTCHA wykryta — zmiana IP...")
                # Z ProxyHat: zmiana nazwy użytkownika = nowy IP
                return None  # Handle w logice biznesowej
            resp.raise_for_status()
            return resp.json()
        except requests.exceptions.RequestException as e:
            wait = (2 ** attempt) + random.uniform(0, 2)
            print(f"Błąd (próba {attempt+1}): {e}. Czekam {wait:.1f}s...")
            time.sleep(wait)
    return None

Geo-targeting — dlaczego lokalizacja proxy ma znaczenie

YouTube dostarcza różne treści w zależności od lokalizacji:

  • Trendy są różne w każdym kraju.
  • Niektóre filmy są zablokowane regionalnie.
  • Reklamy są lokalizowane — kluczowe dla monitoring ad.
  • Kolejność wyników wyszukiwania różni się między krajami.

Z ProxyHat możesz geo-targetować żądania:

# Trendy w Niemczech
proxy_de = "http://user-country-DE:pass@gate.proxyhat.com:8080"

# Trendy w Japonii
proxy_jp = "http://user-country-JP:pass@gate.proxyhat.com:8080"

# Trendy w Brazylii
proxy_br = "http://user-country-BR:pass@gate.proxyhat.com:8080"

To kluczowe dla zespołów monitorujących trendy globalnie — pozwala porównywać, co trenduje w różnych rynkach, z jednego skryptu.

Etyka scrapingu YouTube — kiedy używać oficjalnego API

Skrapowanie danych publicznych jest legalne w wielu jurysdykcjach, ale to nie znaczy, że zawsze jest właściwe. Kilka zasad:

Kiedy oficjalne API jest lepszym wyborem

  • Mała skala — jeśli potrzebujesz < 100 wyszukiwań dziennie, API v3 jest stabilniejsze i bardziej etyczne.
  • Dane do celów wewnętrznych — jeśli nie redystrybuujesz danych, API jest bezpieczniejsze prawnie.
  • Stabilność krytyczna — InnerTube może się zmienić bez ostrzeżenia; API v3 jest versioned i stabilne.

Czego NIE robić

  • Nie redystrybuuj transkrypcji — transkrypcje są dziełem twórcy (lub automatycznie generowane na jego treści). Pobieranie do analizy sentymentu — OK. Publikowanie na innym portalu — naruszenie praw autorskich.
  • Nie omijaj logowania — dane dostępne tylko po zalogowaniu są celowo ograniczone. Scrapowanie ich narusza ToS i potencjalnie CFAA.
  • Nie przeciążaj infrastruktury — rozsądne opóźnienia między żądaniami to nie tylko technika unikania blokad, to szacunek dla infrastruktury.
  • Nie skrapuj danych prywatnych — komentarze usunięte przez użytkowników, prywatne wiadomości, dane z YouTube Studio.

GDPR i prawa podmiotów danych

Komentarze YouTube zawierają dane osobowe — nazwy użytkowników, treść wypowiedzi. Jeśli przetwarzasz te dane w UE:

  • Musisz mieć podstawę prawną przetwarzania (np. uzasadniony interes).
  • Podmioty danych mają prawo do usunięcia („prawo do bycia zapomnianym”).
  • Anonimizacja danych przed przechowywaniem jest dobrą praktyką.

Kluczowe wnioski

  • YouTube Data API v3 jest wystarczające dla małej skali — ale quota na search.list (100/dzień) szybko staje się wąskim gardłem.
  • InnerTube API daje dostęp do tych samych danych co przeglądarka — bez limitów quota, ale z ryzykiem zmian bez ostrzeżenia.
  • Residential proxy są niezbędne przy masowym scrapingu — Google skutecznie flaguje zakresy IP datacenter.
  • Sticky sessions są wymagane do paginacji komentarzy — continuation tokens są powiązane z sesją.
  • Geo-targeting proxy pozwala porównywać trendy i reklamy między rynkami.
  • Etyka ma znaczenie — nie redystrybuuj transkrypcji, nie omijaj logowania, szanuj GDPR.

Jeśli Twój zespół potrzebuje YouTube residential proxies do skalowalnego wydobywania danych — sprawdź plany ProxyHat i zacznij z rotacyjnymi residential proxy w kilka minut. Dostępne są też lokalizacje proxy w ponad 190 krajach, co pozwala na precyzyjny geo-targeting trendów YouTube na każdym rynku.

Dla dalszej lektury o technikach scrapingu z proxy, zobacz nasz artykuł o web scrapingu z residential proxy oraz SERP tracking z ProxyHat.

Gotowy, aby zacząć?

Dostęp do ponad 50 mln rezydencjalnych IP w ponad 148 krajach z filtrowaniem AI.

Zobacz cenyProxy rezydencjalne
← Powrót do Bloga