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:
| Operacja | Koszt (jednostki) | Max zapytań/dzień |
|---|---|---|
search.list | 100 | 100 |
videos.list | 1 | 10 000 |
commentThreads.list | 1 | 10 000 |
channels.list | 1 | 10 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-apito 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
| Kryterium | YouTube Data API v3 | InnerTube scraping | youtube-transcript-api |
|---|---|---|---|
| Stabilność | Wysoka (udokumentowane) | Niska (nieoficjalne) | Średnia |
| Limity | 10 000 jednostek/dzień | Brak twardych (soft rate limits) | Brak twardych |
| Dane komentarzy | Tak (z quota) | Tak (continuation) | Nie |
| Transkrypcje | Nie | Tak (player response) | Tak |
| Wymagany klucz API | Tak | Nie | Nie |
| Wymagane proxy | Rzadko | Tak (przy skali) | Tak (przy skali) |
| Koszt utrzymania | Niski | Wysoki (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
OriginiReferer— YouTube weryfikuje te nagłówki. - Rozważ biblioteki takie jak
curl_cffiw 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.






