javascriptjqueryyoutube-apiyoutube-data-apiyoutube-javascript-api

Get all video IDs of a YouTube playlist through GET requests


I'm trying to load all video IDs of a YouTube playlist and save them in an array in order to access them later.

I started with this:

$.getJSON( "https://www.googleapis.com/youtube/v3/playlistItems", {
  part : 'snippet', 
  playlistId : inputId,
  key: API_KEY
}, function(data) {
  $.each(data.items, function(i, item) {
    var itemId = item.snippet.resourceId.videoId;
    videoIds.push(itemId);
  }
);

Then I noticed only the first 5 video IDs of the input playlist have been saved in my array 'videoIds'. Apparantly, the YouTube API uses pages to limit the amount of items in a GET response. I didn't see a way to increase the amount of items per request. So instead I updated my code by using the response keys 'resultsPerPage', 'totalResults' and 'nextPageToken'. Basically, I now send one GET request for every page of the playlist:

$.getJSON("https://www.googleapis.com/youtube/v3/playlistItems", {
  part : 'snippet', 
  playlistId : inputId,
  key: API_KEY
}, function(data) {
  resultsPerPage = data.pageInfo.resultsPerPage;
  nextPageToken = data.nextPageToken;
  totalResults = data.pageInfo.totalResults;
  $.each(data.items, function(i, item) {
    var itemId = item.snippet.resourceId.videoId;
    videoIds.push(itemId);
  });

  // if playlist items don't fit on a single page
  if (resultsPerPage < totalResults) {
    for (var i = 0; i < totalResults/resultsPerPage; i++) {
      // send the request again...
      $.getJSON("https://www.googleapis.com/youtube/v3/playlistItems", {
        part: 'snippet', 
        playlistId: inputId,
        // but this time, with a pageToken
        pageToken: nextPageToken,
        key: API_KEY
      }, function(data) {
        // debug logging  
        console.log("old token:" + nextPageToken);
        console.log("new token:" + data.nextPageToken);
        // update the nextPageToken for the next iteration
        nextPageToken = data.nextPageToken;
        $.each(data.items, function(i, item) {
          var itemId = item.snippet.resourceId.videoId;
          videoIds.push(itemId);
        });
      });
    }
  }
});

My problem: the value of 'nextPageToken' never changes. This is what my console looks like after I run my code:

old token:CAUQAA script.js:62 
new token:CAoQAA script.js:63
old token:CAoQAA script.js:62
new token:CAoQAA script.js:63
old token:CAoQAA script.js:62
new token:CAoQAA script.js:63
old token:CAoQAA script.js:62
new token:CAoQAA script.js:63

Why is the value of nextPageToken in a GET response the same String as the value I used for pageToken in the correlating GET request? Is there an easier way to get all IDs of a playlist?


Solution

  • YouTube Data API's Videos.list API endpoint returns maximum 50 items per page:

    maxResults (unsigned integer)

    The maxResults parameter specifies the maximum number of items that should be returned in the result set.

    Note: This parameter is supported for use in conjunction with the myRating parameter, but it is not supported for use in conjunction with the id parameter. Acceptable values are 1 to 50, inclusive. The default value is 5.

    The way nextPageToken works is like this:

    Situation:

    You're trying to retrieve a list of 200 videos but YouTube can only return 50 results per pagination.

    1. After a successful first request, YouTube gives you the first 50 videos, so only 150 left. With this first 50 lists of videos comes a nextPageToken, which you can use to retrieve the next 51-100.

    2. So you pass this nextPageToken value to the pageToken property and perform another request, which results in YouTube Data API giving you the next 51-100 videos, so only 100 left. With this 51-100 videos comes a new nextPageToken again which will be used to retrieve the next 101-150 videos. Rinse and repeat.

    This will be easier with an actual demo on how to do this so watch this tutorial.

    Test it on Google API Explorer youtube.search.list.