What is the maximum HTTP GET request length for a YouTube API? - youtube-api

I want to use youtube video:list api to get details of multiple videos in single request. As per the api documentation, I can send comma separated videoId list as id parameter. But what is the maximum length possible?
I know the GET request limit is dependent on both the server and the client. In my case I am making the request from server-side and not from browser. Hence the maximum length could be configured on my end. But what is the maximum length acceptable for youtube?
UPDATE: Though official documentation couldn't find, current limit is 50 ids from the tests performed as explained by Tempus. I am adding a code below with 51 different video ids (1 is commented) for those who want to check this in future.
var key = prompt("Please enter your key here");
if (!key) {
alert("No key entered");
} else {
var videoIds = ["RgKAFK5djSk",
"fRh_vgS2dFE",
"OPf0YbXqDm0",
"KYniUCGPGLs",
"e-ORhEE9VVg",
"nfWlot6h_JM",
"NUsoVlDFqZg",
"YqeW9_5kURI",
"YQHsXMglC9A",
"CevxZvSJLk8",
"09R8_2nJtjg",
"HP-MbfHFUqs",
"7PCkvCPvDXk",
"0KSOMA3QBU0",
"hT_nvWreIhg",
"kffacxfA7G4",
"DK_0jXPuIr0",
"2vjPBrBU-TM",
"lp-EO5I60KA",
"5GL9JoH4Sws",
"kOkQ4T5WO9E",
"AJtDXIazrMo",
"RBumgq5yVrA",
"pRpeEdMmmQ0",
"YBHQbu5rbdQ",
"PT2_F-1esPk",
"uelHwf8o7_U",
"KQ6zr6kCPj8",
"IcrbM1l_BoI",
"vjW8wmF5VWc",
"PIh2xe4jnpk",
"QFs3PIZb3js",
"TapXs54Ah3E",
"uxpDa-c-4Mc",
"oyEuk8j8imI",
"ebXbLfLACGM",
"kHSFpGBFGHY",
"CGyEd0aKWZE",
"rYEDA3JcQqw",
"fLexgOxsZu0",
"450p7goxZqg",
"ASO_zypdnsQ",
"t4H_Zoh7G5A",
"QK8mJJJvaes",
"QcIy9NiNbmo",
"yzTuBuRdAyA",
"L0MK7qz13bU",
"uO59tfQ2TbA",
"kkx-7fsiWgg",
"EgqUJOudrcM",
// "60ItHLz5WEA" // 51st VideoID. Uncomment it to see error
];
var url = "https://www.googleapis.com/youtube/v3/videos?part=statistics&key=" + key + "&id=" + videoIds.join(",");
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
(xmlHttp.readyState == 4) && alert("HTTP Status code: " + xmlHttp.status);
}
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}

The answer is 50. Reason being, is that is all you will get back.
As some calls can have quite a few results depending on search criteria and available results, they have capped the "maxResults" at 50.
Acception to this is the CommentThreads which are up to 100.
This is (as you can work out) to speed page loads and call times.
EDIT:
This can be tested out HERE in the "Try api" part.
You will need to put 50 videoID's into the "id" field separated by coma's.
Then ad one more ID to get 51 and test again. You should receive a "400" response.
P.S. they do not need to be unique ID's. So have a few and then copy and paste as many times as needed ;-)

Related

Instagram Graph API Recent Search result returns blank data

thank you for reviewing my question.
I've been using Instagram Graph API to make some hashtag recent search.
# Retrieve Keys
key = json.loads(keycontent)
HASHTAG_ID = key['HASHTAG_ID']
USER_ID = key['USER_ID']
ACCESS_TOKEN = key['ACCESS_TOKEN']
CURSOR = key['CURSOR']
topic = 'HASHTAG_ID' # Job
# Get Request URL
url = f"https://graph.facebook.com/{HASHTAG_ID}/recent_media?fields=id,permalink,caption,media_url&limit=50&user_id={USER_ID}&access_token={ACCESS_TOKEN}"
if CURSOR != "":
url = url + '&after=' + CURSOR
res = requests.get(url)
print(res.json()[‘data’])
It works quite successfully, but problem turns out that it starts to return blank data after calling the function several times. The data I am receiving at the moment are equal to either of the followings:
{"data": []}
{
"data": [
],
"paging": {
"cursors": {
"after": "NEXT_CURSOR"
},
"next": "LINK_WITH_NEXT_CURSOR"
}
}
I've checked several known issues, and the list of what I've checked are stated below.
It is not the permission issue. I've checked all the permissions related, and it is confirmed that the app has all permission it needs.
The app is certainly below the execution limit. Actually, it is mostly even below half of it.
The app is also below the number of hashtags I can search. I've called significantly lower than 30 hashtags within 7 days.
So, I'd like to know if there are potential reasons that I am having blank data for Instagram Graph API call.
Thank you in advance.

How to avoid omissions in video information acquisition when using the YouTube Data API?

Assumption / What I want to achieve
I want to use YouTube Data API V3 to get the video ID without any omissions, and find out if the cause of the trouble is in the code or in the video settings of YouTube (API side).
Problem
The following code is used to get the video information from YouTube Data API, but the number of IDs I got did not match the number of videos that are actually posted.
from apiclient.discovery
import build
id = "UCD-miitqNY3nyukJ4Fnf4_A" #sampleID
token_check = None
nextPageToken = None
id_info = []
while True:
if token_check != None:
nextPageToken = token_check
Search_Video = youtube.search().list(
part = "id",
channelId = id,
maxResults = 50,
order = 'date',
safeSearch = "none",
pageToken = nextPageToken
).execute()
for ID_check in Search_Video.get("items", []):
if ID_check["id"]["kind"] == "youtube#video":
id_info.append(ID_check["id"]["videoId"])
try:
token_check = Search_Video["nextPageToken"]
except:
print(len(id_info)) #check number of IDs
break
I also used the YouTube Data API function to get the videoCount information of the channel, and noticed that the value of videoCount did not match the number of IDs obtained by the code above, which is why I posted this.
According to channels() API, this channel have 440 videos, but the above code gets only 412 videos (at 10:30 a.m. JST).
Supplemental Information
・Python 3.9.0
・YouTube Data API v3
You have to acknowledge that the Search.list API endpoint does not have a crisp behavior. That means you should not expect precise results from it. Google does not document this behavior as such, but this forum has many posts from users experiencing that.
If you want to obtain all the IDs of videos uploaded by a given channel then you should employ the following two-step procedure:
Step 1: Obtain the ID of the Uploads Playlist of a Channel.
Invoke the Channels.list API endpoint, queried with its request parameter id set to the ID of the channel of your interest (or, otherwise, with its request parameter mine set to true) for to obtain that channel's uploads playlist ID, contentDetails.relatedPlaylists.uploads.
def get_channel_uploads_playlist_id(youtube, channel_id):
response = youtube.channels().list(
fields = 'items/contentDetails/relatedPlaylists/uploads',
part = 'contentDetails',
id = channel_id,
maxResults = 1
).execute()
items = response.get('items')
if items:
return items[0] \
['contentDetails'] \
['relatedPlaylists'] \
.get('uploads')
else:
return None
Do note that the function get_channel_uploads_playlist_id should only be called once for to obtain the uploads playlist
ID of a given channel; subsequently use that ID as many times as needed.
Step 2: Retrieve All IDs of Videos of a Playlist.
Invoke the PlaylistItems.list API endpoint, queried with its request parameter playlistId set to the ID obtained from get_channel_uploads_playlist_id:
def get_playlist_video_ids(youtube, playlist_id):
request = youtube.playlistItems().list(
fields = 'nextPageToken,items/snippet/resourceId',
playlistId = playlist_id,
part = 'snippet',
maxResults = 50
)
videos = []
is_video = lambda item: \
item['snippet']['resourceId']['kind'] == 'youtube#video'
video_id = lambda item: \
item['snippet']['resourceId']['videoId']
while request:
response = request.execute()
items = response.get('items', [])
assert len(items) <= 50
videos.extend(map(video_id, filter(is_video, items)))
request = youtube.playlistItems().list_next(
request, response)
return videos
Do note that, when using the Google's APIs Client Library for Python (as you do), API result set pagination is trivially simple: just use the list_next method of the Python API object corresponding to the respective paginated API endpoint (as was shown above):
request = API_OBJECT.list(...)
while request:
response = request.execute()
...
request = API_OBJECT.list_next(
request, response)
Also note that above I used twice the fields request parameter. This is good practice: ask from the API only the info that is of actual use.
Yet an important note: the PlaylistItems.list endpoint would not return items that correspond to private videos of a channel when invoked with an API key. This happens when your youtube object was constructed by calling the function apiclient.discovery.build upon passing to it the parameter developerKey.
PlaylistItems.list returns items corresponding to private videos only to the channel owner. This happens when the youtube object is constructed by calling the function apiclient.discovery.build upon passing to it the parameter credentials and if credentials refer to the channel that owns the respective playlist.
An additional important note: according to Google staff, there's an upper 20000 limit set by design for the number of items returned via PlaylistItems.list endpoint when queried for a given channel's uploads playlist. This is unfortunate, but a fact.

How to retrieve Slack messages via API identified by permalink?

I'm trying to retrieve a list of Slack reminders, which works fine using Slack API's reminders.list method. However, reminders that are set using SlackBot (i.e. by asking Slackbot to remind me of a message) return the respective permalink of that message as text:
{
"ok": true,
"reminders": [
{
"id": "Rm012C299C1E",
"creator": "UV09YANLX",
"text": "https:\/\/team.slack.com\/archives\/DUNB811AM\/p1583441290000300",
"user": "UV09YANLX",
"recurring": false,
"time": 1586789303,
"complete_ts": 0
},
Instead of showing the permalink, I'd naturally like to show the message I wanted to be reminded of. However, I couldn't find any hints in the Slack API docs on how to retrieve a message identified by a permalink. The link is presumably generated by chat.getPermalink, but there seems to be no obvious chat.getMessageByPermalink or so.
I tried to interpet the path elements as channel and timestamp, but the timestamp (transformed from the example above: 1583441290.000300) doesn't seem to really match. At least I don't end up with the message I expected to retrieve when passing this as latest to conversations.history and limiting to 1.
After fiddling a while longer, here's how I finally managed in JS:
async function downloadSlackMsgByPermalink(permalink) {
const pathElements = permalink.substring(8).split('/');
const channel = pathElements[2];
var url;
if (permalink.includes('thread_ts')) {
// Threaded message, use conversations.replies endpoint
var ts = pathElements[3].substring(0, pathElements[3].indexOf('?'));
ts = ts.substring(0, ts.length-6) + '.' + ts.substring(ts.length-6);
var latest = pathElements[3].substring(pathElements[3].indexOf('thread_ts=')+10);
if (latest.indexOf('&') != -1) latest = latest.substring(0, latest.indexOf('&'));
url = `https://slack.com/api/conversations.replies?token=${encodeURIComponent(slackAccessToken)}&channel=${channel}&ts=${ts}&latest=${latest}&inclusive=true&limit=1`;
} else {
// Non-threaded message, use conversations.history endpoint
var latest = pathElements[3].substring(1);
if (latest.indexOf('?') != -1) latest = latest.substring(0, latest.indexOf('?'));
latest = latest.substring(0, latest.length-6) + '.' + latest.substring(latest.length-6);
url = `https://slack.com/api/conversations.history?token=${encodeURIComponent(slackAccessToken)}&channel=${channel}&latest=${latest}&inclusive=true&limit=1`;
}
const response = await fetch(url);
const result = await response.json();
if (result.ok === true) {
return result.messages[0];
}
}
It's not been tested to the latest extend, but first results look alright:
The trick with the conversations.history endpoint was to include the inclusive=true parameter
Messages might be threaded - the separate endpoint conversations.replies is required to fetch those
As the Slack API docs state: ts and thread_ts look like timestamps, but they aren't. Using them a bit like timestamps (i.e. cutting off some characters at the back and inserting a dot) seems to work, gladly, however.
Naturally, the slackAccessToken variable needs to be set beforehand
I'm aware the way to extract & transform the URL components in the code above might not the most elegant solution, but it proves the concept :-)

youtube data api v3 php search pagination?

i am trying with youtube api v3 php search...
first time i'm using this api for this i am beginner...
i have 3 question;
1) how can below search list showing pagination numbers? (per page 50 result)
2) how can video duration show in list? (3:20 min:second)
3) how can order viewCount
if ($_GET['q']) {
require_once 'src/Google_Client.php';
require_once 'src/contrib/Google_YoutubeService.php';
$DEVELOPER_KEY = 'my key';
$client = new Google_Client();
$client->setDeveloperKey($DEVELOPER_KEY);
$youtube = new Google_YoutubeService($client);
try {
$searchResponse = $youtube->search->listSearch('id,snippet', array(
'q' => $_GET['q'],
'maxResults' => 50,
'type' => "video",
));
foreach ($searchResponse['items'] as $searchResult) {
$videos .= '<li style="clear:left"><img src="'.$searchResult['snippet']['thumbnails']['default']['url'].'" style="float:left; margin-right:18px" alt="" /><span style="float:left">'.$searchResult['snippet']['title'].'<br />'.$searchResult['id']['videoId'].'<br />'.$searchResult['snippet']['publishedAt'].'<br />'.$item['contentDetails']['duration'].'</span></li>';
}
$htmlBody .= <<<END
<ul>$videos</ul>
END;
} catch (Google_ServiceException $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
}
1) how can below search list showing pagination numbers? (per page 50 result)
You need to write your own cacheing logic to implement this feature because with every result you get two tokens "NextPageToken" and "PreviousPageToken" and subsequent query must contain that token number to get next page or previous page token like below.
So whenever results are not available at cache then you should send either nextpagetoken or previous page token.
https://www.googleapis.com/youtube/v3/search?key=API_KEY&part=snippet&q=japan&maxResults=10&order=date&pageToken=NEXT_or_PREVIOUS_PAGE_TOKEN
In particular your case where you need 50 pages per page and you are showing 3 pagination like (1,2,NEXT) then you need to fetch results two times. Both the results you will keep in cache so for page 1 and 2 results will be retrieved from cache. For next you make it sure that you are making query google again by sending nextPageToken.
Thus to show pagination 1-n and every page 50 results then you need to make n-1 queries to google api. But if you are showing 10 results per page then you cane make single query of 50 results using which you can show first 5 pages (1-5) with the help of retrieved results and at next you should again send next page token like above.
NOTE- Google youtube api provide 50 results max.
2) how can video duration show in list? (3:20 min:second)
Youtube API v3 do not return video duration at simple first search response. To get video duration we need to make one extra call to youtube api like below.
https://www.googleapis.com/youtube/v3/videos?id=VIDEO_ID1%2CVIDEO_ID2&part=contentDetails&key=API_KEY (max 50 IDs)
This issue is highlighted in "http://code.google.com/p/gdata-issues/issues/detail?id=4294".I posted my answer here too.
Hence if we want to display video duration then we need to make two calls every time.
3) how can order viewCount
Trigger below query it will provide results ordered by view count.
https://www.googleapis.com/youtube/v3/search?key=KEY&part=snippet&q=japan&maxResults=5&order=viewCount
For detail please refer this - https://developers.google.com/youtube/v3/docs/search/list#order
The youTube API V3 is somehow complicated compare to API V2.
To the question above, my approach is not for search result rather is to retrieve user uploaded videos. I believe this can be useful
References
The way you create pagination in v3 is not the same as in v2 where you can make your call simply like
$youtube = "http://gdata.youtube.com/feeds/api/users/Qtube247/uploads?v=2&alt=jsonc&start-index=1&max-results=50";
In v3 you need to make two or three calls the first one will be to get the channel detail and second call will be to retrieve playlist from where we will get the channel playlist Id and finally retrieve individual video data.
I am using Php CURL
$youtube = “https://www.googleapis.com/youtube/v3/channels?part=snippet%2CcontentDetails%2Cstatistics&id=yourChannelIdgoeshere&key=yourApiKey”;
Here we retrieve user playlist ID
$result = json_decode($return, true);
$playlistId=$result['items'][0]['contentDetails']['relatedPlaylists']['uploads'];
we define pagetoken
$pageToken=’’;
Each time user click control button we retrieve pagetoken from session[] and feed the curl url, and in turn will produce nextpagetoken or prevpagetoken. Whatever you feed the url the Api know what set of list to populate.
if(isset($_REQUEST['ptk']) && $_REQUEST['ptk’]!==''){
$pageToken=$_REQUEST['ptk’];
}
Here we retrieve user playlist
$ playlistItems =”https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&pageToken=”.$pageToken.”&maxResults=50&playlistId=$playlistId&key= yourApiKey”;
If user has more than maxResult, we should have nextPageToken, take for an example user has 200 uploaded videos,the first pagetoken may be CDIQAA and next pagetoken may be CGQQAA while previous may be CDIQAQ , something like that so is not a number.
Here we save the pagetoken
if(isset($result['nextPageToken'])) { $_SESSION[nextToken]=$result['nextPageToken'];
}
if(isset($result['prevPageToken'])) { $_SESSION[prevToken]=$result['prevPageToken'];
}
we can then create our control button <>
$next=$_SESSION[nextToken];
$prev=$_SESSION[prevToken];
The control button here
<a href=”?ptk=<?php echo $prev?>” ><<prev</a>
<a href=”?ptk=<?php echo $next?>” >next>></a>
From here when user click link it set either next or prev page in session variable (go to up to see how this work)
To get video duration we use same Php curl
$videoDetails="https://www.googleapis.com/youtube/v3/videos?part=id,snippet,contentDetails,statistics,status&id=videoIdHere&key=yourApiKey";
$videoData = json_decode($return, true);
$duration = $videoData['items'][0]['contentDetails']['duration'];
$viewCount = $videoData['items'][0]['statistics']['viewCount'];
you may get something like this ('PT2H34M25S')
I have answer a question Here which show you how to convert the duration data
See Working Demo Here

Retrieving Data in a While Loop from the Youtube API

I do have a hughe database where some data sets link to certain youtube videos. As we all know some youtube videos disappear after a while from youtube and this leads to my solution and my problem as well --> I'd like to check if the youtube video still exists by simply checking via JSON if there is data to retrieve from a video. If not than I'd simply delete that certain data set.
So the first part of my solution would be to go through each row of my data table and checking for each id if there is data to retrieve from youtube as seen in the following code:
$result = $db->query("SELECT id, link FROM songs");
while($row = $result->fetch_assoc())
{
$number = 1+$rown++;
$id = $row['id'];
$link = $row['link'];
$video_ID = $link;
$JSON = file_get_contents("https://gdata.youtube.com/feeds/api/videos/{$video_ID}?v=2&alt=json");
$JSON_Data = json_decode($JSON);
$views = $JSON_Data->{'entry'}->{'yt$statistics'}->{'viewCount'};
echo $number .' row<br />';
echo $link .' link<br />';
echo $views .' views<br /><br />';
}
This attempt works fine and outputs me the data I need. The only problem is, that it just gets me data from the first 150-190 rows and that's it. Now I am checking for a solution that checks each row for empty youtube data and this lead to two concrete questions I have:
1st) Might youtube be responsible for that due to a restriction in retrieving data from one single query?
2nd) Might this be a server issue of mine that stops queries after x-seconds (but I already expand the time limit by putting a line set_time_limit (10000000); into my php code but without success)?
Hope you can help, thanks in advance.
YouTube, naturally, enforces limits on how many requests you can make per period of time. Unfortunately, there are no clear guidelines on what those limits are ... for v2, the guidelines merely state:
The YouTube API enforces quotas to prevent problems associated with
irregular API usage. Specifically, a too_many_recent_calls error
indicates that the API servers have received too many calls from the
same caller in a short amount of time. If you receive this type of
error, then we recommend that you wait a few minutes and then try your
request again.
If time isn't an issue for you, you could slow down each query so that you only make 1 request per every 10-15 seconds or so. Alternatively, you'd probably have better luck batch processing. With this, you can make up to 50 requests at once (this counts as 50 requests against your overall request per day quota, but only as one against your per time quota). Batch processing with v2 of the API is a little involved, as you make a POST request to a batch endpoint first, and then based on those results you can send in the multiple requests. Here's the documentation:
https://developers.google.com/youtube/2.0/developers_guide_protocol?hl=en#Batch_processing
Batch processing is much easier with v3, as you just have the videoId parameter be a comma delimited list of the videos you want info on -- so in your case, you'd execute file_get_contents on a URL like this:
https://www.googleapis.com/youtube/v3/videos?part=id&id={comma-separated-list-of-IDs}&maxResults=50&key={YOUR_API_KEY}
Any video ID in your list that doesn't come back in the JSON response doesn't exist anymore. IF you do 50 at a time, wait for 15 seconds, do another 50, etc., that should give you better performance.

Resources