Como Raspar Dados Públicos do YouTube com Proxies Residenciais em 2025

Guia completo para extração de dados do YouTube: quando a API v3 basta, como usar endpoints InnerTube, e por que proxies residenciais são essenciais para raspagem em escala.

Como Raspar Dados Públicos do YouTube com Proxies Residenciais em 2025

Se você trabalha com análise de mídia ou pesquisa na creator economy, já sentiu a dor: precisa de milhares de threads de comentários, contagens de views em tempo real ou metadados de vídeos antes que entrem em tendência — e a YouTube Data API v3 simplesmente não acompanha. As cotas são restritas, os custos por requisição são altos e muitos dados simplesmente não estão disponíveis. É aí que entra a extração de dados do YouTube via scraping com proxies residenciais.

Aviso legal e ético: Este guia cobre apenas acesso a dados publicamente disponíveis. Respeite os Termos de Serviço do YouTube, a CFAA (EUA), o GDPR (UE) e a CCPA (Califórnia). Não redistribua transcrições, conteúdo de vídeos ou dados protegidos por direitos autorais. Quando existir uma API oficial que atenda às suas necessidades, use-a.

YouTube Data API v3: Quando Basta e Quando Falha

A YouTube Data API v3 é bem documentada e estável, mas foi projetada para aplicativos que consomem dados moderados — não para raspagem em escala industrial.

Cotas e custos por operação

O Google atribui um custo em unidades de cota a cada endpoint:

OperaçãoCusto em unidadesRequisições com 10.000 unidades/dia
search.list100100
videos.list110.000
commentThreads.list110.000
channels.list110.000

A cota padrão gratuita é de 10.000 unidades por dia. Isso significa que uma única operação de busca consome 1% da sua cota diária. Para equipes de análise que precisam monitorar milhares de canais ou detectar tendências precoces, isso é insuficiente.

Onde a API deixa a desejar

  • Threads de comentários em escala: A API pagina com até 100 comentários por requisição, mas cada página custa unidades e a profundidade de respostas (replies) é limitada.
  • Detecção precoce de tendências: O endpoint de busca é caro e retorna resultados ordenados por relevância, não por recência com granularidade de minutos.
  • Monitoramento de anúncios: A API não expõe anúncios exibidos nos vídeos — dado crucial para inteligência competitiva.
  • Transcrições: Não há endpoint oficial para legendas/transcrições.
  • Dados em tempo real: Contagens de views ao vivo (live counters) não estão disponíveis via API.

Para esses cenários, o scraping complementa a API preenchendo lacunas que o Google deliberadamente deixou.

Dados Acessíveis Sem Login no YouTube

Mesmo sem autenticação, o YouTube serve uma quantidade impressionante de dados estruturados via seu frontend. Aqui está o que você pode acessar:

  • Metadados de vídeo: título, descrição, tags (parciais), duração, contagem de views, likes, data de publicação.
  • Páginas de canal: lista de vídeos, contagem de inscritos, descrição, links externos.
  • Threads de comentários: texto do comentário, autor, likes, data, respostas aninhadas.
  • Transcrições geradas automaticamente: disponíveis para a maioria dos vídeos via endpoint interno.
  • Player response: objeto JSON embutido na página com streamingData, videoDetails, microformat.

A chave para acessar esses dados de forma programática está nos endpoints InnerTube do YouTube.

A API Interna InnerTube: O Motor Por Trás do YouTube

O InnerTube é a API interna do YouTube que alimenta o site, o app mobile e smart TVs. Ela não é documentada oficialmente, mas é estável o suficiente para raspagem de dados públicos. Os endpoints mais úteis são:

/youtubei/v1/next

Retorna comentários, vídeos relacionados e sugestões para um vídeo. É o equivalente a rolar a página abaixo do player.

POST https://www.youtube.com/youtubei/v1/next
Content-Type: application/json

{
  "videoId": "dQw4w9WgXcQ",
  "context": {
    "client": {
      "clientName": "WEB",
      "clientVersion": "2.20250101"
    }
  }
}

Tokens de continuação (continuation tokens)

Os resultados vêm paginados com continuation tokens — strings opacas que você envia de volta para obter a próxima página. Para comentários:

{
  "context": {
    "client": {
      "clientName": "WEB",
      "clientVersion": "2.20250101"
    }
  },
  "continuation": "TOKEN_AQUI"
}

Cada chamada com um continuation token retorna a próxima página de comentários e um novo token. Isso permite iterar por threads completas.

Player response

Ao carregar qualquer página de vídeo, o YouTube embute um objeto JSON em window["ytInitialPlayerResponse"] no HTML. Esse objeto contém videoDetails, streamingData, captions (transcrições) e muito mais. Você pode extraí-lo com uma simples regex:

import re, json, requests

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

resp = requests.get(
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"},
    proxies=proxies,
)

match = re.search(r'var ytInitialPlayerResponse\s*=\s*(\{.*?\});', resp.text)
if match:
    player_data = json.loads(match.group(1))
    print(player_data["videoDetails"]["title"])
    print(f"Views: {player_data['videoDetails']['viewCount']}")

Por Que Proxies Residenciais São Essenciais

O Google mantém listas de ranges IP de datacenters e provedores de cloud. Requisições vindas desses ranges são flaggadas imediatamente com CAPTCHAs, blocos temporários ou respostas com dados reduzidos. Isso é especialmente agressivo no YouTube.

Datacenter vs. Residencial: Comparação

AspectoProxy de DatacenterProxy Residencial
Risco de CAPTCHAAlto (50%+ em volume)Baixo (<5%)
Rotação de IPDisponível, mas ranges são conhecidosIPs de ISPs reais, não flagados
Geo-targetingLimitado a localizações de DCPaís e cidade por ISP real
CustoMenorMaior, mas necessário para YouTube
Confiabilidade para YouTubeBaixa em escalaAlta

Para raspar o YouTube com proxies em qualquer volume significativo, proxies residenciais não são um luxo — são um requisito. O Google simplesmente não confia em tráfego de datacenter em massa.

Estratégia de rotação

Use rotação por requisição para comentários e metadados, e sessões sticky para paginação de threads (para não quebrar o contexto de continuação). Com o ProxyHat, você controla isso pelo nome de usuário:

  • Rotação por requisição: user-country-US:PASSWORD — cada requisição recebe um IP diferente.
  • Sessão sticky: user-country-US-session-abc123:PASSWORD — mantém o mesmo IP por até 30 minutos.

Implementação em Python: Raspagem Completa

Vamos construir um scraper que combina três fontes de dados: transcrições via youtube-transcript-api, metadados via InnerTube e comentários via paginação.

1. Instalação de dependências

pip install youtube-transcript-api requests

2. Configuração do proxy

PROXY_USER = "user-country-US"
PROXY_PASS = "SUA_SENHA_AQUI"
PROXY_HOST = "gate.proxyhat.com"
PROXY_PORT = 8080

def get_proxy_url(session_id=None):
    username = f"{PROXY_USER}-session-{session_id}" if session_id else PROXY_USER
    return f"http://{username}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}"

def get_proxies(session_id=None):
    url = get_proxy_url(session_id)
    return {"http": url, "https": url}

3. Extração de transcrições

from youtube_transcript_api import YouTubeTranscriptApi

# A youtube-transcript-api suporta proxies via parâmetro
proxies_dict = get_proxies(session_id="transcripts")

try:
    transcript = YouTubeTranscriptApi.get_transcript(
        ["dQw4w9WgXcQ"],
        languages=["pt", "en"],
        proxies=proxies_dict,
    )
    for entry in transcript:
        print(f"[{entry['start']:.1f}s] {entry['text']}")
except Exception as e:
    print(f"Transcrição indisponível: {e}")

4. Comentários via InnerTube com paginação

import json, time, requests

INNER_TUBE_URL = "https://www.youtube.com/youtubei/v1/next"
INNER_TUBE_KEY = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"

HEADERS = {
    "Content-Type": "application/json",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
    "Origin": "https://www.youtube.com",
    "Referer": "https://www.youtube.com/",
}

CONTEXT = {
    "client": {
        "clientName": "WEB",
        "clientVersion": "2.20250610",
        "hl": "pt",
        "gl": "BR",
    }
}

def fetch_comments(video_id, max_pages=10):
    """Raspa comentários de um vídeo via InnerTube /next endpoint."""
    all_comments = []
    
    # Primeira requisição — nova sessão sticky para manter contexto
    session_id = f"comments-{video_id}"
    proxies = get_proxies(session_id=session_id)
    
    payload = {
        "context": CONTEXT,
        "videoId": video_id,
    }
    
    resp = requests.post(
        f"{INNER_TUBE_URL}?key={INNER_TUBE_KEY}",
        json=payload,
        headers=HEADERS,
        proxies=proxies,
        timeout=30,
    )
    data = resp.json()
    
    # Extrair continuation token para comentários
    continuation_token = extract_comment_continuation(data)
    
    page = 0
    while continuation_token and page < max_pages:
        time.sleep(1.5)  # Rate limiting respeitoso
        
        payload = {
            "context": CONTEXT,
            "continuation": continuation_token,
        }
        
        resp = requests.post(
            f"{INNER_TUBE_URL}?key={INNER_TUBE_KEY}",
            json=payload,
            headers=HEADERS,
            proxies=proxies,
            timeout=30,
        )
        data = resp.json()
        
        comments = parse_comments_from_response(data)
        all_comments.extend(comments)
        
        continuation_token = extract_comment_continuation(data)
        page += 1
    
    return all_comments

def extract_comment_continuation(data):
    """Extrai o token de continuação de comentários da resposta."""
    try:
        contents = data.get("onResponseReceivedEndpoints", [])
        for endpoint in contents:
            reload = endpoint.get("reloadContinuationItemsCommand", {})
            if reload:
                for item in reload.get("continuationItems", []):
                    token = item.get("continuationItemRenderer", {}).get("continuationEndpoint", {}).get("continuationCommand", {}).get("token")
                    if token:
                        return token
            append = endpoint.get("appendContinuationItemsAction", {})
            if append:
                for item in append.get("continuationItems", []):
                    token = item.get("continuationItemRenderer", {}).get("continuationEndpoint", {}).get("continuationCommand", {}).get("token")
                    if token:
                        return token
    except (KeyError, TypeError):
        pass
    return None

def parse_comments_from_response(data):
    """Extrai texto e metadados dos comentários."""
    comments = []
    try:
        contents = data.get("onResponseReceivedEndpoints", [])
        for endpoint in contents:
            items = endpoint.get("appendContinuationItemsAction", {}).get("continuationItems", [])
            for item in items:
                renderer = item.get("commentThreadRenderer", {}).get("comment", {}).get("commentRenderer", {})
                if not renderer:
                    renderer = item.get("commentRenderer", {})
                if renderer:
                    text_runs = renderer.get("contentText", {}).get("runs", [])
                    text = " ".join(run.get("text", "") for run in text_runs)
                    author = renderer.get("authorText", {}).get("simpleText", "")
                    likes = renderer.get("voteCount", {}).get("simpleText", "0")
                    comments.append({
                        "author": author,
                        "text": text,
                        "likes": likes,
                    })
    except (KeyError, TypeError):
        pass
    return comments

# Uso
comments = fetch_comments("dQw4w9WgXcQ", max_pages=5)
print(f"Extraídos {len(comments)} comentários")
for c in comments[:3]:
    print(f"  {c['author']}: {c['text'][:80]}...")

5. Metadados de vídeo em massa com rotação

def fetch_video_metadata_batch(video_ids):
    """Busca metadados de múltiplos vídeos com rotação de IP por requisição."""
    results = []
    
    for vid in video_ids:
        # Rotação por requisição — sem session_id
        proxies = get_proxies()
        
        try:
            resp = requests.get(
                f"https://www.youtube.com/watch?v={vid}",
                headers={
                    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
                    "Accept-Language": "pt-BR,pt;q=0.9",
                },
                proxies=proxies,
                timeout=20,
            )
            
            match = re.search(
                r'var ytInitialPlayerResponse\s*=\s*(\{.*?\});',
                resp.text,
            )
            if match:
                data = json.loads(match.group(1))
                details = data.get("videoDetails", {})
                results.append({
                    "id": vid,
                    "title": details.get("title"),
                    "viewCount": details.get("viewCount"),
                    "lengthSeconds": details.get("lengthSeconds"),
                    "channel": details.get("author"),
                })
            
            time.sleep(2)  # Pausa entre requisições
            
        except Exception as e:
            print(f"Erro em {vid}: {e}")
    
    return results

video_ids = ["dQw4w9WgXcQ", "9bZkp7q19f0", "kJQP7kiw5Fk"]
metadata = fetch_video_metadata_batch(video_ids)
for m in metadata:
    print(f"{m['title']}: {m['viewCount']} views")

Implementação em Node.js

Para equipes que preferem JavaScript, aqui está um exemplo equivalente usando a biblioteca undici:

import { fetch } from 'undici';

const PROXY_USER = 'user-country-US';
const PROXY_PASS = 'SUA_SENHA_AQUI';
const PROXY_URL = `http://${PROXY_USER}:${PROXY_PASS}@gate.proxyhat.com:8080`;

async function fetchVideoMetadata(videoId) {
  const resp = await fetch(`https://www.youtube.com/watch?v=${videoId}`, {
    headers: {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
      'Accept-Language': 'pt-BR,pt;q=0.9',
    },
    dispatcher: new HttpAgent({ proxy: PROXY_URL }), // use undici ProxyAgent
  });
  
  const html = await resp.text();
  const match = html.match(/var ytInitialPlayerResponse\s*=\s*(\{.*?\});/);
  
  if (match) {
    const data = JSON.parse(match[1]);
    console.log({
      title: data.videoDetails.title,
      views: data.videoDetails.viewCount,
      channel: data.videoDetails.author,
    });
  }
}

fetchVideoMetadata('dQw4w9WgXcQ');

Riscos de Fingerprint e Mitigações

O Google não confia apenas no IP — ele também analisa o fingerprint do navegador. Aqui estão os principais vetores e como mitigá-los:

  • User-Agent consistente: Use o mesmo UA em headers HTTP e TLS fingerprint. Bibliotecas como curl_cffi ou tls-client emulam fingerprints de Chrome/Firefox.
  • Headers de ordem: O servidor pode verificar a ordem dos headers. Use sessões do requests para manter consistência.
  • Accept-Language: Alinhe com o geo-targeting do proxy. Se o IP é do Brasil, use pt-BR.
  • Rate limiting por IP: Mesmo com proxies residenciais, limite a 1-2 requisições por segundo por IP. Use rotação para distribuir a carga.
  • Cookies e estado: Não reutilize cookies entre IPs diferentes — isso associa sessões e pode triggerar blocos.

Padrões de Rate Limiting para Escala

Para operações de larga escala, o padrão ideal é:

  1. Pool de IPs residenciais com rotação automática (ProxyHat fornece isso nativamente).
  2. Fila de tarefas com backoff exponencial — se um IP recebe CAPTCHA, pause e tente com novo IP.
  3. Delay aleatório entre requisições (1.5–4 segundos) para imitar comportamento humano.
  4. Limite por vídeo — não tente raspar 100 páginas de comentários de um único vídeo em uma sessão.
  5. Monitoramento de sucesso — registre a taxa de sucesso por IP e descarte IPs que consistentemente retornam blocos.

Quando Usar a API Oficial Em Vez de Scraping

Scraping não é sempre a melhor solução. Use a YouTube Data API v3 quando:

  • Você precisa de menos de 10.000 requisições por dia e a cota gratuita basta.
  • Os dados que você precisa estão disponíveis via API (vídeos.list, canais.list).
  • Você precisa de estabilidade a longo prazo — a API é versionada e backward-compatible.
  • Seu caso de uso é comercial e precisa de conformidade com os ToS do YouTube.

Use scraping quando:

  • A API não expõe os dados necessários (transcrições, anúncios, comentários profundos).
  • A cota é insuficiente para o volume necessário.
  • Você precisa de dados em tempo real (contadores ao vivo, detecção de tendências).
  • O custo de expandir a cota da API é proibitivo.

Muitas equipes usam uma abordagem híbrida: API para dados estruturados e scraping para complementar lacunas. Isso reduz o risco e maximiza a cobertura.

Considerações Éticas e Legais

A extração de dados do YouTube levanta questões éticas importantes:

  • Propriedade do criador: Transcrições, thumbnails e conteúdo de vídeos pertencem aos criadores. Não redistribua esses dados sem permissão.
  • Dados pessoais: Comentários contêm dados pessoais (nomes, opiniões). O GDPR exige base legal para processamento. Para pesquisa acadêmica, anonimize os dados.
  • robots.txt: O YouTube bloqueia muitos paths em robots.txt. Respeite essas diretivas — especialmente para paths que exigem autenticação.
  • Termos de Serviço: O scraping viola os ToS do YouTube. Entenda os riscos legais da sua jurisdição antes de prosseguir.
  • Impacto no serviço: Raspagem agressiva degrada a experiência de outros usuários. Use rate limiting responsável.

Regra prática: se os dados são para análise interna e não serão redistribuídos, o risco ético é menor. Se você planeja republicar transcrições ou comentários, busque permissão explícita ou use apenas dados agregados e anonimizados.

Pontos-Chave

  • A YouTube Data API v3 é suficiente para volumes baixos, mas suas cotas tornam-se um gargalo para análise em escala.
  • Os endpoints InnerTube (/youtubei/v1/next, player response) dão acesso a dados públicos que a API não expõe: transcrições, comentários profundos, contadores em tempo real.
  • Proxies residenciais são obrigatórios para raspagem de YouTube em escala — o Google flagga ranges de datacenter imediatamente.
  • Use rotação por requisição para metadados e sessões sticky para paginação de comentários.
  • Sempre respeite rate limits, anonimize dados pessoais e não redistribua conteúdo protegido por direitos autorais.
  • Considere uma abordagem híbrida (API + scraping) para equilibrar cobertura, custo e conformidade.

Pronto para começar a raspar dados do YouTube com proxies residenciais confiáveis? Confira os planos do ProxyHat e acesse IPs residenciais em mais de 190 localizações. Para mais guias de extração de dados, veja nosso artigo sobre melhores práticas de web scraping e nosso caso de uso de rastreamento SERP.

Pronto para começar?

Acesse mais de 50M de IPs residenciais em mais de 148 países com filtragem por IA.

Ver preçosProxies residenciais
← Voltar ao Blog