fent / node-ytdl-core

YouTube video downloader in javascript.
MIT License
4.47k stars 790 forks source link

Improve video details extraction by using innertube API #960

Open WaqasIbrahim opened 3 years ago

WaqasIbrahim commented 3 years ago

YouTube is slowly migrating to their new innertube API and we should consider using the new API for consitent and reliable results. youtube-dl is already using this new API.

Examples:

curl --location --request POST 'https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8' \
--header 'Content-Type: application/json' \
--data-raw '{
    "context": {
        "client": {
            "clientName": "WEB",
            "clientVersion": "2.20210623.00.00"
        }
    },
    "videoId": "vKJpN5FAeF4"
}'

An age restricted video that does not work with get_video_info route.

curl --location --request POST 'https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8' \
--header 'Content-Type: application/json' \
--data-raw '{
    "context": {
        "client": {
            "clientName": "WEB_EMBEDDED_PLAYER",
            "clientVersion": "1.20210623.1.0"
        }
    },
    "videoId": "HtVdAasjOgU"
}'

The API key and client version can be extracted from watch or embed page.

gatecrasher777 commented 3 years ago

I published an innertube library two days ago. The biggest issues I found was that innertube would happily deliver ciphered streams that would not play (403) when deciphered (solved when your post request includes a valid playback context with the correct signature timestamp from the player). Also when making a logged-in request (bypassing age-restriction), you need to supply a SAPISIDHASH, which is another obfuscated function from the yt player. So it is tricky to depend only on the innertube, unless you are emulating exactly what is happening in the browser.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

gatecrasher777 commented 2 years ago

In the getInfo pipeline only the html watch page seems to be working at present. The json watch page request is ignored by YT and the get_video_info call returns 410 errors. Inevitably, a move to the innerube api is needed. For these reasons this issue should not become stale.

TechBroCode commented 1 month ago

I published an innertube library two days ago. The biggest issues I found was that innertube would happily deliver ciphered streams that would not play (403) when deciphered (solved when your post request includes a valid playback context with the correct signature timestamp from the player). Also when making a logged-in request (bypassing age-restriction), you need to supply a SAPISIDHASH, which is another obfuscated function from the yt player. So it is tricky to depend only on the innertube, unless you are emulating exactly what is happening in the browser.

YouTube updated their bin player base.js file then i included the correct signature timestamp from that file and passed it below the body context key via json but still got 403 error when trying to play the video url. You also talked about SAPISIDHASH, how do I pass it to the POST request?

gatecrasher777 commented 1 month ago

I published an innertube library two days ago. The biggest issues I found was that innertube would happily deliver ciphered streams that would not play (403) when deciphered (solved when your post request includes a valid playback context with the correct signature timestamp from the player). Also when making a logged-in request (bypassing age-restriction), you need to supply a SAPISIDHASH, which is another obfuscated function from the yt player. So it is tricky to depend only on the innertube, unless you are emulating exactly what is happening in the browser.

YouTube updated their bin player base.js file then i included the correct signature timestamp from that file and passed it below the body context key via json but still got 403 error when trying to play the video url. You also talked about SAPISIDHASH, how do I pass it to the POST request?

It is passed to the POST request by including it in the headers as the authorization property. So, from https://github.com/gatecrasher777/ytcog/blob/main/lib/video.js on line 362

if (this.session.loggedIn) hdrs.authorization = this.session.player.idhashFn(this.sapisid);

As it suggests, this is required for innertube requests when you are "logged-in", i.e. have supplied a valid session cookie.