It might look like the search
API is a good idea to retrieve all the videos by a single loop, but apparently not. If a channel has thousands (more than 1600) of videos, search
will not return all of them: few last result pages will be empty, number of results will be wrong, and the amount of given pages will be around only 20 pages.
So, if you need to get all IDs via API, then it's better to use at first channels
API to get an "uploads" playlist ID, and then use it in playlistItems
API to retrieve all videos.
First request URL will look like this (using https://www.googleapis.com/youtube/v3/ in the beginning, of course):
channels?part=contentDetails&id=CHANNEL_ID&key=YOUR_TOKEN
Result:
{
"kind": "youtube#channelListResponse",
"etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/Nza6t_W5qltBCnHIHKgNiSRu0bE\"",
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 1
},
"items": [
{
"kind": "youtube#channel",
"etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/95y8HKrtWV3t4apHu0KjgoaNbc0\"",
"id": "UC9-y-6csu5WGm29I7JiwpnA",
"contentDetails": {
"relatedPlaylists": {
"likes": "LL9-y-6csu5WGm29I7JiwpnA",
"favorites": "FL9-y-6csu5WGm29I7JiwpnA",
"uploads": "UU9-y-6csu5WGm29I7JiwpnA",
"watchHistory": "HL",
"watchLater": "WL"
}
}
}
]
}
Or if you don't need tons of bytes, use filter fields like this:
channels?fields=items(contentDetails(relatedPlaylists(uploads)))&part=contentDetails&id=CHANNEL_ID&key=YOUR_TOKEN
Filtered result:
{
"items": [
{
"contentDetails": {
"relatedPlaylists": {
"uploads": "UU9-y-6csu5WGm29I7JiwpnA"
}
}
}
]
}
Next step is to get list of all pages with videos:
playlistItems?maxResults=50&playlistId=PLAYLIST_ID&part=snippet&key=YOUR_TOKEN
Result (shorten by 1st result of array in items
key):
{
"kind": "youtube#playlistItemListResponse",
"etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/GmoHN7IVzBjFEtB0547SRegTL9c\"",
"nextPageToken": "CDIQAA",
"pageInfo": {
"totalResults": 399,
"resultsPerPage": 50
},
"items": [
{
"kind": "youtube#playlistItem",
"etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/5gxLp2iP0FwcZQWb98LCOGu0TfA\"",
"id": "VVU5LXktNmNzdTVXR20yOUk3Sml3cG5BLjlua3RyMU1nUy1B",
"snippet": {
"publishedAt": "2017-08-03T11:27:38.000Z",
"channelId": "UC9-y-6csu5WGm29I7JiwpnA",
"title": "Stop Button Solution? - Computerphile",
"description": "After seemingly insurmountable issues with Artificial General Intelligence, Rob Miles takes a look at a promising solution.\n\nConcrete Problems in AI Safety: blah blah blah blah blah blah blah blah blah",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/9nktr1MgS-A/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/9nktr1MgS-A/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/9nktr1MgS-A/hqdefault.jpg",
"width": 480,
"height": 360
},
"standard": {
"url": "https://i.ytimg.com/vi/9nktr1MgS-A/sddefault.jpg",
"width": 640,
"height": 480
},
"maxres": {
"url": "https://i.ytimg.com/vi/9nktr1MgS-A/maxresdefault.jpg",
"width": 1280,
"height": 720
}
},
"channelTitle": "Computerphile",
"playlistId": "UU9-y-6csu5WGm29I7JiwpnA",
"position": 0,
"resourceId": {
"kind": "youtube#video",
"videoId": "9nktr1MgS-A"
}
}
},
{
...
}
]
}
Or the filtered one to get only IDs of the videos (and next page tokens):
playlistItems?fields=nextPageToken,items(snippet(resourceId(videoId)))&maxResults=50&playlistId=PLAYLIST_ID&part=snippet&key=YOUR_TOKEN
Result:
{
"nextPageToken": "CDIQAA",
"items": [
{
"snippet": {
"resourceId": {
"videoId": "9nktr1MgS-A"
}
}
}
]
}
You can retrieve next pages by using nextPageToken
key value, adding it to GET parameters with pageToken
key:
(I took a token from the result above just for example, it could be different for your request)
playlistItems?fields=nextPageToken,items(snippet(resourceId(videoId)))&maxResults=50&part=snippet&playlistId=PLAYLIST_ID&key=YOUR_TOKEN&pageToken=CDIQAA
On the last page there will be no nextPageToken
key.