Skip to content

Instantly share code, notes, and snippets.

@pukkandan
Last active January 2, 2023 16:05
Show Gist options
  • Save pukkandan/24f13ff1ed385c5a390c1d7bd130d8f7 to your computer and use it in GitHub Desktop.
Save pukkandan/24f13ff1ed385c5a390c1d7bd130d8f7 to your computer and use it in GitHub Desktop.
yt-dlp plugin extractor to decrypt youtube nsig online
Moved to https://github.com/pukkandan/YT_NSigProxy
"""
SPDX-License-Identifier: MIT https://opensource.org/licenses/MIT
Copyright © 2022 [email protected]
yt-dlp plugin extractor to decrypt youtube nsig online
Needs yt-dlp 2022.09.17 or above
Usage: Import this file in ytdlp_plugins/extractor/__init__.py
See https://github.com/yt-dlp/yt-dlp#plugins for details
Solver Source:
https://github.com/pukkandan/yt-dlp-online-utils/blob/master/api/youtube/nparams/decrypt.js
Credits: @Lesmiscore for the implementation
Note: The solver has limited resources. Please do not abuse
"""
from yt_dlp.utils import ExtractorError, traverse_obj
from yt_dlp.extractor.youtube import YoutubeIE
SOLVER_URL = 'https://yt-dlp-online-utils.vercel.app/youtube/nparams/decrypt'
PREFER_SOLVER = False # Whether to prefer online solver over local solver
class Youtube_NsigProxyIE(YoutubeIE, plugin_name='NSIG'):
def __nsig_error(self, current, next, s, video_id, player_url, e):
self.report_warning(
f'{current} nsig extraction failed: Trying with {next}\n'
f' n = {s} ; player = {player_url}', video_id)
self.write_debug(e)
def _decrypt_nsig(self, s, video_id, player_url):
fallback = True
try:
if not player_url or not PREFER_SOLVER:
return super()._decrypt_nsig(s, video_id, player_url)
except Exception as e:
if not player_url:
raise
self.__nsig_error('Local', 'online solver', s, video_id, player_url, e)
fallback = False
try:
response_data = self._download_json(
SOLVER_URL, video_id, query={'player': player_url, 'n': s},
note='Requesting nsig decryption from online solver')
if response_data['status'] != 'ok':
raise ExtractorError(f'Failed at step "{response_data["step"]}":\n '
f'{traverse_obj(response_data, ("data", "message"))}')
self.write_debug(f'Decrypted nsig {s} => {response_data["data"]}')
return response_data['data']
except Exception as e:
if not fallback:
raise
self.__nsig_error('Online', 'local solver', s, video_id, player_url, e)
return super()._decrypt_nsig(s, video_id, player_url)
Copy link

ghost commented Sep 13, 2022

i can do this:

remove Youtube_AgeGateBypassIE import from ytdlp_plugins/extractor/__init__.py
and replace import in ytdlp_plugins/extractor/Youtube_NsigProxy.py to this:

from ytdlp_plugins.extractor.Youtube_AgeGateBypass import Youtube_AgeGateBypassIE as YoutubeIE

and then... it's working as expected

[debug] yt-dlp version 2022.09.01 [5d7c7d656] (source)
[debug] Lazy loading extractors is disabled
[debug] Plugins: ['SamplePluginIE', 'Youtube_NsigProxyIE', 'SamplePluginPP']
[debug] Git HEAD: 22df97f9c
...skipped...
[debug] [youtube:NSIG+AGB] Extracting URL: https://www.youtube.com/watch?v=Cr381pDsSsA

@pukkandan
Copy link
Author

hm.. The plugin system wasn't really designed with this kind of use-case in mind. I will have to see what can be changed in yt-dlp to make this easier

Copy link

ghost commented Sep 16, 2022

Everything good with latest commit, except two small things

  • small typo "Needs yt-dlp 2021.09.17 or above" => "Needs yt-dlp 2022.09.17 or above"
  • nsig always use online solver, even if PREFER_SOLVER = False

@pukkandan
Copy link
Author

@0xcc07c9 Thanks, fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment