Python · YouTube

Monitore estatísticas de vídeos do YouTube com Python

O YouTube mostra a contagem atual de visualizações de um vídeo, mas não como ela chegou lá. Se você quer saber a velocidade com que um vídeo cresce – o seu, o de um concorrente ou o de uma campanha que você pagou –, precisa anotar os números regularmente. Este guia monta um pequeno script que faz isso por você.

Uma vez por dia, ele pede à everydata.io as visualizações, curtidas e comentários atuais de cada vídeo da sua lista, adiciona uma linha a um arquivo CSV e mostra quantas visualizações cada vídeo ganhou desde a última execução. Opcionalmente, ele também pega os uploads mais recentes de um canal, para que vídeos novos sejam acompanhados desde o primeiro dia.

Atualizado em · por everydata.io

O que você terá no final

  • Um arquivo CSV com uma linha por vídeo e por dia: visualizações, curtidas, comentários.
  • O crescimento de visualizações desde a verificação anterior, exibido a cada execução.
  • Acompanhamento automático dos novos uploads de um canal.

O que você precisa

  • Python 3.10 ou mais recente e pip install requests.
  • Uma chave de API gratuita da everydata.io – crie uma aqui – na variável de ambiente EVERYDATA_API_KEY.
  • Os vídeos que você quer acompanhar: o ID depois de v= no link, ou o link completo.

01Veja o que a API retorna para um vídeo

O endpoint de detalhes do vídeo recebe um ID ou link de vídeo em id e retorna os números públicos da página do vídeo. Exemplo documentado, resumido:

Resposta de exemplo · GET /ytb/youtube-video-details
{
  "responseStatus": "PAGE_FOUND",
  "responseMessage": "Page successfully found!",
  "videoId": "kJQP7kiw5Fk",
  "title": "Luis Fonsi - Despacito ft. Daddy Yankee",
  "channelName": "LuisFonsiVEVO",
  "viewCount": 9125159593,
  "likeCount": 56673581,
  "likeCountText": "56M",
  "commentCount": 4300000,
  "publishedAt": "2017-01-12T21:00:02-08:00",
  "duration": 282
}

viewCount, likeCount e commentCount são números simples, prontos para armazenar e comparar. likeCountText é o rótulo arredondado que o YouTube mostra na página.

02Registre os números a cada execução

O script lê do arquivo CSV a última contagem de visualizações de cada vídeo, busca os números atuais, adiciona uma nova linha e mostra a diferença.

monitor.py
"""Record views, likes and comments of YouTube videos and print the growth since the last check."""
import csv
import os
import re
import time
from datetime import datetime, timezone
from pathlib import Path

import requests

API = "https://api.everydata.io"
KEY = os.environ["EVERYDATA_API_KEY"]
CSV_FILE = Path("video_stats.csv")
VIDEOS = ["kJQP7kiw5Fk"]  # video IDs or full YouTube links


def api_get(path: str, params: dict) -> dict:
    """GET an everydata.io endpoint. Waits when rate limited (429) and retries a failed page load (5xx) once."""
    retried = False
    for _ in range(4):
        resp = requests.get(f"{API}{path}", params=params, headers={"x-api-key": KEY}, timeout=60)
        if resp.status_code == 429:
            # Too many requests at once. The answer says how long to wait: "... Try again in 12 seconds."
            wait = re.search(r"in (\d+) seconds", resp.text)
            time.sleep(int(wait.group(1)) + 1 if wait else 60)
            continue
        if resp.status_code >= 500 and not retried:
            retried = True  # 5xx answers are not counted against your quota
            time.sleep(10)
            continue
        resp.raise_for_status()  # 4xx (wrong key, quota used up, bad parameter) or a second 5xx
        return resp.json()
    raise RuntimeError("still rate limited after several waits – try again later")


def video_details(video: str) -> dict:
    return api_get("/ytb/youtube-video-details", {"id": video})


def last_views() -> dict[str, int]:
    """Most recent view count per video from earlier runs."""
    if not CSV_FILE.exists():
        return {}
    with CSV_FILE.open(newline="") as f:
        return {r["video_id"]: int(r["views"]) for r in csv.DictReader(f) if r["views"]}


def main() -> None:
    before = last_views()
    now = datetime.now(timezone.utc).isoformat(timespec="seconds")
    new_file = not CSV_FILE.exists()

    with CSV_FILE.open("a", newline="") as f:
        writer = csv.writer(f)
        if new_file:
            writer.writerow(["checked_at", "video_id", "title", "views", "likes", "comments"])
        for video in VIDEOS:
            try:
                v = video_details(video)
            except (requests.RequestException, RuntimeError) as exc:
                print(f"{video}: could not check this time ({exc}) – the next run tries again")
                continue  # one failed video does not stop the others
            video_id = v.get("videoId") or video
            views = v.get("viewCount")
            writer.writerow([now, video_id, v.get("title"), views or "",
                             v.get("likeCount") or "", v.get("commentCount") or ""])
            if views is not None and video_id in before:
                print(f"{v.get('title')}: +{views - before[video_id]:,} views since the last check")


if __name__ == "__main__":
    main()

Execute com python3 monitor.py. A partir da segunda execução, você vê linhas como “+12,345 views since the last check”. api_get espera e continua quando você envia requisições demais de uma vez (429) e tenta mais uma vez um carregamento de página com falha (5xx); um vídeo que continuar falhando é informado e tentado de novo na próxima execução.

03Pegue os novos vídeos de um canal

Em vez de adicionar cada vídeo novo à mão, peça os uploads mais recentes de um canal e inclua-os na lista. O endpoint de vídeos do canal aceita um ID ou um link de canal.

monitor.py (adicione abaixo de video_details)
def latest_uploads(channel: str) -> list[str]:
    """IDs of the newest regular videos of a channel (channel ID or URL such as https://www.youtube.com/@WWE)."""
    data = api_get("/ytb/youtube-channel-videos", {"id": channel, "filter": "videos_latest"})
    return [item["videoId"] for item in data.get("items", []) if item.get("type") == "video"]


# In main(): watch the five newest uploads of a channel as well as your fixed list
# for video in VIDEOS + latest_uploads("https://www.youtube.com/@WWE")[:5]:
Resposta de exemplo · GET /ytb/youtube-channel-videos
{
  "responseStatus": "PAGE_FOUND",
  "responseMessage": "Page successfully found!",
  "channelId": "UCJ5v_MCY6GNUBTO8-D3XoAg",
  "filter": "videos_latest",
  "items": [
    {
      "type": "video",
      "videoId": "b7kl_pcHa0A",
      "title": "Blake Monroe vows to get payback against Giulia: SmackDown exclusive, Sept. 18, 2026",
      "viewCount": 6800,
      "publishedTimeText": "47 minutes ago"
    }
  ]
}

04Execute uma vez por dia

Agende o script com o cron (Mac, Linux), o Agendador de Tarefas do Windows ou um job agendado de CI:

crontab
0 6 * * * cd /home/you/yt-monitor && EVERYDATA_API_KEY=ds_your_key /usr/bin/python3 monitor.py >> monitor.log 2>&1

Cada consulta de vídeo e cada consulta de canal é uma requisição. Por exemplo, três vídeos verificados uma vez por dia dão cerca de 90 requisições por mês, dentro do plano gratuito de 100. Para números diários de muitos vídeos, veja os preços.

Abra video_stats.csv em uma planilha e faça um gráfico das visualizações por checked_at para ver a curva de crescimento.

Endpoints usados neste guia

GET/ytb/youtube-video-details

Video Details · API YouTube

GET/ytb/youtube-channel-videos

Channel Videos · API YouTube

Todos os parâmetros na referência da API

Teste com seus próprios dados

O plano gratuito inclui 100 requisições por mês, válidas em todas as plataformas – o suficiente para seguir este guia do início ao fim.