Medya analitiği ekipleri ve içerik ekonomisi araştırmacıları için YouTube, paha biçilemez bir veri kaynağıdır. Ancak YouTube Data API v3 kotaları, ölçekli veri çekme ihtiyaçlarını karşılamada yetersiz kalır. Bir yorum dizisi çekimi bile kısa sürede günlük kotanızı tüketebilir. Bu rehberde, YouTube'dan residential proxy kullanarak nasıl veri çekeceğinizi, InnerTube API'sini nasıl kullanacağınızı ve etik sınırları nasıl koruyacağınızı detaylandıracağız.
Önemli Uyarı: Bu rehber yalnızca kamuya açık verilere erişim için geçerlidir. YouTube'un Hizmet Şartları scraping'i yasaklar; bu nedenle tüm işlemlerinizde ABD'de CFAA, AB'de GDPR ve ilgili yerel yasalara uyum sağlamaktan siz sorumlusunuz. Topladığınız transkriptleri veya video içeriklerini yeniden dağıtmayın; yaratıcıların mülkiyet haklarına saygı gösterin.
YouTube Data API v3 Ne Zaman Yeterli, Ne Zaman Yetersiz?
YouTube Data API v3, küçük ölçekli projeler için harika bir başlangıç noktasıdır. Ancak ölçek arttıkça ciddi darboğazlarla karşılaşırsınız.
Kota Sistemi ve Maliyet Yapısı
API v3, her isteğinizi kota birimi cinsinden ölçer. Günlük varsayılan kota 10.000 birimdir. İşte temel işlemlerin maliyeti:
| İşlem | Kota Birimi Maliyeti | Günlük 10K Kota ile Yaklaşık Kapasite |
|---|---|---|
| video.list (tek video) | 1 | 10.000 video |
| search.list (arama) | 100 | 100 arama |
| commentThreads.list | 1 | 10.000 yorum |
| channels.list | 1 | 10.000 kanal |
Bu tablo umut verici görünebilir, ancak arama işlemlerinin 100 birim tükettiğini fark edin. 100 arama ile günlük kotanız biter. Yorum çekimi 1 birim görünse de, bir popüler videoda 50.000+ yorum olabilir ve continuation token'ları ile sayfalama yapmanız gerekir — bu da hızlı bir şekilde binlerce birim tüketir.
API'nin Yetersiz Kaldığı Senaryolar
- Yorum dizilerini ölçekli çekme: Binlerce video için yorum analizi yapıyorsanız API kotaları günlerce beklemenize neden olur.
- Erken trend tespiti: Yeni yüklenen videoların anlık performans metriklerini dakikalar içinde izlemek istediğinizde API'nin güncelleme hızı yetersiz kalır.
- Reklam izleme: API v3, videolarda hangi reklamların gösterildiğine dair hiçbir veri sunmaz; bu bilgi yalnızca sayfa scraping ile elde edilir.
- Öneri algoritması haritalama: Bir videodan hangi önerilerin çıktığı, API'de mevcut değildir.
Giriş Yapmadan Erişilebilen Veriler
YouTube'da oturum açmadan, yalnızca sayfa istekleri ile erişebileceğiniz veriler şunlardır:
- Video metadatası: Başlık, açıklama, yükleme tarihi, süre, kategori, etiketler
- Etkileşim metrikleri: Görüntülenme sayısı, beğeni/beğenmeme, yorum sayısı
- Kanal bilgileri: Kanal adı, abone sayısı, toplam video sayısı, açıklama
- Yorum dizileri: Hem üst düzey yorumlar hem de yanıtlar
- Transkriptler: Otomatik veya manuel altyazılar
- Öneri videoları: Bir videonun yan panelinde listelenen öneriler
Giriş duvarlı veriler: Yaş doğrulaması gereken videolar, üyeliğe özel içerikler ve bazı özel playlist'ler erişilemez. Bu verileri çekmeye çalışmak hem etik değil hem de teknik olarak karmaşık CAPTCHA süreçleri gerektirir.
InnerTube API: YouTube'un Dahili Arayüzü
YouTube, web ve mobil istemcilerinde InnerTube adlı dahili bir JSON API kullanır. Bu endpoint'ler, YouTube'un kendi SPA'sı (Single Page Application) tarafından çağrılır ve standart HTTP istekleri ile erişilebilir.
Temel InnerTube Endpoint'leri
| Endpoint | İşlev | Örnek Kullanım |
|---|---|---|
/youtubei/v1/player | Video oynatıcı detayları, akış bilgileri | Video metadatası, format listesi |
/youtubei/v1/next | Sonraki içerik, öneriler, yorumlar | Yorum dizisi çekimi, öneri haritalama |
/youtubei/v1/browse | Kanal sayfası, playlist içerikleri | Kanal videolarını listeleme |
/youtubei/v1/search | Arama sonuçları | Anahtar kelime bazlı video bulma |
InnerTube İstek Yapısı
Her InnerTube isteği bir JSON body ve özel header'lar gerektirir. İşte temel bir /youtubei/v1/next isteğinin yapısı:
{
"videoId": "dQw4w9WgXcQ",
"context": {
"client": {
"clientName": "WEB",
"clientVersion": "2.20240101"
},
"hl": "tr",
"gl": "TR"
},
"continuation": "optional_continuation_token"
}
clientName alanını WEB, MWEB (mobil web) veya ANDROID olarak değiştirerek farklı yanıt yapıları elde edebilirsiniz. Mobil istemciler genellikle daha az CAPTCHA tetikler.
Continuation Token'lar ve Sayfalama
InnerTube, yorum ve öneri listelerini continuation token ile sayfalar. İlk yanıt bir continuationEndpoint veya continuationCommand içerir; bu token'ı sonraki isteğin continuation alanına koyarak bir sonraki sayfayı çekersiniz. Bu, API v3'ün pageToken mekanizmasına benzer, ancak kota maliyeti yoktur.
Neden Residential Proxy Zorunludur?
Google, datacenter IP aralıklarını çok iyi tanır. Bir veri merkezinden gelen yoğun istekler dakikalar içinde şu yanıtlarla karşılaşır:
- HTTP 429 Too Many Requests
- CAPTCHA sayfası (HTTP 200 ile dönen HTML)
- Boş veya eksik JSON yanıtları
Residential proxy'ler, gerçek İnternet Servis Sağlayıcılarından (ISP) gelen IP adresleri kullanır. Google'ın bot filtreleri, bu IP'leri normal kullanıcı trafiği olarak değerlendirir. Bu nedenle YouTube residential proxies, ölçekli veri çekme işlemlerinde zorunludur.
IP Rotasyon Stratejileri
- Per-request rotasyon: Her istek için yeni IP. Yorum çekimi ve arama gibi yüksek hacimli işlemler için ideal.
- Sticky session: Aynı IP üzerinde 10-30 dakika oturum. Video metadatası çekimi gibi tutarlı oturum gerektiren işlemler için uygun.
ProxyHat ile her iki stratejiyi de kullanıcı adı parametreleri ile kontrol edebilirsiniz:
# Per-request rotasyon (her istekte yeni IP)
http://user-country-US:PASSWORD@gate.proxyhat.com:8080
# Sticky session (aynı IP üzerinde kalıcı oturum)
http://user-session-vid123-country-US:PASSWORD@gate.proxyhat.com:8080
Python ile YouTube Veri Çekme
Örnek 1: Video Metadatası ve Yorumlar (InnerTube + Proxy)
Aşağıdaki örnek, bir videonun temel metadatasını ve ilk yorum sayfasını InnerTube üzerinden çeker:
import requests
import json
PROXY_URL = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"
PROXIES = {"http": PROXY_URL, "https": PROXY_URL}
INNERBASE = "https://www.youtube.com/youtubei/v1/next"
HEADERS = {
"Content-Type": "application/json",
"User-Agent": (
"Mozilla/5.0 (Linux; Android 12; Pixel 6) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Mobile Safari/537.36"
),
"X-YouTube-Client-Name": "2",
"X-YouTube-Client-Version": "18.01.01",
}
def fetch_video_comments(video_id: str, max_pages: int = 5):
"""InnerTube /next endpoint ile yorum çeker."""
all_comments = []
continuation = None
payload = {
"videoId": video_id,
"context": {
"client": {
"clientName": "MWEB",
"clientVersion": "18.01.01",
},
"hl": "en",
"gl": "US",
},
}
for page in range(max_pages):
if continuation:
payload["continuation"] = continuation
resp = requests.post(
INNERBASE,
json=payload,
headers=HEADERS,
proxies=PROXIES,
timeout=30,
)
resp.raise_for_status()
data = resp.json()
# Yorumları çıkar (yapı değişebilir, hata yakalamalı)
contents = data.get("contents", {})
# MWEB yanıtı yapısı farklılık gösterebilir
comment_section = _extract_comments(contents)
all_comments.extend(comment_section)
# Sonraki sayfa token'ını bul
continuation = _find_continuation(contents)
if not continuation:
break
# Rate-limit: sayfalar arası 2 saniye bekle
import time
time.sleep(2)
return all_comments
def _extract_comments(contents: dict) -> list:
"""Yanıt ağacından yorum metinlerini çeker.
YouTube sık sık yapıyı değiştirdiği için
bu fonksiyonu güncel tutmanız gerekir."""
comments = []
# Basitleştirilmiş çıkarma mantığı
try:
renderers = contents.get(
"singleColumnWatchNextResults", {}
).get("results", {}).get("results", {}).get("contents", [])
for item in renderers:
comment_renderer = (
item.get("itemSectionRenderer", {})
.get("contents", [{}])[0]
.get("commentThreadRenderer", {})
.get("comment", {})
.get("commentRenderer", {})
)
text = comment_renderer.get("contentText", {}).get("runs", [{}])
author = comment_renderer.get("authorText", {}).get("simpleText", "")
comment_text = "".join(t.get("text", "") for t in text)
if comment_text:
comments.append({"author": author, "text": comment_text})
except (KeyError, IndexError, TypeError):
pass
return comments
def _find_continuation(contents: dict):
"""Yanıt içinde continuation token'ı arar."""
try:
items = contents.get(
"singleColumnWatchNextResults", {}
).get("results", {}).get("results", {}).get("contents", [])
for item in items:
cont = item.get("continuationItemRenderer", {}).get(
"continuationEndpoint", {}
).get("continuationCommand", {}).get("token")
if cont:
return cont
except (KeyError, TypeError):
pass
return None
# Kullanım
if __name__ == "__main__":
comments = fetch_video_comments("dQw4w9WgXcQ", max_pages=3)
for c in comments[:10]:
print(f"{c['author']}: {c['text'][:80]}")
Örnek 2: Transkript Çekme (youtube-transcript-api + Proxy)
youtube-transcript-api kütüphanesi, YouTube'un transkript endpoint'lerini sarmalar. Proxy desteği için proxies parametresini kullanabilirsiniz:
from youtube_transcript_api import YouTubeTranscriptApi
import requests
PROXY_URL = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"
PROXIES = {"http": PROXY_URL, "https": PROXY_URL}
def get_transcript(video_id: str, language: str = "en"):
"""Bir videonun transkriptini çeker."""
try:
# youtube-transcript-api proxy desteği
ytt_api = YouTubeTranscriptApi(
proxy_config=PROXY_URL
)
transcript = ytt_api.fetch(video_id, languages=[language])
for entry in transcript:
print(f"[{entry['start']:.1f}s] {entry['text']}")
return transcript
except Exception as e:
print(f"Transkript hatası: {e}")
return None
if __name__ == "__main__":
get_transcript("dQw4w9WgXcQ", "en")
Örnek 3: Kanal Video Listesi (InnerTube /browse)
import requests
import json
import time
PROXY_URL = "http://user-country-DE:PASSWORD@gate.proxyhat.com:8080"
PROXIES = {"http": PROXY_URL, "https": PROXY_URL}
BROWSE_URL = "https://www.youtube.com/youtubei/v1/browse"
HEADERS = {
"Content-Type": "application/json",
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36"
),
"X-YouTube-Client-Name": "1",
"X-YouTube-Client-Version": "2.20240101",
}
def fetch_channel_videos(channel_id: str, max_pages: int = 10):
"""Bir kanalın videolarını /browse ile çeker."""
videos = []
continuation = None
payload = {
"browseId": channel_id,
"context": {
"client": {
"clientName": "WEB",
"clientVersion": "2.20240101",
},
"hl": "en",
"gl": "US",
},
}
for page in range(max_pages):
if continuation:
payload = {
"continuation": continuation,
"context": {
"client": {
"clientName": "WEB",
"clientVersion": "2.20240101",
},
},
}
resp = requests.post(
BROWSE_URL,
json=payload,
headers=HEADERS,
proxies=PROXIES,
timeout=30,
)
resp.raise_for_status()
data = resp.json()
# Video öğelerini çıkar
new_videos = _extract_videos(data)
videos.extend(new_videos)
continuation = _find_browse_continuation(data)
if not continuation:
break
time.sleep(3) # Sayfalar arası bekleme
return videos
def _extract_videos(data: dict) -> list:
"""Browse yanıtından video başlıklarını ve ID'leri çıkarır."""
videos = []
try:
tabs = data.get("contents", {}).get(
"twoColumnBrowseResultsRenderer", {}
).get("tabs", [])
for tab in tabs:
content = tab.get("tabRenderer", {}).get("content", {})
items = content.get(
"richGridRenderer", {}
).get("contents", [])
for item in items:
vid = item.get("richItemRenderer", {}).get(
"content", {}
).get("videoRenderer", {})
if vid:
videos.append({
"videoId": vid.get("videoId", ""),
"title": vid.get("title", {}).get(
"runs", [{}]
)[0].get("text", ""),
"views": vid.get("viewCountText", {}).get(
"simpleText", ""
),
})
except (KeyError, IndexError, TypeError):
pass
return videos
def _find_browse_continuation(data: dict):
"""Browse yanıtında continuation token arar."""
try:
tabs = data.get("contents", {}).get(
"twoColumnBrowseResultsRenderer", {}
).get("tabs", [])
for tab in tabs:
content = tab.get("tabRenderer", {}).get("content", {})
items = content.get(
"richGridRenderer", {}
).get("contents", [])
for item in items:
token = item.get(
"continuationItemRenderer", {}
).get("continuationEndpoint", {}).get(
"continuationCommand", {}
).get("token")
if token:
return token
except (KeyError, TypeError):
pass
return None
if __name__ == "__main__":
vids = fetch_channel_videos("UCxxxxxxxxxxxx", max_pages=3)
print(f"{len(vids)} video bulundu")
Örnek 4: Node.js ile Video Metadata Çekme
const https = require("https");
const { HttpsProxyAgent } = require("https-proxy-agent");
const PROXY = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080";
const agent = new HttpsProxyAgent(PROXY);
function fetchVideoMetadata(videoId) {
const payload = JSON.stringify({
videoId,
context: {
client: {
clientName: "WEB",
clientVersion: "2.20240101",
},
hl: "en",
gl: "US",
},
});
const options = {
hostname: "www.youtube.com",
path: "/youtubei/v1/player",
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(payload),
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
"AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
"X-YouTube-Client-Name": "1",
"X-YouTube-Client-Version": "2.20240101",
},
agent,
};
const req = https.request(options, (res) => {
let body = "";
res.on("data", (chunk) => (body += chunk));
res.on("end", () => {
const data = JSON.parse(body);
const vd = data.videoDetails || {};
console.log({
title: vd.title,
viewCount: vd.viewCount,
author: vd.author,
lengthSeconds: vd.lengthSeconds,
});
});
});
req.on("error", (e) => console.error(e));
req.write(payload);
req.end();
}
fetchVideoMetadata("dQw4w9WgXcQ");
Rate-Limit ve Fingerprint Riskleri
YouTube scraping'inde en büyük risk CAPTCHA ve IP bloklarıdır. İşte bunları minimize etmek için stratejiler:
İstek Hızı Kontrolü
- Aralıklı istekler: Her istek arasına en az 1-3 saniye ekleyin. Ani burst trafiği, Google'ın bot dedektörünü anında tetikler.
- Günlük hacim sınırları: Tek bir IP'den günde 500-1.000 istek makul bir üst sınırdır. Proxy havuzunuz yeterliyse bu sayıyı IP başına dağıtabilirsiniz.
- Rastgele gecikme: Sabit 2 saniye yerine
random.uniform(1.5, 4.0)gibi değişken gecikmeler kullanın; bu, trafik paterninizi daha insana benzer hale getirir.
Fingerprint Yönetimi
Google yalnızca IP'nize bakmaz. İsteğinizin browser fingerprint'ini de analiz eder:
- User-Agent tutarlılığı: Proxy rotasyonu yaparken User-Agent'ınızı da değiştirin. Farklı işletim sistemi ve tarayıcı kombinasyonları kullanın.
- Header sırası: HTTP header'larının gönderim sırası bile fingerprint oluşturur.
requestsgibi kütüphaneler sabit sıra kullanır; bu da bot olarak işaretlenme riskini artırır. - TLS parmak izi: Python'ın
requestskütüphanesi, JA3 fingerprint ile tanınabilir. Daha gelişmiş senaryolardacurl_cffiveyatls_clientgibi kütüphaneler tercih edin.
CAPTTCHA ile Başa Çıkma
CAPTTCHA alırsanız, o IP'yi geçici olarak atlayın ve bir sonraki IP ile devam edin. ProxyHat'ın geniş residential havuzu sayesinde engellenen IP'leri hızlıca değiştirebilirsiniz. CAPTCHA çözmeye çalışan servisler kullanmak, YouTube'un Hizmet Şartlarını daha da ciddi şekilde ihlal eder ve bu rehberde önerilmemektedir.
InnerTube API Derinlemesine: /youtubei/v1/next ve Continuation
/youtubei/v1/next endpoint'i, YouTube scraping'inin kalbidir. Bir video sayfasının "sonraki" sekmesine denk gelir ve şu verileri sunar:
- Yorum dizisi: İlk yüklemede 20 yorum; her continuation ile 20 daha.
- Öneri videoları: Sağ panel / mobilde alt panel önerileri.
- İlgili playlist bilgisi: Videonun dahil olduğu playlist'ler.
Continuation Token Akışı
Yorum çekiminin tipik akışı şöyledir:
/youtubei/v1/next'evideoIdile istek gönderin.- Yanıttan
commentSectionRendereriçindekicontinuationItemRenderer'ı bulun. - Token'ı çıkarın ve bir sonraki
/youtubei/v1/nextisteğinecontinuationparametresi olarak ekleyin. - Yanıt artık yorum içerir ve yeni bir continuation token sunar.
- Token kalmayana kadar tekrarlayın.
Pratik İpucu: InnerTube yanıt yapısı YouTube'un her güncellemesiyle değişebilir. JSON çıkarma fonksiyonlarınızı sık sık test edin ve güncelleyin.
json.dumps(data, indent=2)ile yanıtları kaydedip yapıyı incelemek, debug sürecinizi hızlandırır.
Etik Scraping ve Resmi API Kullanımı
YouTube scraping güçlü bir araçtır, ancak gücüyla sorumluluk gelir. İşte etik sınırlar:
Ne Yapmalısınız?
- Kamuya açık verilerle yetinin: Yorumlar, görüntülenme sayıları ve video başlıkları herkese açıktır. Özel veya yaş doğrulamalı içeriklere erişmeyin.
- Yaratıcı haklarına saygı: Transkriptleri ve video içeriklerini yeniden dağıtmayın. Bu içeriklerin telif hakkı yaratıcıya aittir.
- Veri minimizasyonu: Yalnızca ihtiyacınız olan veriyi çekin. Tüm YouTube'u indirmeye çalışmak hem etik değil hem de teknik olarak verimsiz.
- robots.txt'i dikkate alın: YouTube'un
robots.txtdosyası, belirli endpoint'lerin taranmasını yasaklar. Bu kısıtlamalara uyun.
Ne Zaman Resmi API Kullanmalısınız?
- Kota yeterli olduğunda: Günde birkaç yüz video veya birkaç bin yorum çekiyorsanız, API v3 yeterlidir ve scraping riskini gereksiz kılar.
- Uzun vadeli projelerde: InnerTube yapıları değişebilir ve bakım maliyeti yüksektir. API v3 kararlı bir sözleşme sunar.
- Ticari ürünlerde: Müşterilerinize sunulan bir SaaS ürünü için, resmi API kullanmak hukuki açıdan daha güvenlidir.
Scraping, API'nin yetmediği belirli boşlukları doldurmak için kullanılmalıdır: yorum analizi ölçeklendirme, erken trend tespiti, reklam izleme ve öneri haritalama. Bu senaryolarda scraping, resmi API'nin yanında tamamlayıcı bir araç olarak konumlandırılmalıdır.
Temel Çıkarımlar
- YouTube Data API v3 günlük 10.000 kota birimi ile sınırlıdır; arama işlemleri 100 birim tüketir ve ölçekli projeler için yetersiz kalır.
- InnerTube API, YouTube'un dahili endpoint'leridir ve giriş yapmadan video metadatası, yorumlar, transkriptler ve önerilere erişim sağlar.
- Residential proxy zorunludur: Google datacenter IP'lerini hızla işaretler ve bloklar. ProxyHat'ın residential havuzu bu sorunu çözer.
- IP rotasyonu ve rate-limit kontrolü, CAPTCHA ve blokları minimize eder. Per-request rotasyon yüksek hacimli işlemler için, sticky session tutarlı oturumlar için idealdir.
- Etik sınırlar net olmalıdır: Kamuya açık verilerle yetinin, transkriptleri dağıtmayın, yaratıcı haklarına saygı gösterin ve mümkün olduğunda resmi API'yi tercih edin.
- InnerTube yanıt yapıları sık değişir; JSON çıkarma fonksiyonlarınızı düzenli olarak test edin ve güncelleyin.
Sonraki Adım
YouTube veri çekme projeniz için güvenilir residential proxy'ye ihtiyacınız varsa, ProxyHat fiyatlandırma sayfasını inceleyerek size uygun planı bulabilirsiniz. 190+ ülkede IP havuzu, per-request ve sticky session desteği, ve HTTP/SOCKS5 erişimi ile ölçekli YouTube scraping projelerinizi güvenle yürütebilirsiniz.
Web scraping genel rehberimizi de incelemek isterseniz: Web Scraping Rehberi. SERP izleme ile ilgili daha fazla bilgi için: SERP Tracking Kullanım Senaryosu.






