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
W tym artykule

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.

Często zadawane pytania

Czy skrapowanie YouTube jest legalne?

Skrapowanie publicznie dostępnych danych z YouTube (metadane, publiczne komentarze, statystyki) jest legalne w wielu jurysdykcjach na podstawie doktryny publicznego dostępu. Należy jednak respektować Warunki Usługi YouTube, nie omijać logowania i nie redystrybuować chronionych prawem autorskim treści, takich jak transkrypcje. W UE uwzględnij też wymogi GDPR dotyczące danych osobowych w komentarzach.

Czym jest YouTube InnerTube API?

InnerTube to wewnętrzne API YouTube używane przez frontend do komunikacji z backendem. Udostępnia endpointy takie jak /youtubei/v1/player, /youtubei/v1/next i /youtubei/v1/search, które zwracają czysty JSON z metadanymi, komentarzami i wynikami wyszukiwania. Nie jest udokumentowane i może się zmieniać bez ostrzeżenia.

Dlaczego potrzebuję residential proxy do scrapingu YouTube?

Google skutecznie identyfikuje i flaguje ruch z zakresów IP datacenter (AWS, Azure, GCP), nakładając niższe limity żądań i szybciej wyzwalając CAPTCHA. Residential proxy sprawiają, że ruch wygląda jak pochodzący od zwykłych użytkowników ISP, co pozwala na znacznie wyższe wolumeny scrapingu bez blokad.

Ile kosztuje YouTube Data API v3?

YouTube Data API v3 jest darmowy, ale ma limit 10 000 jednostek quoty dziennie na projekt. Najbardziej kosztowna operacja to search.list (100 jednostek), co daje tylko 100 wyszukiwań dziennie. Możesz wystąpić o zwiększenie quota, ale Google rzadko przyznaje znaczące zwiększenia dla zastosowań scrapingu.

Jak pobierać transkrypcje z YouTube w Pythonie?

Najprostszym sposobem jest biblioteka youtube-transcript-api. Instalujesz ją przez pip install youtube-transcript-api i wywołujesz YouTubeTranscriptApi.get_transcript(video_id). Zwraca listę słowników z polami text, start i duration. Przy masowym pobieraniu używaj residential proxy, aby uniknąć blokad.

Czy Twoje proxy są blokowane podczas scrapingu?

Wykonaj darmowy test proxy — współczynnik blokad, prędkość i anonimowość w kilka sekund. Bez rejestracji.

Sprawdź proxy za darmo
← Powrót do Bloga