Skip to content

Instantly share code, notes, and snippets.

@xissy
Last active November 29, 2023 18:09
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save xissy/3812653 to your computer and use it in GitHub Desktop.
Save xissy/3812653 to your computer and use it in GitHub Desktop.
Get a youtube video information from get_video_info.
request = require 'request'
youTubeMovieInfo =
youTubeMovieId: 'videoId'
url = "http://www.youtube.com/get_video_info?video_id=#{youTubeMovieInfo.youTubeMovieId}"
request.get url, (err, res, body) ->
return callback(false) if err
return callback(false) if res.statusCode isnt 200
formats = parseYoutubeInfoStringToFormats(body)
return callback(false) if formats is null
mp4StreamUrl = getMp4StreamUrlFromFormats(formats)
youTubeMovieInfo.mp4StreamUrl = mp4StreamUrl
# parse youtube api json response.
parseYoutubeInfoStringToFormats = (youtubeInfoString) ->
youtubeInfoArray = youtubeInfoString.split '&'
return null if youtubeInfoArray[0] is 'status=fail'
formatStreamArrayString = (element for element in youtubeInfoArray when element.split('=')[0] is 'url_encoded_fmt_stream_map')[0].split('=')[1]
formatStreamArray = decodeURIComponent(formatStreamArrayString).split(',')
formats = []
for formatStreamString in formatStreamArray
formatInfoArray = formatStreamString.split '&'
formatInfoMap = {}
for formatInfoElement in formatInfoArray
formatInfoElementPair = formatInfoElement.split '='
formatInfoMap[formatInfoElementPair[0]] = decodeURIComponent(formatInfoElementPair[1])
formats.push formatInfoMap
return formats
# find mp4 stream url from parsed data.
getMp4StreamUrlFromFormats = (formats) ->
return format.url for format in formats when format.itag is '18'
@JeanPaul3
Copy link

Hi
Do you know a similar code in php?
thanks

@JeanPaul3
Copy link

Thanks for the answer, but unfortunately getVideoInfo () not from anymore the results that you manage with your code, particularly the index "url_encoded_fmt_stream_map" it doesn't exist anymore, but it is necessary to intercept the index "player_response."
I attach you a code what works alone if is present the index 'url' , but unfortunately in the most greater part of the video Youtube the url is now drowned in the index "cipher", that I don't know whether to decipher.
for example the id: "QGV14x_8-eQ" directly returns an url downloadable, while the id "7cGWMlcAWq4" not!
Do You succeed there even?
This is the code
`<?PHP
//$id = "QGV14x_8-eQ";
$id = "7cGWMlcAWq4";
$data = youtube_info($id);
foreach($data[0] as $h => $v) echo ($h.":".$v."
");

function youtube_info($id)
	{
		$vformat = "video/mp4"; 				// The MIME type of the video. e.g. video/mp4, video/webm, etc.
		$url = "http://youtube.com/get_video_info?video_id=".$id;
		parse_str(file_get_contents($url),$info);
		if (!array_key_exists('player_response',$info)) 
			$div[0] = 'not found';
			else
			{	$videos = $info["player_response"];
				$i = 0;
				while ($i != 99)
					{ $da = strpos($videos,'{"itag"')+1;
					  $per = strpos($videos,'}',$da) - $da;
					  $data = substr($videos,$da,$per);
					   
					  if (strpos($data,$vformat) && strpos($data,'"quality"')) $itags [$i++] = $data; 
					  
					  $videos = substr($videos,$da + $per);
					  if ( !strpos($videos,'{"itag"') ) $i = 99;
					}
				$y = 0;
				$c = count($itags); $i = 0;
				while ($c--)
					{ $itags[$i] = str_replace ('":' , ':' , $itags[$i] );
					  $itags[$i] = str_replace ('"itag' , 'itag' , $itags[$i] );
					  $array = explode(',"',$itags[$i++]);
					  $base = array();
					  foreach($array as $h => $v) 
						{ $d = strpos($array[$h],":");
						  $ch = substr($array[$h],0,$d);
						  $dt = substr($array[$h],$d+1);
						  if (substr($dt,0,1) == '"') 
						  		$dt = substr($dt,1,strlen($dt)-2);
						  $base[$ch] = str_replace("\\u0026","&",$dt);
						}
					  if (!array_key_exists('url',$base)) 
					  	{ parse_str($base["cipher"],$dturl);
							foreach($dturl as $h => $v) echo ($h.":".$v."<br>");
							$url = $dturl['url'].'&sig='.$dturl['s'];
					  	}
					  $elem = array();
						if (array_key_exists('url',$base)) 
							{ $elem['url'] = $base['url']; $elem['dec'] = urldecode($base['url']); }
							else 
							{ $elem['cipher'] = $base['cipher']; $elem['dec'] = urldecode($base['cipher']); }
						$elem['itag'] = $base['itag'];
						$elem['formato'] = 'mp4';
						$elem['quality'] = $base['quality'];
						$elem['dim'] = $base['qualityLabel'];
					  $div [$y++] = $elem;
					}
			}
		return $div;
	}

?>`

@parthavi-patel
Copy link

Thanks for the answer, but unfortunately getVideoInfo () not from anymore the results that you manage with your code, particularly the index "url_encoded_fmt_stream_map" it doesn't exist anymore, but it is necessary to intercept the index "player_response."
I attach you a code what works alone if is present the index 'url' , but unfortunately in the most greater part of the video Youtube the url is now drowned in the index "cipher", that I don't know whether to decipher.
for example the id: "QGV14x_8-eQ" directly returns an url downloadable, while the id "7cGWMlcAWq4" not!
Do You succeed there even?
This is the code
`<?PHP
//$id = "QGV14x_8-eQ";
$id = "7cGWMlcAWq4";
$data = youtube_info($id);
foreach($data[0] as $h => $v) echo ($h.":".$v."
");

function youtube_info($id)
	{
		$vformat = "video/mp4"; 				// The MIME type of the video. e.g. video/mp4, video/webm, etc.
		$url = "http://youtube.com/get_video_info?video_id=".$id;
		parse_str(file_get_contents($url),$info);
		if (!array_key_exists('player_response',$info)) 
			$div[0] = 'not found';
			else
			{	$videos = $info["player_response"];
				$i = 0;
				while ($i != 99)
					{ $da = strpos($videos,'{"itag"')+1;
					  $per = strpos($videos,'}',$da) - $da;
					  $data = substr($videos,$da,$per);
					   
					  if (strpos($data,$vformat) && strpos($data,'"quality"')) $itags [$i++] = $data; 
					  
					  $videos = substr($videos,$da + $per);
					  if ( !strpos($videos,'{"itag"') ) $i = 99;
					}
				$y = 0;
				$c = count($itags); $i = 0;
				while ($c--)
					{ $itags[$i] = str_replace ('":' , ':' , $itags[$i] );
					  $itags[$i] = str_replace ('"itag' , 'itag' , $itags[$i] );
					  $array = explode(',"',$itags[$i++]);
					  $base = array();
					  foreach($array as $h => $v) 
						{ $d = strpos($array[$h],":");
						  $ch = substr($array[$h],0,$d);
						  $dt = substr($array[$h],$d+1);
						  if (substr($dt,0,1) == '"') 
						  		$dt = substr($dt,1,strlen($dt)-2);
						  $base[$ch] = str_replace("\\u0026","&",$dt);
						}
					  if (!array_key_exists('url',$base)) 
					  	{ parse_str($base["cipher"],$dturl);
							foreach($dturl as $h => $v) echo ($h.":".$v."<br>");
							$url = $dturl['url'].'&sig='.$dturl['s'];
					  	}
					  $elem = array();
						if (array_key_exists('url',$base)) 
							{ $elem['url'] = $base['url']; $elem['dec'] = urldecode($base['url']); }
							else 
							{ $elem['cipher'] = $base['cipher']; $elem['dec'] = urldecode($base['cipher']); }
						$elem['itag'] = $base['itag'];
						$elem['formato'] = 'mp4';
						$elem['quality'] = $base['quality'];
						$elem['dim'] = $base['qualityLabel'];
					  $div [$y++] = $elem;
					}
			}
		return $div;
	}

?>`

@

Hello @JeanPaul3

Your PHP code works for me , but why for some YouTube videos, it is not returning MP4 URL ?
can you please help me with this ? Do you have any alternative solution for this ?

I need direct MP4 URL of YouTube video

@AnasQiblawi
Copy link

AnasQiblawi commented Jul 13, 2021

@Aduffy
Copy link

Aduffy commented Jul 22, 2021

New Method

https://www.youtube.com/get_video_info?video_id={videoId}&eurl=https://youtube.googleapis.com/v/{videoId}&html5=1&c=TVHTML5&cver=6.20180913

change {videoid}
there are two of them.

Seems like as of this morning this method is no longer working

@chungminhtu
Copy link

New Method

https://www.youtube.com/get_video_info?video_id={videoId}&eurl=https://youtube.googleapis.com/v/{videoId}&html5=1&c=TVHTML5&cver=6.20180913
change {videoid}
there are two of them.

Seems like as of this morning this method is no longer working

Yes, It return 404 now. Unfortunately.

@hubert17
Copy link

New Method not working. Sad.

@hariprakashnagar
Copy link

I am facing same issue. anyone can help please.

@jiaghara
Copy link

jiaghara commented Jul 23, 2021

try this one is working for me

echo getVideoInfo("op4B9sNGi0k");

`>function getVideoInfo($video_id){

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{  "context": {    "client": {      "hl": "en",      "clientName": "WEB",      "clientVersion": "2.20210721.00.00",      "clientFormFactor": "UNKNOWN_FORM_FACTOR",   "clientScreen": "WATCH",      "mainAppWebInfo": {        "graftUrl": "/watch?v='.$video_id.'",           }    },    "user": {      "lockedSafetyMode": false    },    "request": {      "useSsl": true,      "internalExperimentFlags": [],      "consistencyTokenJars": []    }  },  "videoId": "'.$video_id.'",  "playbackContext": {    "contentPlaybackContext": {        "vis": 0,      "splay": false,      "autoCaptionsDefaultOn": false,      "autonavState": "STATE_NONE",      "html5Preference": "HTML5_PREF_WANTS",      "lactMilliseconds": "-1"    }  },  "racyCheckOk": false,  "contentCheckOk": false}');
curl_setopt($ch, CURLOPT_ENCODING, 'gzip, deflate');
$headers = array();
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);  }
curl_close($ch);
return $result;

}
`

@surajpendhare
Copy link

try this one is working for me

echo getVideoInfo("op4B9sNGi0k");

`>function getVideoInfo($video_id){

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{  "context": {    "client": {      "hl": "en",      "clientName": "WEB",      "clientVersion": "2.20210721.00.00",      "clientFormFactor": "UNKNOWN_FORM_FACTOR",   "clientScreen": "WATCH",      "mainAppWebInfo": {        "graftUrl": "/watch?v='.$video_id.'",           }    },    "user": {      "lockedSafetyMode": false    },    "request": {      "useSsl": true,      "internalExperimentFlags": [],      "consistencyTokenJars": []    }  },  "videoId": "'.$video_id.'",  "playbackContext": {    "contentPlaybackContext": {        "vis": 0,      "splay": false,      "autoCaptionsDefaultOn": false,      "autonavState": "STATE_NONE",      "html5Preference": "HTML5_PREF_WANTS",      "lactMilliseconds": "-1"    }  },  "racyCheckOk": false,  "contentCheckOk": false}');
curl_setopt($ch, CURLOPT_ENCODING, 'gzip, deflate');
$headers = array();
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);  }
curl_close($ch);
return $result;

}
`

how can i use this code in nodejs

@AnasQiblawi
Copy link

AnasQiblawi commented Jul 23, 2021

Simplified

Method: POST

URL:

https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8

Content Type:

JSON (application/json)

Content:

{
   "context":{
      "client":{
         "hl":"en",
         "clientName":"WEB",
         "clientVersion":"2.20210721.00.00",
         "clientFormFactor":"UNKNOWN_FORM_FACTOR",
         "clientScreen":"WATCH",
         "mainAppWebInfo":{
            "graftUrl": "/watch?v={Video ID}"🛑
         }
      },
      "user":{
         "lockedSafetyMode":false
      },
      "request":{
         "useSsl":true,
         "internalExperimentFlags":[
            
         ],
         "consistencyTokenJars":[
            
         ]
      }
   },
   "videoId":"{Video ID}",🛑
   "playbackContext":{
      "contentPlaybackContext":{
         "vis":0,
         "splay":false,
         "autoCaptionsDefaultOn":false,
         "autonavState":"STATE_NONE",
         "html5Preference":"HTML5_PREF_WANTS",
         "lactMilliseconds":"-1"
      }
   },
   "racyCheckOk":false,
   "contentCheckOk":false
}

Change {Video ID}

Live Demo

https://reqbin.com/9d2xjrp2

@AnasQiblawi
Copy link

AnasQiblawi commented Jul 23, 2021

@surajpendhare

how can i use this code in nodejs


I think it's better to use youtube-dl on NodeJS.

Examples

const { getInfo } = require('ytdl-getinfo')
const youtube_video_id = "XxEhuSJF780"; // you can use full url too, https://www.youtube.com/watch?v=XxEhuSJF780

Method 1

getInfo( youtube_video_id ).then(info => {
    // info.items[0] should contain the output of youtube-dl --dump-json
    console.log( info.items[0] )
});

Method 2

getInfo( youtube_video_id, ['--dump-json'] ).then(info => {
    console.log( info.items[0] )
});

References:

https://www.npmjs.com/package/ytdl-getinfo

@thenandkishorkumawat
Copy link

old ytInfoUrl += "www.youtube.com/get_video_info?video_id=" + videoID + "&eurl="
+ URLEncoder.encode("https://youtube.googleapis.com/v/" + videoID, "UTF-8")
+"&html5=1&c=TVHTML5&cver=6.20180913";

and i update new ytInfoUrl

            ytInfoUrl += "www.youtube.com/get_video_info?video_id=" + videoID + "&eurl="
            + URLEncoder.encode("https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8/" + videoID, "UTF-8")
            +"&html5=1&c=TVHTML5&cver=6.20180913";

but still video not playing and showing the W/System.err: java.io.FileNotFoundException Error

@AnasQiblawi
Copy link

AnasQiblawi commented Jul 24, 2021

@surajpendhare @thenandkishorkumawat
Your solution is working for me.
But, How can i parse response in node js.


const request = require('request');
const youtube_video_id = 'XxEhuSJF780'; // https://www.youtube.com/watch?v=XxEhuSJF780


var options = {
    method: 'POST',
    url: 'https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8',
    'headers': {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        "context": {
            "client": {
                "hl": "en",
                "clientName": "WEB",
                "clientVersion": "2.20210721.00.00",
                "clientFormFactor": "UNKNOWN_FORM_FACTOR",
                "clientScreen": "WATCH",
                "mainAppWebInfo": {
                    "graftUrl": "/watch?v=" + youtube_video_id
                }
            },
            "user": {
                "lockedSafetyMode": false
            },
            "request": {
                "useSsl": true,
                "internalExperimentFlags": [

                ],
                "consistencyTokenJars": [

                ]
            }
        },
        "videoId": youtube_video_id,
        "playbackContext": {
            "contentPlaybackContext": {
                "vis": 0,
                "splay": false,
                "autoCaptionsDefaultOn": false,
                "autonavState": "STATE_NONE",
                "html5Preference": "HTML5_PREF_WANTS",
                "lactMilliseconds": "-1"
            }
        },
        "racyCheckOk": false,
        "contentCheckOk": false
    })

};



request(options, function(error, response, body) {
    if (error) throw new Error(error);
    console.log(JSON.parse(body));
});

@yarteks
Copy link

yarteks commented Aug 12, 2021

Simplified

Method: POST

URL:

https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8

Content Type:

JSON (application/json)

Content:

{
   "context":{
      "client":{
         "hl":"en",
         "clientName":"WEB",
         "clientVersion":"2.20210721.00.00",
         "clientFormFactor":"UNKNOWN_FORM_FACTOR",
         "clientScreen":"WATCH",
         "mainAppWebInfo":{
            "graftUrl": "/watch?v={Video ID}"🛑
         }
      },
      "user":{
         "lockedSafetyMode":false
      },
      "request":{
         "useSsl":true,
         "internalExperimentFlags":[
            
         ],
         "consistencyTokenJars":[
            
         ]
      }
   },
   "videoId":"{Video ID}",🛑
   "playbackContext":{
      "contentPlaybackContext":{
         "vis":0,
         "splay":false,
         "autoCaptionsDefaultOn":false,
         "autonavState":"STATE_NONE",
         "html5Preference":"HTML5_PREF_WANTS",
         "lactMilliseconds":"-1"
      }
   },
   "racyCheckOk":false,
   "contentCheckOk":false
}

Change {Video ID}

Live Demo

https://reqbin.com/9d2xjrp2

from where is the key, what is thatclient, goodsolution, thanks

@Loule95450
Copy link

🙌 I used this method

URL :

https://www.youtube.com/youtubei/v1/player?key=`key`

Content Type :

JSON (application/json)

Content :

{
   "context":{
      "client":{
         "hl":"en",
         "clientName":"WEB",
         "clientVersion":"2.20210721.00.00",
         "clientFormFactor":"UNKNOWN_FORM_FACTOR",
         "clientScreen":"WATCH",
         "mainAppWebInfo":{
            "graftUrl": "/watch?v={Video ID}" // <- Change here (Delete this comment)
         }
      },
      "user":{
         "lockedSafetyMode":false
      },
      "request":{
         "useSsl":true,
         "internalExperimentFlags":[
            
         ],
         "consistencyTokenJars":[
            
         ]
      }
   },
   "videoId":"{Video ID}", // <- Change here (Delete this comment)
   "playbackContext":{
      "contentPlaybackContext":{
         "vis":0,
         "splay":false,
         "autoCaptionsDefaultOn":false,
         "autonavState":"STATE_NONE",
         "html5Preference":"HTML5_PREF_WANTS",
         "lactMilliseconds":"-1"
      }
   },
   "racyCheckOk":false,
   "contentCheckOk":false
}

@guig3
Copy link

guig3 commented Nov 29, 2023

How do I return the MP4 URL for download using PHP? My function is below:
`function getVideoInfo($video_id){

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{  "context": {    "client": {      "hl": "en",      "clientName": "WEB",      "clientVersion": "2.20210721.00.00",      "clientFormFactor": "UNKNOWN_FORM_FACTOR",   "clientScreen": "WATCH",      "mainAppWebInfo": {        "graftUrl": "/watch?v='.$video_id.'",           }    },    "user": {      "lockedSafetyMode": false    },    "request": {      "useSsl": true,      "internalExperimentFlags": [],      "consistencyTokenJars": []    }  },  "videoId": "'.$video_id.'",  "playbackContext": {    "contentPlaybackContext": {        "vis": 0,      "splay": false,      "autoCaptionsDefaultOn": false,      "autonavState": "STATE_NONE",      "html5Preference": "HTML5_PREF_WANTS",      "lactMilliseconds": "-1"    }  },  "racyCheckOk": false,  "contentCheckOk": false}');
curl_setopt($ch, CURLOPT_ENCODING, 'gzip, deflate');

$headers = array();
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
return $result;

}

$video_link = 'https://www.youtube.com/watch?v='.$vid;
preg_match('%(?:youtube(?:-nocookie)?.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu.be/)([^"&?/ ]{11})%i', $video_link, $match);
$video_id = $vid;
$video = json_decode(getVideoInfo($video_id));
$formats = $video->streamingData->formats;
$adaptiveFormats = $video->streamingData->adaptiveFormats;
$thumbnails = $video->videoDetails->thumbnail->thumbnails;
$title = $video->videoDetails->title;
$short_description = $video->videoDetails->shortDescription;
$thumbnail = end($thumbnails)->url;`

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