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