Home > OS >  API call to youtube.videos.list failed with error
API call to youtube.videos.list failed with error

Time:09-27

When I run the following JavaScript through Google Apps script with more then 100 keywords.

function youTubeSearchResults() {
  // 1. Retrieve values from column "A".
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const values = sheet.getRange("A2:A"   sheet.getLastRow()).getDisplayValues().filter(([a]) => a);

  // 2. Retrieve your current values.
  const modifyResults = values.flatMap(([keywords]) => {
    const searchResults = YouTube.Search.list("id, snippet", { q: keywords, maxResults: 10, type: "video", order: "viewCount", videoDuration: "short", order: "date" });
    const fSearchResults = searchResults.items.filter(function (sr) { return sr.id.kind === "youtube#video" });
    return fSearchResults.map(function (sr) { return [keywords, sr.id.videoId, `https://www.youtube.com/watch?v=${sr.id.videoId}`, sr.snippet.title, sr.snippet.publishedAt, sr.snippet.channelTitle, sr.snippet.channelId, `https://www.youtube.com/channel/${sr.snippet.channelId}`, sr.snippet.thumbnails.high.url] });
  });

  // 3. Retrieve viewCounts and subscriberCounts.
  const { videoIds, channelIds } = modifyResults.reduce((o, r) => {
    o.videoIds.push(r[1]);
    o.channelIds.push(r[6]);
    return o;
  }, { videoIds: [], channelIds: [] });
  const limit = 50;
  const { viewCounts, subscriberCounts } = [...Array(Math.ceil(videoIds.length / limit))].reduce((obj, _) => {
    const vIds = videoIds.splice(0, limit);
    const cIds = channelIds.splice(0, limit);
    const res1 = YouTube.Videos.list(["statistics"], { id: vIds, maxResults: limit }).items.map(({ statistics: { viewCount } }) => viewCount);
    const obj2 = YouTube.Channels.list(["statistics"], { id: cIds, maxResults: limit }).items.reduce((o, { id, statistics: { subscriberCount } }) => (o[id] = subscriberCount, o), {});
    const res2 = cIds.map(e => obj2[e] || null);
    obj.viewCounts = [...obj.viewCounts, ...res1];
    obj.subscriberCounts = [...obj.subscriberCounts, ...res2];
    return obj;
  }, { viewCounts: [], subscriberCounts: [] });
  const ar = [viewCounts, subscriberCounts];
  const rr = ar[0].map((_, c) => ar.map(r => r[c]));

  // 4. Merge data.
  const res = modifyResults.map((r, i) => [...r, ...rr[i]]);

  // 5. Put values on Spreadsheet.
  sheet.getRange(2, 2, res.length, res[0].length).setValues(res);
}

it gives me that error

GoogleJsonResponseException: API call to youtube.videos.list failed with error: 
The request cannot be completed because you have exceeded your <a href="/youtube/v3/getting-started#quota">quota</a>.
reduce.viewCounts @code.gs:23
youTubeSearchResults @code.gs:20 

I know YouTube have data call limits for example you can call the results of not more then 50 video ids at one time but if you have 1000 video ids in your sheet you can run then loop for first 50 then next so on. Is it anything like that I can do with search results too.

Please help me understand how can I fix this issue.

CodePudding user response:

Note that the endpoint the most expensive in your script is the Search: list one which costs 100 of your 10,000 quota (you can have a look to other endpoint costs here).

You may be interested in the standalone quota-free solution that consists in reverse-engineering the YouTube UI search feature.

Otherwise a temporary solution to Google audit consists in using my no-key service at https://yt.lemnoslife.com With my no-key service:

const searchResults = YouTube.Search.list("id, snippet", { q: keywords, maxResults: 10, type: "video", order: "viewCount", videoDuration: "short", order: "date" });

would become:

const searchResults = JSON.parse(UrlFetchApp.fetch(`https://yt.lemnoslife.com/noKey/search?part=snippet&q=${keywords}&maxResults=10&type=video&order=viewCount&videoDuration=short`).getContentText())

As part=id doesn't add more data to the response and AFAIK using two order isn't supported by YouTube Data API v3.

  • Related