ytdlp.online

Alle Lösungen

Auf dieser Seite

yt-dlp und Rumble: JSON-Fehler 403 mit Player-Fallback beheben

Veröffentlicht am

Fix-Plugin herunterladen rumble_player.py

Wenn yt-dlp beim Herunterladen eines Rumble-Videos Unable to download JSON metadata: HTTP Error 403: Forbidden meldet, kannst du das Kompatibilitätsplugin aus diesem Artikel laden. Gibt Rumbles JSON-Schnittstelle embedJS/u3 den Status 403 zurück, ruft das Plugin automatisch die offizielle eingebettete Player-Seite (/embed/) desselben Videos ab. Es liest die dort eingebetteten Mediendaten aus und setzt den Download fort.

Wenn du weder ein lokales Plugin einrichten noch Links manuell umwandeln möchtest, kannst du unseren Rumble-Video-Downloader verwenden. Diese Fehlerbehebung ist dort bereits integriert.

Zuerst prüfen, an welcher Stelle der Fehler 403 auftritt

Beim Download von Rumble kann ein Fehler 403 in drei verschiedenen Phasen auftreten. Dieses Plugin behebt gezielt den zweiten Fall:

Fehlermeldung Blockierte Anfrage Vorgehen
Unable to download webpage: HTTP Error 403 Die HTML-Seite des Videos wird blockiert (siehe Issue #15089) Über die offizielle oEmbed-Schnittstelle die /embed/-Adresse ermitteln und --impersonate firefox verwenden
Unable to download JSON metadata: HTTP Error 403 Die Metadatenschnittstelle embedJS/u3 wird blockiert (siehe Issue #17496) Hier hilft dieses Plugin: automatisch auf die eingebetteten Daten der /embed/-Seite zurückgreifen
Die Formate werden aufgelistet, aber beim Download von Fragmenten oder der MP4-Datei tritt ein Fehler 403 auf Das CDN lehnt die Anfrage nach den Mediendaten ab Proxy und Anfrageheader prüfen oder ein Format mit anderer Auflösung wählen

Schritte zur schnellen Fehlerbehebung

1. Die Plugindatei speichern

Erstelle in deinem Arbeitsverzeichnis die folgende Ordnerstruktur und speichere den vollständigen Plugincode am Ende des Artikels als rumble_player.py. Den Quellcode von yt-dlp musst du dafür nicht ändern:

plugins/
└── rumble/
    └── yt_dlp_plugins/
        └── extractor/
            └── rumble_player.py

2. Die offizielle /embed/-Adresse des Videos ermitteln

Die ID in der URL einer Rumble-Videoseite, etwa v6xxxx, ist nicht identisch mit der ID des eingebetteten Players, etwa vb0ofn. Die Player-Adresse lässt sich deshalb nicht einfach aus der Video-URL zusammensetzen. Wenn du nur den normalen Videolink hast, frage die tatsächliche /embed/-Adresse über Rumbles öffentliche oEmbed-Schnittstelle ab:

curl -fsSG --data-urlencode "url=https://rumble.com/your-video.html" "https://rumble.com/api/Media/oembed.json"

Suche im JSON-Feld html nach <iframe src="https://rumble.com/embed/xxxx/..." und übernimm daraus https://rumble.com/embed/xxxx/.

Wenn oEmbed den Status 403 zurückgibt, installiere curl_cffi und versuche es mit einem Firefox-Fingerprint erneut. Ersetze die Beispiel-URL unten durch die vollständige URL der Videoseite.

python -m pip install curl_cffi
python -c "import sys; from curl_cffi import requests; r = requests.get('https://rumble.com/api/Media/oembed.json', params=dict(url=sys.argv[1]), impersonate='firefox', timeout=15); r.raise_for_status(); print(r.text)" "https://rumble.com/your-video.html"

Schlägt auch dieser Versuch fehl, kannst du den Link mit dem Online-Downloader automatisch umwandeln lassen.

3. Die verfügbaren Formate auflisten und den Fallback prüfen

Führe den folgenden Befehl im Verzeichnis aus, das den Ordner plugins enthält. Ersetze die Beispieladresse durch die /embed/-Adresse deines Videos:

yt-dlp --ignore-config --plugin-dirs ./plugins --no-cache-dir -v -F "https://rumble.com/embed/vb0ofn/"

Die Kennung [RumbleEmbed+PlayerFallback] im Protokoll zeigt, dass das Plugin geladen wurde:

  • Gibt die JSON-Schnittstelle den Status 403 zurück, folgt die Meldung Downloading player webpage. Diese Meldung bestätigt nur, dass der alternative Abrufweg ausgelöst wurde. Erst die anschließende Ausgabe der Formatliste bestätigt, dass die Daten erfolgreich ausgewertet wurden.
  • Gibt die JSON-Schnittstelle in deiner Netzwerkumgebung den Status 200 zurück, bleibt es beim regulären Ablauf. Es wird keine zusätzliche Anfrage an die Player-Seite gestellt.

4. Das Video herunterladen und die Dekodierung prüfen

Wähle aus der Ausgabe von -F eine Format-ID, zum Beispiel mp4-360p, und starte den Download:

yt-dlp --ignore-config --plugin-dirs ./plugins --no-cache-dir -v --no-playlist -f mp4-360p -o "rumble-test.%(ext)s" "https://rumble.com/embed/vb0ofn/"

Beim Test mit ausgelöstem Fallback wurde folgendes vollständiges Terminalprotokoll aufgezeichnet:

[RumbleEmbed+PlayerFallback] vb0ofn: Downloading JSON metadata
[RumbleEmbed+PlayerFallback] vb0ofn: Downloading player webpage
[info] vb0ofn: Downloading 1 format(s): mp4-360p
[download] 100% of    7.85MiB in 00:01:20 at 99.48KiB/s

Mit ffprobe und ffmpeg kannst du anschließend prüfen, ob der MP4-Container und die Audio- und Videospuren vollständig und fehlerfrei sind:

ffprobe -v error -show_entries stream=codec_name,codec_type,width,height:format=duration,size -of json "rumble-test.mp4"
ffmpeg -nostdin -v error -xerror -i "rumble-test.mp4" -map 0:v:0 -map "0:a:0?" -f null -

Technischer Hintergrund: Warum die Player-Seite bei JSON-Fehler 403 weiterhilft

1. Eingebettete Daten derselben Quelle wiederverwenden

RumbleEmbedIE ruft die JSON-Metadaten normalerweise direkt über https://rumble.com/embedJS/u3/?request=video&ver=2&v=... ab. Wird diese Schnittstelle separat von Cloudflare oder den Schutzmechanismen der Website blockiert und antwortet mit HTTP 403, bricht die Extraktion ab.

Die offizielle Player-Seite https://rumble.com/embed/<video_id>/ enthält jedoch bereits ein Videokonfigurationsobjekt mit derselben Struktur direkt in ihrem Seitenskript. Dazu gehören ua mit den Stream-Adressen für die verschiedenen Auflösungen sowie Titel, Laufzeit und weitere Felder. Das Plugin liest dieses Objekt aus und gibt es an _download_json zurück. Der anschließende Code von yt-dlp zur Formatauswertung kann unverändert weiterarbeiten.

2. Das ungültige JSON-Feld loaded: h() entfernen

Das eingebettete Datenobjekt ist kein gültiges JSON-Literal: Am Ende enthält es den Funktionsaufruf loaded: h(), zum Beispiel:

u.f["vb0ofn"] = {"ua": {"mp4": {"360": {"url": "https://..."}}}, "title": "...", loaded: h()};

Ein JSON-Parser würde bei h() einen Syntaxfehler melden. Deshalb nutzt das Plugin in _search_json den Hook transform_source, um vor dem Parsen ausschließlich das abschließende , loaded: xxx() mit einem regulären Ausdruck zu entfernen. Dabei wird nur Text im Arbeitsspeicher verarbeitet; JavaScript aus der Webseite wird nicht ausgeführt:

  • Gezielte Auswahl: Es wird nur das Objekt ausgelesen, dessen Schlüssel genau der aktuellen video_id entspricht (\b[\w$]+\.f\[\s*["']{video_id}["']\s*\]\s*=). Anschließend wird geprüft, ob das Ergebnis ein Dictionary mit einem nicht leeren Medienfeld ua ist.
  • Begrenzter Eingriff: Der Fallback greift nur, wenn _download_json einen HTTPError mit Status 403 abfängt. Bei 401, 404, 429, 500 und anderen Fehlern oder bei einem fehlenden gültigen Objekt wird der ursprüngliche Fehler unverändert weitergegeben.
  • Einbindung in unseren Online-Dienst: Zusätzlich zum Plugin wandelt unser Dienst eingegebene Videoseiten-URLs automatisch über oEmbed in /embed/-Adressen um. Wenn kein --impersonate angegeben ist, verwendet er standardmäßig den Fingerprint firefox-135.

Vollständiger Plugincode

Speichere den folgenden Code als plugins/rumble/yt_dlp_plugins/extractor/rumble_player.py. Er wurde mit Python 3.12+ und yt-dlp 2026.10.10+ erfolgreich geprüft:

"""Reuse official player media data when Rumble's JSON endpoint is blocked."""

import re

from yt_dlp.extractor.rumble import RumbleEmbedIE as BaseRumbleEmbedIE
from yt_dlp.networking.exceptions import HTTPError
from yt_dlp.utils import ExtractorError


class RumbleEmbedIE(BaseRumbleEmbedIE, plugin_name='PlayerFallback'):
    def _real_extract(self, url):
        self._player_url = url
        return super()._real_extract(url)

    def _download_json(self, url_or_request, video_id, *args, **kwargs):
        try:
            return super()._download_json(url_or_request, video_id, *args, **kwargs)
        except ExtractorError as error:
            if not isinstance(error.cause, HTTPError) or error.cause.status != 403:
                raise
            webpage = self._download_webpage(self._player_url, video_id, note='Downloading player webpage')
            # Parse this video's object and strip the runtime call without executing page scripts.
            data = self._search_json(
                rf'''\b[\w$]+\.f\[\s*["']{re.escape(video_id)}["']\s*\]\s*=\s*''',
                webpage, 'player data', video_id,
                fatal=False,
                transform_source=lambda source: re.sub(r',\s*loaded\s*:\s*[\w$]+\(\s*\)\s*(?=})', '', source))
            if not isinstance(data, dict) or not data.get('ua'):
                raise error
            return data
yt-dlp Tools
Alle yt-dlp-Werkzeuge anzeigen
yt-dlp Hilfe & Doku