Python · YouTube

YouTube-Videostatistiken mit Python überwachen

YouTube zeigt die aktuelle Aufrufzahl eines Videos, aber nicht, wie sie zustande kam. Wenn Sie wissen möchten, wie schnell ein Video wächst – Ihr eigenes, das eines Wettbewerbers oder eine bezahlte Kampagne –, müssen Sie die Zahlen regelmäßig festhalten. Diese Anleitung baut ein kleines Skript, das das für Sie erledigt.

Einmal täglich fragt es bei everydata.io die aktuellen Aufrufe, Likes und Kommentare jedes Videos auf Ihrer Liste ab, hängt eine Zeile an eine CSV-Datei an und gibt aus, wie viele Aufrufe jedes Video seit dem letzten Lauf dazugewonnen hat. Optional übernimmt es auch die neuesten Uploads eines Kanals, sodass neue Videos ab ihrem ersten Tag erfasst werden.

Aktualisiert am · von everydata.io

Was Sie am Ende haben

  • Eine CSV-Datei mit einer Zeile pro Video und Tag: Aufrufe, Likes, Kommentare.
  • Der Zuwachs an Aufrufen seit der letzten Prüfung, bei jedem Lauf ausgegeben.
  • Automatisches Tracking der neuen Uploads eines Kanals.

Was Sie brauchen

  • Python 3.10 oder neuer und pip install requests.
  • Ein kostenloser everydata.io-API-Schlüssel – hier anlegen – in der Umgebungsvariablen EVERYDATA_API_KEY.
  • Die Videos, die Sie beobachten möchten: die ID nach v= im Link oder den vollständigen Link.

01Ansehen, was die API für ein Video liefert

Der Videodetails-Endpoint nimmt in id eine Video-ID oder einen Link entgegen und liefert die öffentlichen Zahlen der Videoseite. Gekürztes dokumentiertes Beispiel:

Beispielantwort · 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 und commentCount sind einfache Zahlen, bereit zum Speichern und Vergleichen. likeCountText ist das gerundete Label, das YouTube auf der Seite zeigt.

02Die Zahlen bei jedem Lauf festhalten

Das Skript liest die letzte Aufrufzahl jedes Videos aus der CSV-Datei, ruft die aktuellen Zahlen ab, hängt eine neue Zeile an und gibt die Differenz aus.

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()

Starten Sie es mit python3 monitor.py. Ab dem zweiten Lauf sehen Sie Zeilen wie „+12,345 views since the last check“. api_get wartet und macht weiter, wenn Sie zu viele Anfragen auf einmal senden (429), und versucht einen fehlgeschlagenen Seitenabruf (5xx) noch einmal; ein Video, das weiterhin fehlschlägt, wird gemeldet und beim nächsten Lauf erneut abgefragt.

03Neue Videos eines Kanals übernehmen

Statt jedes neue Video von Hand hinzuzufügen, fragen Sie die neuesten Uploads eines Kanals ab und nehmen sie in die Liste auf. Der Channel-Videos-Endpoint akzeptiert eine Kanal-ID oder einen Kanal-Link.

monitor.py (unter video_details einfügen)
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]:
Beispielantwort · 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"
    }
  ]
}

04Einmal täglich ausführen

Planen Sie das Skript mit cron (Mac, Linux), der Windows-Aufgabenplanung oder einem zeitgesteuerten CI-Job ein:

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

Jede Video- und jede Kanalabfrage ist eine Anfrage. Drei Videos, die einmal täglich geprüft werden, ergeben zum Beispiel rund 90 Anfragen im Monat – im Rahmen des kostenlosen Tarifs mit 100. Für tägliche Zahlen zu vielen Videos siehe Preise.

Öffnen Sie video_stats.csv in einer Tabellenkalkulation und stellen Sie die Aufrufe über checked_at dar, um die Wachstumskurve zu sehen.

In dieser Anleitung verwendete Endpoints

GET/ytb/youtube-video-details

Video Details · YouTube API

GET/ytb/youtube-channel-videos

Channel Videos · YouTube API

Alle Parameter in der API-Referenz

Probieren Sie es mit Ihren eigenen Daten

Der kostenlose Tarif enthält 100 Anfragen pro Monat, nutzbar auf jeder Plattform – genug, um diese Anleitung vollständig durchzuspielen.