Retrieve all videos from youtube playlist using youtube v3 API
Asked Answered
B

9

83

I'm retrieving videos of a playlist using youtube v3 API and getting 50 items without any problem with this link:-

https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=PLB03EA9545DD188C3&key=MY_API_KEY

But the video count is 100 and I'm only getting 50. How can I get the next 50 items? I tried start-index but it does not work for v3 API. Any help is appreciated.

Bohun answered 14/9, 2013 at 18:12 Comment(1)
See my answer her ..... #14173928Blomquist
T
65

YouTube Data API v3 results are paginated. So you need to get the next page of results for the others.

Basically in the response you have nextPageToken.

To get the remaining results, do the same exact call but setting pageToken into that token you received.

Trichocyst answered 14/9, 2013 at 20:18 Comment(2)
@ibrahim Ulukaya can you help me on this question #18857051Astrahan
it gives me videos till last one year only.. is this an api constraint?Aslant
A
39

There are three tokes

  1. pageToken
  2. nextPageToken
  3. prevPageToken

and also you can set max page size using

maxResults=50 {allowed Values 1 to 50 }

if you are on page 1 you won't get prevPageToken

but you get nextPageToken

pass this token to next request's

pageToken = {nextPageToken get from last request}

this way you can navigate to next page Try it Your Self

Edited

Ok, for other scenarios

If you are on First Page then

  1. pageToken = 'Some values'
  2. nextPageToken = 'Some values'
  3. prevPageToken = null

If you are on neither the first nor last page then

  1. pageToken = 'Some values'
  2. nextPageToken = 'Some values'
  3. prevPageToken = 'Some values'

@Manoj: you can find your answer below

if you are on the last page

  1. pageToken = 'Some values'
  2. nextPageToken = null
  3. prevPageToken = 'Some value'

Even the field may not be present.

Astrahan answered 15/9, 2013 at 7:41 Comment(1)
How do we know if current page is the last page? nextPageToken will be missing in last responseSatisfactory
D
25

This is a small example made in python using the Python Youtube Client Lib This also borrows boilerplate setup from the youtube API examples

""" Pull All Youtube Videos from a Playlist """

from apiclient.discovery import build
from apiclient.errors import HttpError
from oauth2client.tools import argparser


DEVELOPER_KEY = "YOURKEY HERE"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"

def fetch_all_youtube_videos(playlistId):
    """
    Fetches a playlist of videos from youtube
    We splice the results together in no particular order

    Parameters:
        parm1 - (string) playlistId
    Returns:
        playListItem Dict
    """
    youtube = build(YOUTUBE_API_SERVICE_NAME,
                    YOUTUBE_API_VERSION,
                    developerKey=DEVELOPER_KEY)
    res = youtube.playlistItems().list(
    part="snippet",
    playlistId=playlistId,
    maxResults="50"
    ).execute()

    nextPageToken = res.get('nextPageToken')
    while ('nextPageToken' in res):
        nextPage = youtube.playlistItems().list(
        part="snippet",
        playlistId=playlistId,
        maxResults="50",
        pageToken=nextPageToken
        ).execute()
        res['items'] = res['items'] + nextPage['items']

        if 'nextPageToken' not in nextPage:
            res.pop('nextPageToken', None)
        else:
            nextPageToken = nextPage['nextPageToken']

    return res

if __name__ == '__main__':
  # comedy central playlist, has 332 video
  # https://www.youtube.com/watch?v=tJDLdxYKh3k&list=PLD7nPL1U-R5rDpeH95XsK0qwJHLTS3tNT
  videos = fetch_all_youtube_videos("PLD7nPL1U-R5rDpeH95XsK0qwJHLTS3tNT")

videos will be a list of all your videos concatenated to the first list. It will keep fetching until it has all the videos because of pagination by 50. A similar approach can be taken in other languages.

In the list there will be all the individual video meta data and order

Dionysiac answered 3/8, 2015 at 19:49 Comment(2)
I have played a little with the python sample codes i found on the youtube API page and also with a bit inspiration of your code. I wanted to have all results of a search keyword to be written in a text file. I am wondering however that the results written in the file are always less than the totalResults number. May be you can take a look at my code and see why this happens? I would really appreciate it. Here is my code: gist.github.com/amirteymuri/8b80ef813fa48c5a0703308041ec501dUlulant
My function is find_vids.Ululant
S
9

In the JSON data sent to us by youtube data.pageInfo.totalResults is just the original total number of videos. After some months or years this number may be decreased because of video deleting, banning ... Actually youtube gives us only currently playable videos. So we need to change the code to get the better one.
We shouldn’t use if(sum == data.pageInfo.toTalResults) as stop condition. Instead let’s use the standard if(typeof nextPageToken == ‘undefined’).
In the case when the current total number is less than the original one. If we use old coding then the last function call is made with undefined nextPageToken. This cause Youtube to wrongly give us the first JSON page again. In the results, we have some duplicated videos.
Please try my new coding (it looks like the coding given by mister user3053204)

/* new coding. Please replace and use your api3 key */

function start(){
    count = 0; 
    $('#area1').val('');
    getVids();
}
function getVids(PageToken){
pid = $('#searchtext1').val();
$.get(
    "https://www.googleapis.com/youtube/v3/playlistItems",{
    part : 'snippet', 
    maxResults : 50,
    playlistId : pid,
    pageToken : PageToken,
    key: 'AIz....................................zm4'
    },
    function(data){
          myPlan(data);
    }        
    );  
}
count = 0;
str = '';

 function myPlan(data){
  nextPageToken=data.nextPageToken;
  pageLen = data.items.length;
  count += parseInt(pageLen);
  for(i=0; i<pageLen; i++){
           str += '"' + data.items[i].snippet.resourceId.videoId + '", ';
  }
   if(typeof nextPageToken == 'undefined'){
          total = data.pageInfo.totalResults;
          $('#all').html(count + '/' + total + ' videos');
          ind = str.lastIndexOf(',');
          str1 = str.substring(0, ind);
          $('#area1').val('arr = [' + str1 + '];\n');
          return;      
      }else{
          getVids(nextPageToken);
      }
 }

 <input type="text"  value="PLTI6yRvQqlYq9KoU-NHu43uDmKON7Fsjv" 
  id="searchtext1" size="75">&nbsp;
 <button onclick="start()">Get Items</button>
 <br><br>
 IDs for test: <br>
 <br>
 Ricky King playlist (92/103 videos):<br>
 PLTI6yRvQqlYq9KoU-NHu43uDmKON7Fsjv<br>
 Franck Pourcel playlist (425/425 videos):<br>
 PLMGmDo5xNOgU7gerHMwEk6SmD_vbPyLe9<br>
 Lobo playlist (25/41vids):<br>
 PLFE095732AC64AD06
 <br><br>         
 TOTAL:&nbsp;<span id="all"></span><br>
 <textarea id="area1" style="width:600px;height:500px;;font-size:12pt"></textarea>

/* old coding - to be cleared */

sum = 0;
sumN = 1;
var nextPageToken;

function getVids(PageToken){
    pid = $('#searchtext1').val();
    $.get(
        "https://www.googleapis.com/youtube/v3/playlistItems",{
        part : 'snippet', 
        maxResults : 50,
        playlistId : pid,
        pageToken : PageToken,
        key: 'YOUR API3 KEY'
        },
        function(data){
              myPlan(data);
        }        
    );  
 }

  function myPlan(data){
      total = data.pageInfo.totalResults;
      nextPageToken=data.nextPageToken;
      for(i=0;i<data.items.length;i++){
          document.getElementById('area1').value +=  
          sumN + '-' + data.items[i].snippet.title+'\n'+
          data.items[i].snippet.resourceId.videoId +'\n\n';
          sum++ ; sumN++;
          if(sum == (total-1) ){              
              sum = 0;  
              return;      
          }
      }  
      if(sum <(total-1)){
          getVids(nextPageToken);
      }    
 }
 
 function init(){
    $('#area1').val('');
 }
<!- - old coding - to be cleared - ->
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
  
  <body onload="$('#area1').val('')">
    
  <input type="text"  value="PLTI6yRvQqlYq9KoU-NHu43uDmKON7Fsjv" 
  id="searchtext1" size="75">&nbsp;
  <button onclick="getVids()">Get Items</button>
  <br><br>
  IDs for test: <br>PLTI6yRvQqlYq9KoU-NHu43uDmKON7Fsjv<br>
  PL32C69B40337EF920
  <br><br>         
  <textarea id="area1" style="width:600px;height:500px">
  </textarea>
Suggestible answered 24/11, 2015 at 20:32 Comment(2)
I can see where you get your key and playlist ID (pid), but where does "PLTI6yRvQqlYq9KoU-NHu43uDmKON7Fsjv" come from? This is not a user ID, playlist ID, key, or other factor which would seem to be case-specific as I have extracted the code and got it working, though I cannot find out what this meansWelker
Sorry for the late reply. Recently I only use the iPad and use the YouTube app. 1. In youtube, find PLTI6yRvQqlYq9KoU-NHu43uDmKON7Fsjv. You will see only one result, which is Ricky King instrumental 103 videos. 2. Click on the thumbnail to play this playlist. 3. If you see an icon in the form of a curved arrow, click it and select Copy Link, there will be: youtube.com/watch?v=J0WKl7NaiHg&list=PLTI6yRvQqlYq9KoU-NHu43uDmKON7FsjvSuggestible
Z
3

The easiest way to get all the videos,

DEVELOPER_KEY = "REPLACE_ME" YOUTUBE_API_SERVICE_NAME = "youtube" YOUTUBE_API_VERSION = "v3"

youtube = build("youtube", "v3", developerKey=api_key)
def get_videos_from_playlist(youtube, items, playlistID):
    response = items.list(part="snippet", playlistId=playlistID)
    while response:
        playlistitems_list_response = response.execute()

        for playlist_item in playlistitems_list_response["items"]:
            # title = playlist_item["snippet"]["title"]
            video_id = playlist_item["snippet"]["resourceId"]["videoId"]
            yield video_id

        response = youtube.playlistItems().list_next(
        response, playlistitems_list_response)

Pass the playlist id,

items = youtube.playlistItems()
playlist = get_videos_from_playlist(youtube, items, 'PLoROMvodv4rOhcuXMZkNm7j3fVwBBY42z')

and then parse through the list:

for videoID in playlist:
    print(videoID)

additionally, you can use pages to scrape through multiple pages use something like:

nextPageToken = res.get('nextPageToken')
    while ('nextPageToken' in res):
        nextPage = youtube.playlistItems().list(
        part="snippet",
        playlistId=playlistId,
        maxResults="50",
        pageToken=nextPageToken
        ).execute()
        res['items'] = res['items'] + nextPage['items']

        if 'nextPageToken' not in nextPage:
            res.pop('nextPageToken', None)
        else:
            nextPageToken = nextPage['nextPageToken']
Zulmazulu answered 3/12, 2019 at 14:18 Comment(0)
J
0

Another solution, using recursion:

$.fn.loadYoutubeResource = function(resource_request, resource_type, resource_id, resource_container, pageToken = null, callback = null){
    $.ajax({
            url: "https://www.googleapis.com/youtube/v3/" + resource_request,
            type: 'get',
            dataType: 'json',
            data: {
                    part : 'snippet', 
                    [resource_type]: resource_id,
                    maxResults : 50,
                    pageToken: pageToken,
                    key: '< API Key >', 
                  },
            success:    function(data) {
                                console.log("New resource " + resource_type + " loaded:");
                                console.log(data);                                          
                                for(var index = 0; index < data.items.length; index++){                                         
                                    var url = data.items[index]['snippet'].thumbnails.default.url;
                                    var ytb_id = data.items[index]['id'];   
                                    jQuery('#' + resource_container).append('<img class="tube_thumbs" src="' + url + '" id="' + ytb_id 
                                                                        + '" title="' + data.items[index]['snippet']['title'] + '" >');
                                    }
                                if ( data.nextPageToken == null)
                                    return callback();
                                $.fn.loadYoutubeResource(resource_request, resource_type, resource_id, resource_container, data.nextPageToken, callback);                   
                        }
            });     
        }        

And then call it as follows:

jQuery('body').append('<div id="ytb_container"></div>');

$.fn.loadYoutubeResource('playlistItems', 'playlistId', 'PLmwK57OwOvYVdedKc_vPPfbcsey_R0K8r', 'ytb_container', null, function(){ <callback code>});
Jerz answered 5/12, 2016 at 3:36 Comment(0)
R
0

here is my recursive function, maybe can help somebody:

First at all I created a button for the first call:

<button id="aux" class="btn btn-danger">Click Me</button>    

Then in script section:

   $(document).ready(function () {

        function getVideos(t) {
            var url = "https://www.googleapis.com/youtube/v3/search?part=snippet&key=YourAPIKey&channelId=YourChannelID&maxResults=50";
            if (t != undefined) {
                url = url + "&pageToken=" + t
            }
            $.ajax({
                type: 'GET',
                url: url,
                dataType: 'json',
                success: function (html) {
                    console.log(html.items);
                    if (html.nextPageToken != undefined) {
                        getVideos(html.nextPageToken);
                    }
                }
            });
        };

        //initial call
        $("#aux").click(function () {
            getVideos();
        });
 });

Regards

Rags answered 3/8, 2018 at 11:17 Comment(0)
S
0

Another ways (no need of request format knowing and having api key): just use json loacated inside youtube playlist html file and use JSON.parse method
Unfortunate, this method can’t give more then 200 videos. In json I see some key codes, maybe for continuation, but can’t use them.
For getting html source code we can use jquery $.ajax method.

<meta charset = utf-8>
<body>
<div id="help" style="width:90%">
1- Open youtube.com and search for playlist   (http://www.youtube.com/....&list=...)<br>
For example: click <a href="http://www.youtube.com/watch?v=sMyj9e2qOc0&list=PL33196EF7664597D5">paul mauriat playlist</a><br>
You will see in the adress bar: http://www.youtube.com/watch?v=sMyj9e2qOc0&list=PL33196EF7664597D5 <br>
Select all and copy this url.<br>
2- Open any online html source code  viewer. For example<br>
<a href="https://www.duplichecker.com/page-snooper.php">
https://www.duplichecker.com/page-snooper.php</a><br>
Paste the url, click "Enter", wait several seconds, scroll down, click   "Copy"<br>
3- Return to this page. Paste the code to the below input smal textarea, wait several seconds, click "GET VIDEO IDS".<br>
4- Click the button TEST JAVASCRIPT.
</div><br>
<textarea id = "input">
</textarea><br>
<button onclick="extract()">GET VIDEOS IDS</button><br>
Total:&nbsp;<span id='len'></span>
<br><button onclick="test()">TEST JAVASCRIPT</button><br>
COPY THIS TO CREATE A JAVASCRIPT FILE<br>
<textarea id="area2" style="width:90%;height:400px;font-size:14pt">
</textarea><br>

<script> 
function extract(){
str = document.getElementById('input').value;
aa = str.indexOf('{"responseContext');
bb = str.indexOf('{"related', aa);
jsn = str.substring(aa, bb + 24);
obje = JSON.parse(jsn);
alert('Click OK to continue');
make();
}
glStr = '';
function make(){
len = obje.contents.singleColumnWatchNextResults.playlist.playlist.contents.length;
ss = '';
for(i=0; i < len; i++){
try{
   ti = obje.contents.singleColumnWatchNextResults.playlist.playlist.contents[i].playlistPanelVideoRenderer.title.runs[0].text;
   ti1 = ti.replace(/"/g,'\\"');
   ide = obje.contents.singleColumnWatchNextResults.playlist.playlist.contents[i].playlistPanelVideoRenderer.navigationEndpoint.watchEndpoint.videoId;
    }catch(e){
                ide = obje.contents.singleColumnWatchNextResults.playlist.playlist.contents[i].playlistPanelVideoRenderer.videoId;
                ti1 = '[Deleted Video]';
}
    ss += '{vid:"' + ide + '",tit:"' + ti1 + '"}';
    if(i != (len - 1)){
        ss += ',\n';
    }
} 
glStr = 'obj = \n[' + ss + '\n];\n';
document.getElementById('area2').value = glStr;
document.getElementById('len').innerHTML = len + ' videos';
}
function test(){
var head = document.getElementsByTagName('head').item(0);
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.innerHTML = glStr;
head.appendChild(script);
 alert('obj.length = ' + obj.length);
 alert('obj[5].vid = ' + obj[5].vid + '\n obj[5].tit = ' +   obj[5].tit);
}
</script>
</body>
Suggestible answered 22/4, 2020 at 8:28 Comment(0)
H
0

I did as follows, but i don't know this one is optimized or not any how i got the results as i expected.

Explanation: Will retrieve all videos from the playlist and push into an Array dynamically.

In Service:

    getSnippets(token): any {
    console.log('API_TOKEN:',token);
    if(token){
      return this.http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=PLV_aspERmuCKxUPxu8UwUd3I52VLje0ra&maxResults=100&key=[API_KEY]='+token).toPromise();
    }else{
      return this.http.get('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=PLV_aspERmuCKxUPxu8UwUd3I52VLje0ra&maxResults=100&key=[API_KEY]').toPromise();
    }
  }

To display data:

      async getPlayList(){
    try{
      let pageToken;
      this.finalAr = [];
      // for(let t = 0; t <= 1; t++) {
        const list = await this.service.getSnippets(pageToken);
        pageToken          = list.nextPageToken;
        // let pageInfo       = list.pageInfo;
        let pageTot        = list.pageInfo.totalResults;
        let resultsPerPage = list.pageInfo.resultsPerPage;
        let loopCnt        = pageTot / resultsPerPage;
        let finalCnt       = Math.abs(Math.ceil(loopCnt)) - 1 ;
        if(pageToken != undefined || pageToken != null){
          let tempAr   = list.items;        
          for(let i = 0; i < tempAr.length; i++){
            this.finalAr.push({"vid_id"   : tempAr[i].snippet.resourceId.videoId,
                               "vid_title": tempAr[i].snippet.title,
                               "vid_desc" : tempAr[i].snippet.description,
                               "vid_icon" : 'https://i.ytimg.com/vi/'+tempAr[i].snippet.resourceId.videoId+'/sddefault.jpg'
                              })
          }
          console.log('finalAr_1:',this.finalAr);
        }
        for(let a = 1; a <= finalCnt; a++){
          const listF = await this.service.getSnippets(pageToken);
            pageToken = listF.nextPageToken;
            let tempAr   = listF.items;      
            for(let i = 0; i < tempAr.length; i++){
              this.finalAr.push({"vid_id"   : tempAr[i].snippet.resourceId.videoId,
                                 "vid_title": tempAr[i].snippet.title,
                                 "vid_desc" : tempAr[i].snippet.description,
                                 "vid_icon" : 'https://i.ytimg.com/vi/'+tempAr[i].snippet.resourceId.videoId+'/sddefault.jpg'
                                })
            }
            console.log('finalAr_2:',this.finalAr);
        }
    }catch (e){
      console.log('ER:',e);
    }

Did the job. But i want to retrieve all videos from multiple playlists if anyone came to know about this let me know.

Heavyhearted answered 30/9, 2020 at 8:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.