ytdlp.online
Главная Tampermonkey

Все решения

На этой странице

yt-dlp и Rumble: исправление ошибки JSON 403 через данные плеера

Дата публикации

Скачать плагин с исправлением rumble_player.py

Если при скачивании видео с Rumble yt-dlp сообщает Unable to download JSON metadata: HTTP Error 403: Forbidden, загрузите плагин совместимости из этой статьи. Когда JSON API embedJS/u3 возвращает статус 403, плагин автоматически запрашивает страницу официального встроенного плеера (/embed/) для того же видео. Затем он извлекает встроенные медиаданные и продолжает скачивание.

Если вы не хотите настраивать локальный плагин и вручную преобразовывать ссылки, воспользуйтесь нашим загрузчиком видео Rumble. Это исправление уже встроено в него.

Сначала определите, на каком этапе возникает ошибка 403

При скачивании с Rumble ошибка 403 может возникнуть на трёх разных этапах. Этот плагин предназначен именно для второго случая:

Сообщение об ошибке Что блокируется Что делать
Unable to download webpage: HTTP Error 403 HTML страницы просмотра видео (см. issue #15089) Получить адрес /embed/ через официальный API oEmbed и использовать --impersonate firefox
Unable to download JSON metadata: HTTP Error 403 API метаданных embedJS/u3 (см. issue #17496) Использовать этот плагин: он автоматически обращается к данным, встроенным в страницу /embed/
Список форматов выводится, но при скачивании фрагментов или MP4 возникает ошибка 403 CDN отклоняет запрос медиапотока Проверить прокси и заголовки запроса или выбрать формат с другим разрешением

Быстрое исправление

1. Сохраните файл плагина

Создайте в рабочем каталоге следующую структуру папок и сохраните полный код плагина из конца статьи в файл rumble_player.py. Менять исходный код yt-dlp не требуется:

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

2. Получите официальный адрес /embed/ для видео

Идентификатор в URL страницы просмотра Rumble, например v6xxxx, не совпадает с идентификатором встроенного плеера, например vb0ofn. Поэтому нельзя просто составить адрес плеера из обычной ссылки. Если у вас есть только ссылка на страницу просмотра, запросите настоящий адрес /embed/ через открытый API oEmbed Rumble:

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

Найдите в поле html JSON-ответа фрагмент <iframe src="https://rumble.com/embed/xxxx/..." и возьмите из него адрес https://rumble.com/embed/xxxx/.

Если oEmbed возвращает ошибку 403, установите curl_cffi и повторите запрос с отпечатком Firefox. Замените пример URL ниже полным адресом страницы видео.

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"

Если повторный запрос не сработает, воспользуйтесь онлайн-загрузчиком, чтобы автоматически преобразовать ссылку.

3. Выведите доступные форматы и проверьте резервный путь

Выполните команду из каталога, содержащего папку plugins. Замените адрес в примере на /embed/-адрес нужного видео:

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

Метка [RumbleEmbed+PlayerFallback] в журнале означает, что плагин загружен:

  • Если JSON API возвращает 403, следом появляется сообщение Downloading player webpage. Оно означает лишь, что запущен резервный путь. Успешный разбор данных подтверждается только последующим выводом списка форматов.
  • Если JSON API в вашей сети сразу возвращает 200, используется обычный путь обработки. Дополнительный запрос страницы плеера не отправляется.

4. Скачайте видео и проверьте декодирование

Выберите идентификатор формата из вывода -F, например mp4-360p, и запустите скачивание:

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/"

Полный журнал терминала, записанный при проверке со сработавшим резервным путём:

[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

Чтобы проверить целостность скачанного MP4-контейнера и его аудио- и видеопотоков, используйте ffprobe и ffmpeg:

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 -

Как это работает: почему данные плеера помогают при ошибке JSON 403

1. Повторное использование встроенных данных того же источника

По умолчанию RumbleEmbedIE запрашивает JSON-метаданные напрямую по адресу https://rumble.com/embedJS/u3/?request=video&ver=2&v=.... Если Cloudflare или защитные механизмы сайта отдельно блокируют этот API и возвращают HTTP 403, извлечение прерывается.

Однако страница официального плеера https://rumble.com/embed/<video_id>/ уже содержит в своём скрипте объект конфигурации видео с точно такой же структурой. В нём есть ua с адресами потоков для разных разрешений, название, длительность и другие поля. Достаточно извлечь этот объект и вернуть его в _download_json, чтобы последующий код yt-dlp для разбора форматов продолжил работу без изменений.

2. Удаление нестандартного JSON-поля loaded: h()

Встроенный объект не является корректным JSON-литералом: в его конце находится вызов функции loaded: h(), например:

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

JSON-парсер выдаст синтаксическую ошибку на h(). Поэтому плагин использует обработчик transform_source в _search_json: перед разбором регулярное выражение удаляет только завершающий фрагмент , loaded: xxx(). Вся обработка выполняется над текстом в памяти; JavaScript страницы не запускается:

  • Точное совпадение: извлекается только объект, ключ которого строго равен текущему video_id (\b[\w$]+\.f\[\s*["']{video_id}["']\s*\]\s*=). Затем проверяется, что результат является словарём и содержит непустое поле медиапотоков ua.
  • Ограниченная область действия: резервный путь запускается только тогда, когда _download_json перехватывает HTTPError со статусом 403. При ошибках 401, 404, 429, 500 и других, а также при отсутствии корректного объекта на странице исходное исключение передаётся дальше без изменений.
  • Интеграция в наш онлайн-сервис: помимо загрузки плагина, сервис автоматически преобразует введённые ссылки на страницы просмотра в адреса /embed/ через oEmbed. Если --impersonate не указан, по умолчанию используется отпечаток firefox-135.

Полный код плагина

Сохраните этот код в plugins/rumble/yt_dlp_plugins/extractor/rumble_player.py. Он успешно проверен с Python 3.12+ и yt-dlp 2026.10.10+:

"""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
Посмотреть все инструменты yt-dlp
Справка и документация yt-dlp