-
-
Save geuis/8b1b2ea57d7f9a9ae22f80d4fbf5b97f to your computer and use it in GitHub Desktop.
// Run from the dev tools console of any Youtube video | |
// Accurate as of July 2, 2020. | |
// | |
// Copy and paste this into the dev console in a browser with the desired video loaded. | |
// | |
// NOTE: Some Youtube videos do not directly expose the video url in the response. | |
// This script doesn't currently attempt to handle those. It will work for most other general video types though. | |
(async () => { | |
const html = await fetch(window.location.href).then((resp) => resp.text()).then((text) => text); | |
const startStr = 'ytplayer.config = {'; | |
const start = html.indexOf(startStr) + startStr.length - 1; | |
const end = html.indexOf('};', start) + 1; | |
const playerObj = JSON.parse(html.slice(start, end)); | |
playerObj.args.player_response = JSON.parse(playerObj.args.player_response); | |
const videoUrls = playerObj.args.player_response.streamingData.adaptiveFormats.reduce((acc, item) => { | |
if (!acc[item.quality]) { | |
acc[item.quality] = {}; | |
} | |
const mimeType = item.mimeType.split(';')[0]; | |
acc[item.quality][mimeType] = item; | |
return acc; | |
}, {}); | |
console.log('!!', videoUrls); | |
})(); |
this technique only provides you with separate video and audio files
this script only works when the user loads a video url directly, instead of using YT internal navigation. in other words, you have to refresh the page on every video you wish to download in order to gain access to adaptive_fmts
I can't find adaptive_fmts
but url_encoded_fmt_stream_map
under args
object and everything is working as pointed.
ytplayer.config.args.url_encoded_fmt_stream_map
Doest work anymore in 2018
ytplayer.config.args.url_encoded_fmt_stream_map doesnt work at mobile version of youtube.
Does someone know how to get direct url on mobile version of youtube ?
Uncaught TypeError: Cannot read property 'split' of undefined
at youtubedl.js:15
@ViralShastri review the updated script.
in what language is it written in? I need to rewrite it to swift
@nysander its javascript.
does not work on for example https://www.youtube.com/watch?v=IcrbM1l_BoI
VM780:13 Uncaught (in promise) TypeError: Cannot read property 'split' of undefined
at :13:6
Where do I put this code?
@yair-man its in the very first line
Uncaught TypeError: Cannot read property 'split' of undefined
at :2:4
got this when i tired it out in console
Uncaught (in promise) TypeError: Cannot read property 'split' of undefined
It shows this error everytime I run it.
I get the url of the page when by using window.location.href
but I need the url which contains other properties such as screen-resolution, frame-rate, bit-rate , etc.
I also tried using ifram api by using src="https://www.youtube.com/get_video_info?video_id={videoId}"
but the file which it returns gives this error status=fail&errorcode=2&reason=Invalid+parameters.
.
Please help if you can.
@Joshuajrodrigues @jarvis1234d script is now updated. Try it out.
It works with the updated july 2nd script, thank you @geuis
however the url from every object only contains video stream. Is there a way to get the url for a full video+audio stream?
After running the script what's the field that hold the url? I suppose that is the one named signatureCypher ? It starts with "s=yy.."
so how to extract the url?
For Download video with audio
(async () => {
html = await fetch(window.location.href).then(resp => resp.text()).then(text => text);
startStr = 'ytplayer.config = {';
start = html.indexOf(startStr) + startStr.length - 1;
end = html.indexOf('};', start) + 1;
playerObj = JSON.parse(html.slice(start, end));
playerObj.args.player_response = JSON.parse(playerObj.args.player_response);
videoUrls = playerObj.args.player_response.streamingData.formats[1].url;
videoUrls = videoUrls.replace('"', 'r');
return console.log(videoUrls);
})();
For Download video with audio
(async () => { html = await fetch(window.location.href).then(resp => resp.text()).then(text => text); startStr = 'ytplayer.config = {'; start = html.indexOf(startStr) + startStr.length - 1; end = html.indexOf('};', start) + 1; playerObj = JSON.parse(html.slice(start, end)); playerObj.args.player_response = JSON.parse(playerObj.args.player_response); videoUrls = playerObj.args.player_response.streamingData.formats[1].url; videoUrls = videoUrls.replace('"', 'r'); return console.log(videoUrls); })();
Thank you, this works great!
For Download video with audio
(async () => { html = await fetch(window.location.href).then(resp => resp.text()).then(text => text); startStr = 'ytplayer.config = {'; start = html.indexOf(startStr) + startStr.length - 1; end = html.indexOf('};', start) + 1; playerObj = JSON.parse(html.slice(start, end)); playerObj.args.player_response = JSON.parse(playerObj.args.player_response); videoUrls = playerObj.args.player_response.streamingData.formats[1].url; videoUrls = videoUrls.replace('"', 'r'); return console.log(videoUrls); })();Thank you, this works great!
I've tried the script but I get a reject in promise. Seems not working. TypeError: Cannot read property 'url' of undefined↵ at <anonymous>:8:71
in what language is it written in? I need to rewrite it to swift
@nysander - did you ever get this converted to Swift?
in what language is it written in? I need to rewrite it to swift
@nysander - did you ever get this converted to Swift?
Nope because Apple is very strict with playback rights and I have dropped idea of this script in my app
Can I test this without the ytplayer?
I'm using React to create my own component (slider with video) and I don't think ytplayer is the best tool now, because it's too much just to get YouTube video URL.
You know some way to do that with only the video
id
?