https://www.youtube.com/get_video_info?video_id={videoId} is throwing
Response status code does not indicate success: 404 (Not Found).
https://www.youtube.com/get_video_info?video_id={videoId} is throwing
Response status code does not indicate success: 404 (Not Found).
EDIT: I found this can work. I don't why. But it really works.
You can add &html5=1
in the url to fix it.
&html5=1&c=TVHTML5&cver=6.20180913
(from the URL in the main post) and it seems like it fixed the problem –
Nomography I think I've found an alternative to YouTube get_video_info endpoint.
Below is a CURL & PHP (CURL) implementation of the POST request to youtubei/v1/player endpoint with minimum required request headers & parameters.
I've removed many request headers & parameters from the request to stay simple & as anonymous as possible in the same way as when using GET get_video_info endpoint. e.g cookies, user-agent, etc.
Below example may still contain optional request parameters as it was done in emergency.
I found this new API by inspecting the XHR network requests in firefox after setting the user-agent to a television.
firefox-inspect-network-xhr-requests-television-user-agent
Example video link used in CURL request below:
https://www.youtube.com/watch?v=UF8uR6Z6KLc
CURL
curl 'https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8' -H 'Content-Type: application/json' --data '{ "context": { "client": { "hl": "en", "clientName": "WEB", "clientVersion": "2.20210721.00.00", "clientFormFactor": "UNKNOWN_FORM_FACTOR", "clientScreen": "WATCH", "mainAppWebInfo": { "graftUrl": "/watch?v=UF8uR6Z6KLc", } }, "user": { "lockedSafetyMode": false }, "request": { "useSsl": true, "internalExperimentFlags": [], "consistencyTokenJars": [] } }, "videoId": "UF8uR6Z6KLc", "playbackContext": { "contentPlaybackContext": { "vis": 0, "splay": false, "autoCaptionsDefaultOn": false, "autonavState": "STATE_NONE", "html5Preference": "HTML5_PREF_WANTS", "lactMilliseconds": "-1" } }, "racyCheckOk": false, "contentCheckOk": false}'
PHP (CURL)
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;
}
{ "context": {"client": {"clientName": "WEB", "clientVersion": "2.20210721.00.00"} }, "videoId": "UF8uR6Z6KLc"}
–
Resistant For some reason, Google is trying to make it harder.
Edit Aug 2021:
I just published a new NuGet for C# developers that brings URLs of get_video_info. Enjoy! https://www.nuget.org/packages/Youtube.VideoInfo
The initial value was
https://www.youtube.com/get_video_info?video_id={videoId}&eurl=https://youtube.googleapis.com/v/{videoId}
Then the HTML5 tag was added:
https://www.youtube.com/get_video_info?html5=1&video_id={videoId}&eurl=https://youtube.googleapis.com/v/{videoId}
And now (June 2021) the new solution is:
https://www.youtube.com/get_video_info?video_id={videoId}&eurl=https%3A%2F%2Fyoutube.googleapis.com%2Fv%2Fonz2k4zoLjQ&html5=1&c=TVHTML5&cver=6.20180913
We need to keep our eyes open. looks like someone in google doesn't like the fact that YouTube enables this feature.
&html5=1&c=TVHTML5&cver=6.20180913
fixed the 404 connection error for me - it looks like the eurl=
query argument might be optional. –
Antipus Youtube (at time of writing 8 aug 2021) look to have moved the equivalent output into the watch?v=
end point. You should find video formats within the ytInitialPlayerResponse
(json) variable within the html it returns.
E.g. https://youtube.com/watch?v=SA8ZBJWo73E returns html. Within that html response ytInitialPlayerResponse
variable contains a json string. In that string, you can find the video formats under: [streamingData][formats]
.
I'd love to take all credit but this example commit was where I found the answer.
UPDATE (July 2021)
I have try this way
POST: https://youtubei.googleapis.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8
with the body:
{
"context": {
"client": {
"hl": "en",
"clientName": "WEB",
"clientVersion": "2.20210721.00.00",
"mainAppWebInfo": {
"graftUrl": "/watch?v={VIDEO_ID}"
}
}
},
"videoId": "{VIDEO_ID}"
}
And this work like a charm
You can try with this plugin
new YouTubeToHtml5();
<script src="https://cdn.jsdelivr.net/gh/thelevicole/[email protected]/dist/YouTubeToHtml5.js"></script>
<video data-yt2html5="https://www.youtube.com/watch?v=ScMzIvxBSi4" controls></video>
This is how I am getting youtube streaming data formats right now. Maybe it can help someone.
var videoInfoUrl = $"https://www.youtube.com/watch?v={videoId}";
using (var client = new HttpClient())
{
var videoPageContent = await client.GetStringAsync(videoInfoUrl);
var regex = new Regex(@"ytInitialPlayerResponse\s*=\s*(\{.+?\})\s*;", RegexOptions.Multiline);
var match = regex.Match(videoPageContent);
if (!match.Success)
return "";
var json = match.Result("$1");
var playerResponseJson = JToken.Parse(json);
var formats = playerResponseJson.SelectToken("streamingData.formats").ToList();
}
Try 1060 fix - This issue is yet to be fix in Pytube package. Until it is formally available in Pytube, you can install below one in your system to get downloading work. https://github.com/Zeecka/pytube/tree/fix_1060
For more detail you can refer https://github.com/pytube/pytube/issues/1060
The best solution I've found so far for Python projects that need the data from the get_video_info
API seems to be to use the InnerTube
API from the pytube
project:
>>> from pytube.innertube import InnerTube
>>> innertube = InnerTube()
>>> video_info = innertube.player("dQw4w9WgXcQ")
>>> video_info.keys()
dict_keys(['responseContext', 'trackingParams', 'adBreakParams', 'playabilityStatus', 'streamingData', 'playbackTracking', 'videoDetails', 'annotations', 'playerConfig', 'storyboards', 'attestation', 'videoQualityPromoSupportedRenderers', 'messages', 'endscreen', 'playerSettingsMenuData'])
>>> video_info["videoDetails"]
{'videoId': 'dQw4w9WgXcQ', 'title': 'Rick Astley - Never Gonna Give You Up (Official Music Video)', 'lengthSeconds': '212', 'keywords': ['rick astley', 'Never Gonna Give You Up', 'nggyu', 'never gonna give you up lyrics', 'rick rolled', 'the boys soundtrack', 'the boys amazon prime', 'Never gonna give you up the boys', 'official', 'Rick Roll', 'music video', 'Rick Astley album', 'rick astley official', 'together forever', 'Whenever You Need Somebody', 'rickrolled', 'WRECK-IT RALPH 2', 'Fortnite song', 'Fortnite event', 'Fortnite dance', 'fortnite never gonna give you up', 'rick astley never gonna give you up', 'rick astley never gonna give you up lyrics'], 'channelId': 'UCuAXFkgsw1L7xaCfnd5JJOw', 'isOwnerViewing': False, 'shortDescription': "Rick Astley's official music video for “Never Gonna Give You Up” \n\nSubscribe to the official Rick Astley YouTube channel: https://RickAstley.lnk.to/YTSubID\n\nFollow Rick Astley:\nFacebook: https://RickAstley.lnk.to/FBFollowID \nTwitter: https://RickAstley.lnk.to/TwitterID \nInstagram: https://RickAstley.lnk.to/InstagramID \nWebsite: https://RickAstley.lnk.to/storeID \nTikTok: https://RickAstley.lnk.to/TikTokID\n\nListen to Rick Astley:\nSpotify: https://RickAstley.lnk.to/SpotifyID \nApple Music: https://RickAstley.lnk.to/AppleMusicID \nAmazon Music: https://RickAstley.lnk.to/AmazonMusicID \nDeezer: https://RickAstley.lnk.to/DeezerID \n\nLyrics:\nWe’re no strangers to love\nYou know the rules and so do I\nA full commitment’s what I’m thinking of\nYou wouldn’t get this from any other guy\n\nI just wanna tell you how I’m feeling\nGotta make you understand\n\nNever gonna give you up\nNever gonna let you down\nNever gonna run around and desert you\nNever gonna make you cry\nNever gonna say goodbye\nNever gonna tell a lie and hurt you\n\nWe’ve known each other for so long\nYour heart’s been aching but you’re too shy to say it\nInside we both know what’s been going on\nWe know the game and we’re gonna play it\n\nAnd if you ask me how I’m feeling\nDon’t tell me you’re too blind to see\n\nNever gonna give you up\nNever gonna let you down\nNever gonna run around and desert you\nNever gonna make you cry\nNever gonna say goodbye\nNever gonna tell a lie and hurt you\n\n#RickAstley #NeverGonnaGiveYouUp #OfficialMusicVideo", 'isCrawlable': True, 'thumbnail': {'thumbnails': [{'url': 'https://i.ytimg.com/vi/dQw4w9WgXcQ/default.jpg', 'width': 120, 'height': 90}, {'url': 'https://i.ytimg.com/vi/dQw4w9WgXcQ/mqdefault.jpg', 'width': 320, 'height': 180}, {'url': 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg', 'width': 480, 'height': 360}, {'url': 'https://i.ytimg.com/vi/dQw4w9WgXcQ/sddefault.jpg', 'width': 640, 'height': 480}]}, 'averageRating': 4.893901, 'allowRatings': True, 'viewCount': '1031179782', 'author': 'Rick Astley', 'isPrivate': False, 'isUnpluggedCorpus': False, 'isLiveContent': False}
Dhruv Gohil answer in swift:
private func process(inputString: String) -> [String: Any]?
{
do {
let regex = try NSRegularExpression(pattern: "ytInitialPlayerResponse\\s*=\\s*(\\{.+?\\})\\s*;", options: [])
if let match = regex.firstMatch(in: inputString, options: [], range: NSRange(location: 0, length: inputString.utf16.count)),
let range = Range(match.range(at: 1), in: inputString)
{
let jsonString = String(inputString[range])
let jsonData = jsonString.data(using: .utf8)!
let json = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any]
// json is now a dictionary
print("\n\n\(jsonString)\n\n")
return json
}
} catch {
os_trace("pile parsing: got error \(error)", .error)
}
return nil
}
function getVideo($url)
{
parse_str(file_get_contents("https://www.youtube.com/get_video_info?video_id=$url&html5=1"), $data);
return $finalData = json_decode($data['player_response'], true);
}
header('Content-Type: application/json');
echo json_encode(getVideo('Zrcg7w67Ots'));
I use it like that but sometimes it works and sometimes it doesn't, i.e. when it returns info sometimes it doesn't. Can you fix anything in there, many thanks.
© 2022 - 2024 — McMap. All rights reserved.