Aditya Sharma

Export YouTube Comments to Google Sheets With Apps Script

On this page, 10 sections

To export YouTube comments to Google Sheets, call the YouTube Data API’s commentThreads.list method from an Apps Script, loop through the pages with pageToken, and write each comment into a row. Each call returns up to 100 comment threads and costs 1 quota unit, so a video with 5,000 top-level comment threads takes about 50 calls.

No add-on is needed, and no paid tool. The API is free inside its daily quota, and Apps Script is built into Sheets. What takes care is the loop: where the comment text goes, what happens when comments are disabled, and how not to burn the quota.

I read Google’s commentThreads.list reference, the quota calculator and the Apps Script quotas page on 11 October 2026. The script is a sketch built from those pages, and I have not run it against a live video for this post.

What the method accepts

From the reference page, these are the parameters that matter for a sheet.

  • part: snippet gives you the top-level comment. Add replies to get replies inside each thread.
  • videoId: returns the threads on one video.
  • allThreadsRelatedToChannelId: returns threads across a whole channel. You must pass exactly one filter, so this replaces videoId, not adds to it.
  • maxResults: 1 to 100, default 20. The default is the quota trap, as it is for most Data API list methods.
  • order: time (the default) or relevance.
  • textFormat: html (the default) or plainText. Choose plainText for a sheet, or you will paste markup like &amp; and <br> into cells.
  • pageToken: the cursor for the next page.

The method costs 1 unit per call. That figure is on both the method page and Google’s quota calculator.

The script

This version exports every top-level comment on one video, in plain text, 100 at a time.

function exportComments() {
  const videoId = 'PASTE_VIDEO_ID';
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('Comments') || ss.insertSheet('Comments');
  sheet.clear();
  sheet.appendRow(['Author', 'Comment', 'Likes', 'Published', 'Reply count']);

  let pageToken = '';
  const rows = [];
  try {
    do {
      const res = YouTube.CommentThreads.list('snippet', {
        videoId: videoId,
        maxResults: 100,
        order: 'time',
        textFormat: 'plainText',
        pageToken: pageToken
      });
      res.items.forEach(t => {
        const c = t.snippet.topLevelComment.snippet;
        rows.push([c.authorDisplayName, c.textDisplay, c.likeCount, c.publishedAt, t.snippet.totalReplyCount]);
      });
      pageToken = res.nextPageToken;
    } while (pageToken);
  } catch (e) {
    console.log('Stopped: ' + e.message);
  }
  if (rows.length) sheet.getRange(2, 1, rows.length, 5).setValues(rows);
}

I checked the field names against Google’s commentThread and comment resource pages on 11 October 2026. snippet.topLevelComment and snippet.totalReplyCount sit on the thread. authorDisplayName, textDisplay, likeCount and publishedAt sit on the comment’s snippet.

One caveat from the comment page: even the plain text may differ from what the viewer typed, for example by replacing video links with video titles. textOriginal exists, but Google says it is only returned to the comment’s author.

The try block is deliberate. It catches API errors such as a 403, and because the rows are written after the loop, those errors still leave you the pages you already collected.

It will not save you from the 6 minute execution limit, since Google says a script stops when a limit is exceeded. For a very large video, write each page’s rows to the sheet as you go.

The error you will hit: comments disabled

The reference page documents a 403 commentsDisabled error for a video whose owner turned comments off. Looping over a list of video IDs, one disabled video will throw and stop your whole run if there is no try around each video.

Wrap the per-video call, log the ID, and continue. A disabled video is data too. A column of “comments disabled” is useful when you are auditing a channel.

What it costs in quota

The default Data API allocation is 10,000 units a day for everything except search.list and videos.insert, which have their own 100-call buckets. This is on Google’s quota calculator page, and I cover it fully in the quota guide.

So the arithmetic, which is mine and not Google’s, looks like this.

  • A video with 1,000 threads at 100 per page: 10 calls, 10 units.
  • A channel of 200 videos averaging 500 threads: 5 pages each, so 1,000 calls, 1,000 units.
  • The theoretical ceiling if nothing else ran that day: 10,000 calls at 100 each, 1,000,000 threads.

Forget maxResults: 100 and you get the default of 20, which is five times the calls for the same comments.

Replies, and a limit I could not verify

With part: 'snippet,replies', each thread can carry replies, but not all of them. Google’s commentThread page says the replies list holds a limited number of replies.

Unless the list length equals snippet.totalReplyCount, it is a subset. To get every reply, call comments.list with the parentId parameter set to the top-level comment’s ID. That method costs 1 unit a call on the quota table.

For a first export, leave replies out and keep totalReplyCount. It tells you which threads have replies. Then call comments.list only for threads where the count is above 0, which keeps the call count down.

Putting it in the sheet safely

  • Use plainText. The default html format puts markup in your cells.
  • Write in one batch. One setValues call for all rows is much faster than appendRow in a loop, and it matters when the sheet has 5,000 rows.
  • Watch for formulas. A comment that starts with = can be read by Sheets as a formula when written with setValues. This is how Sheets treats typed input as I understand it, and I did not test it in this session. If you are exporting comments from strangers, prefix any value starting with =, +, - or @ with a single quote.
  • Run within the limit. One execution may run 6 minutes, and consumer accounts get 90 minutes of trigger runtime a day, per the Apps Script quotas page (last updated 3 September 2026).

Make the export usable

A raw dump of 5,000 comments is not an analysis. Three small additions make it one.

  • Add the video ID as a column. When you export several videos into one tab, you need to know which comment came from where.
  • Check the published date column. The API returns it as a datetime value. Look at how Sheets stores it after the first run, before you sort on it.
  • Use likeCount to sort. Sorting by likes puts the comments other viewers agreed with at the top.

Once the data is in, a few simple formulas go a long way. COUNTIF on a keyword column shows how many viewers mentioned a topic. A pivot table on author shows repeat commenters. A filter on the reply count finds the threads where people are actually talking.

For a creator, the practical use is finding questions. Filter the Comment column for a question mark and you have a list of what viewers asked, which you can read as a topic list built from material they already wrote.

Questions people ask

Can I export comments from someone else’s video?

The reference page does not limit videoId to videos you own, so the same method takes any video ID. I did not test a video from another channel. Comments contain names and opinions, so treat the sheet as personal data once they are in it.

How do I get all comments from a channel?

Use allThreadsRelatedToChannelId instead of videoId. It is a documented filter and returns threads across the channel, with the same paging and the same 1 unit per call.

Why is my comment export missing some comments?

I could not verify from the reference page whether held-for-review or removed comments appear in the API. If counts differ from Studio, do not assume the script is wrong.

For metadata about the videos themselves, such as titles and dates, use the video details import and join on video ID.

Do this today

Pick one video with a few hundred comments. Paste the script, set videoId, run it, and look at row 2. If the columns line up with what you see on YouTube, change the ID to the next video.

Resources

Tell me where I am wrong

Your email is not published and I do not add it to any list. Corrections with a source are the ones I act on fastest.