get_video_info YouTube endpoint suddenly returning 404 not found
Asked Answered
P

11

25

https://www.youtube.com/get_video_info?video_id={videoId} is throwing

Response status code does not indicate success: 404 (Not Found).

Potential answered 20/5, 2021 at 6:48 Comment(3)
Isn't this info in the page metadata? I noticed Youtube is now using standard metadata en OG tags.Vesper
The solution was to use noembed.com service to get the video informations: Example URL: "noembed.com/embed?url=https://www.youtube.com/…" copywrites @Marco https://mcmap.net/q/537926/-youtube-get_video_info-throws-restriction-errorMime
the noembed.com is the right solution for now (July 2023). All other answers below are not functioning and not retrieve the data from youtube.Lexis
T
27

EDIT: I found this can work. I don't why. But it really works.

https://www.youtube.com/get_video_info?video_id=onz2k4zoLjQ&eurl=https%3A%2F%2Fyoutube.googleapis.com%2Fv%2Fonz2k4zoLjQ&html5=1&c=TVHTML5&cver=6.20180913


You can add &html5=1 in the url to fix it.

Technocracy answered 21/5, 2021 at 1:48 Comment(21)
Now this way failed too.Technocracy
One thing is different with this new method. Upload and publish date are not available! Am I the only one getting this?Patronymic
I added &html5=1&c=TVHTML5&cver=6.20180913 (from the URL in the main post) and it seems like it fixed the problemNomography
@EricZhao, I think it stopped working with the new solution also.Spent
The new method also stopped working today. @Technocracy you found any solutions for this bro?Patronymic
Still not working for me. Is it working for anyone?Fash
Hi guys. I just created a new package for C# developers that brings the playable urls. enjoy! nuget.org/packages/Youtube.VideoInfo/1.0.0Oribella
@AmiVaknin I'm guessing there's no publicly available source code I could use to help make myRust library work?Apollonius
@MGlolenstine it's my code, can I assist?Oribella
@AmiVaknin I have a Rust library that allows us to bypass "certain things" in yt videos, so I need to get direct links. I haven't found any working code for the past few updates, so I'd be interested in how you got it to work.Apollonius
@MGlolenstine you can create a C# code and use my library, I will soon publish my codeOribella
@AmiVaknin I'll wait for the code to be published :) rewriting the library in C# doesn't help me in the slightest, as there are a few programs relying on my library.Apollonius
@AmiVaknin "certain things" was referring to age restriction (I wanted to bypass the need for ID or Credit Card info). If your library uses the above way, I got it working.Apollonius
@MGlolenstine I'm not sure I'm following you... can you elaborate?Oribella
@AmiVaknin There's been tons of articles about it, mostly in EU it would seem. Youtube now requires you to either have a credit card connected to your Google account or send them your ID proving that you're 18+. Youtube-dl stopped working, so did most of other alternatives. That's why I'm looking into making a library that would help me bypass that and let me download the videos. For example this video doesn't work in incognito (or without confirmation).Apollonius
@MGlolenstine I think I got you. What my library does is bringing the streaming URLs of videos (without rights...only royalty-free). Download is quite the same but still could be some deltas. I suggest you open fiddler and record all the way of what youtube does. yes, they can do tricks but not magics ;)Oribella
@AmiVaknin yeah, they made tons of changes to the API to prevent people from doing what I am. Right now the only way to get access to those videos is to give them credentials (or use cookies) to an account that has been "activated".Apollonius
@MGlolenstine I think theres another way, like is used in the JDownloader app. They are not using Official API.Help
@Paulo A. Costa, I'm looking for the age bypass. I'll take a look tomorrow and see if JDownloader bypasses that. Thanks for pointing it out!Apollonius
@MGlolenstine They bypass using your login and password. JDownloader is open source (i guess they uses Java language).Help
@Paulo A. Costa I'm trying to avoid the login info. The problem is that you have to verify your login info using methods not many people want to share. That's what the bypass is for.Apollonius
C
14

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;

}
Coarsen answered 23/7, 2021 at 0:32 Comment(6)
But where is the key coming from? Could it be, that the key will be blocked in a short term?Palimpsest
The key has been generated from the request they captured, it's probably per-user key.Apollonius
I found that key and other player data in JavaScript at window.ytcfg.data_ It's set in a script embedded in the HTML, so it should be easy to scrape.Meraree
you're great, it work perfectly with fetch api in js by passing your "postfields" params with JSON.stringify. Thx 👍Alyosha
Below example may still contain optional request parameters as it was done in emergency. For your information I implemented this tool to simplify shell curl requests.Ossian
If you send just these it still works: { "context": {"client": {"clientName": "WEB", "clientVersion": "2.20210721.00.00"} }, "videoId": "UF8uR6Z6KLc"}Resistant
O
13

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.

Oribella answered 20/6, 2021 at 10:25 Comment(8)
Your solution work well. Where did you this update information?Husky
Google doesn't like when they don't have total control over everything. 😠 Why do you think they discontinued their "don't be evil" motto? It wasn't compatible with their goals anymore. ¬_¬Josey
Adding &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
indeed not working. now all these URLs return "410-gone". need to find the new trick ASAPOribella
has someone already found a solution?Thibaud
nuget.org/packages/Youtube.VideoInfoOribella
How to use nuget.org/packages/Youtube.VideoInfo in PHP and does it still work at all in C#?Paly
@Paly the code is working great in C# and I don't see how youtube can block me now. Regarding PHP: the language is not an issue here, you can build your server in C# - use nuget.org/packages/Youtube.VideoInfo return the links and use it in your PHP codeOribella
P
12

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.

Plank answered 9/8, 2021 at 11:51 Comment(1)
"formats" is not containing "url" anymore.Paly
S
6

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

Sentient answered 23/7, 2021 at 13:20 Comment(5)
It's working for public videos. any possibilities for private videos. get_video_info was able to return for private videos also.Spent
I was able to get the unlisted videos as well with the above wayWord
We're sorry... ... but your computer or network may be sending automated queries. To protect our users, we can't process your request right now.Dextroglucose
@toan-huynh how did you get the key? is it safe to use?Intertwist
Not a good idea to publish your API key on a public forumRaul
M
5

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>
Method answered 27/7, 2021 at 8:39 Comment(2)
Nice plugin. The last version 5 doesn't work.Murrain
What format does it use?Dannie
P
2

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();
}
Potential answered 27/8, 2021 at 6:30 Comment(1)
I have found that nowadays ytInitialPlayerResponse is sometimes available and sometimes not available. Have you noticed the same?Ophthalmology
P
0

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

Prolix answered 28/7, 2021 at 14:39 Comment(0)
M
0

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}
Mishap answered 28/8, 2021 at 17:50 Comment(0)
T
0

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
}
Teodoro answered 28/3, 2023 at 10:58 Comment(0)
F
-5
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.

Fallfish answered 16/6, 2021 at 1:54 Comment(1)
i don't see a difference when you fixed it! It still shows nullImpend

© 2022 - 2024 — McMap. All rights reserved.