I came across the API reference document regarding the Search API:
Note: Search results are constrained to a maximum of 500 videos if your request specifies a value for the
channelId
parameter and sets thetype
parameter value tovideo
, [...].
Do I have to apply for paid account to break the 500 videos limit? If yes, how do I apply?
If you need to obtain the list of all videos of a given channel -- identified by its ID, say CHANNEL_ID
--, then you have to proceed as follows:
Step 1: Query the Channels.list
API endpoint with parameter id=CHANNEL_ID
for to obtain from the API the ID of that channel's uploads playlist:
response = youtube.channels().list(
id = CHANNEL_ID,
part = 'contentDetails',
fields = 'items(contentDetails(relatedPlaylists(uploads)))',
maxResults = 1
).execute()
uploads_id = response \
['contentDetails'] \
['relatedPlaylists'] \
['uploads']
The code above should run only once for obtaining the uploads playlist ID as uploads_id
, then that ID should be used as many times as needed.
Usually, a channel ID and its corresponding uploads playlist ID are related by s/^UC([0-9a-zA-Z_-]{22})$/UU\1/
.
Step 2: Using the previously obtained uploads playlist ID -- let's name it UPLOADS_ID
--, query the PlaylistItems.list
API endpoint for to obtain the list of all video ID's of that playlist:
is_video = lambda item: \
item['snippet']['resourceId']['kind'] == 'youtube#video'
video_id = lambda item: \
item['snippet']['resourceId']['videoId']
request = youtube.playlistItems().list(
playlistId = UPLOADS_ID,
part = 'snippet',
fields = 'nextPageToken,items(snippet(resourceId))',
maxResults = 50
)
videos = []
while request:
response = request.execute()
items = response.get('items', [])
videos.extend(map(video_id, filter(is_video, items)))
request = youtube.playlistItems().list_next(
request, response)
Upon running the code above, the list videos
will contain the IDs of all videos that were uploaded on the channel identified by CHANNEL_ID
.
Step 3: Query the Videos.list
API endpoint for to obtain the statistics
info (i.e. object) of each of the videos you're interested in:
class Stat:
def __init__(video_id, view_count, like_count):
self.video_id = video_id
self.view_count = view_count
self.like_count = like_count
stats = []
while len(videos):
ids = videos[0:50]
del videos[0:50]
response = youtube.videos().list(
id = ','.join(ids),
part = 'id,statistics',
fields = 'items(id,statistics)',
maxResults = len(ids)
).execute()
items = response['items']
assert len(items) == len(ids)
for item in items:
stat = item['statistics']
stats.append(
Stat(
video_id = item['id'],
view_count = stat['viewCount'],
like_count = stat['likeCount']
)
)
Note that code above, in case the list videos
has length N
, reduces the number of calls to Videos.list
from N
to math.floor(N / 50) + (1 if N % 50 else 0)
. That's because the parameter id
of Videos.list
endpoint can be specified as a comma-separated list of video IDs (the number of IDs in one such list can be maximum 50).
Note also that each piece of code above uses the fields
request parameter for to obtain from the invoked API endpoints only the info that is of actual use.
I must also mention that according to YouTube's staff, there's an upper 20000 limit set by design for the number of items returned via PlaylistItems.list
endpoint. This is unfortunate, but a fact.