Comments

Fetch video comments, replies, stats, and search with auto-pagination

Overview

The comments module fetches YouTube video and channel comments using the YouTube Data API v3. All methods auto-paginate through results and return structured, typed data.

import { yt } from 'lyra-sdk'

const client = yt(process.env.YOUTUBE_API_KEY!)

client.comments(videoUrlOrId, opts?)

Fetch all comment threads for a video. Auto-paginates through all pages.

const threads = await client.comments('dQw4w9WgXcQ')

for (const thread of threads) {
  console.log(`@${thread.topLevelComment.authorName}: ${thread.topLevelComment.text}`)
  console.log(`  ${thread.totalReplyCount} replies`)
}

Also accepts URLs:

const threads = await client.comments('https://youtu.be/dQw4w9WgXcQ')

Options

PropertyTypeDefaultDescription
order"time" | "relevance""time"Sort order for comments
maxResultsnumber100Max total results to return (caps pagination)
searchTermsstringFilter comments by keyword
textFormat"html" | "plainText""plainText"Comment text format

CommentThread

PropertyTypeDescription
idstringComment thread ID
videoIdstringVideo ID
channelIdstringChannel ID associated with the video
topLevelCommentCommentThe top-level comment
totalReplyCountnumberTotal replies to the top-level comment
canReplybooleanWhether the current viewer can reply
isPublicbooleanWhether the thread is publicly visible
repliesComment[]First page of replies (may be incomplete)

Comment

PropertyTypeDescription
idstringComment ID
authorNamestringDisplay name of the commenter
authorProfileImagestringAvatar URL
authorChannelUrlstringChannel URL of the commenter
authorChannelIdstringChannel ID of the commenter
textstringComment text
likeCountnumberNumber of likes
publishedAtDateWhen the comment was published
updatedAtDateWhen the comment was last updated
parentIdstringParent comment ID (only for replies)

client.commentReplies(commentId, textFormat?)

Fetch all replies to a specific comment. Auto-paginates.

const replies = await client.commentReplies('UgwSomeCommentId')

for (const reply of replies) {
  console.log(`  @${reply.authorName}: ${reply.text}`)
}

The commentThreads.list endpoint returns only a subset of replies. Use this method to get all replies when totalReplyCount exceeds the replies included in the thread.


client.commentsWithReplies(videoUrlOrId, opts?)

Fetches all comment threads and auto-fetches all replies for each thread. Combines the two API calls into a single function.

const threads = await client.commentsWithReplies('dQw4w9WgXcQ')

for (const thread of threads) {
  console.log(`@${thread.topLevelComment.authorName}: ${thread.topLevelComment.text}`)
  for (const reply of thread.replies ?? []) {
    console.log(`  └─ @${reply.authorName}: ${reply.text}`)
  }
}

This method makes additional API calls for each thread that has more replies than the first page. For a video with 50 threads and 20 needing full replies, that's ~20 extra quota units. Use client.comments() if you don't need all replies.


client.topComments(videoUrlOrId, limit?)

Fetch top comments sorted by relevance (most liked). Returns up to limit results.

const top5 = await client.topComments('dQw4w9WgXcQ', 5)

for (const thread of top5) {
  const c = thread.topLevelComment
  console.log(`@${c.authorName} (${c.likeCount} likes): ${c.text}`)
}

client.searchComments(videoUrlOrId, query, opts?)

Search comments by keyword. Uses YouTube's searchTerms parameter. Accepts the same options as client.comments().

const results = await client.searchComments('dQw4w9WgXcQ', 'great song', { maxResults: 20 })
console.log(`Found ${results.length} matching threads`)

Keyword search can be slow on videos with millions of comments. Use maxResults to limit results and avoid long waits.


client.channelComments(channelId, opts?)

Fetch all comment threads associated with a channel.

const threads = await client.channelComments('UCxxxxxx')

client.commentStats(videoId, threads)

Compute aggregate statistics from an array of comment threads. Pure computation — no API call.

const threads = await client.comments('dQw4w9WgXcQ', { maxResults: 50 })
const stats = client.commentStats('dQw4w9WgXcQ', threads)

console.log(`Total comments:   ${stats.totalComments}`)
console.log(`Total replies:    ${stats.totalReplies}`)
console.log(`Unique authors:   ${stats.uniqueAuthors}`)
console.log(`Avg likes:        ${stats.avgLikes}`)
console.log(`Reply ratio:      ${stats.replyRatio}`)
console.log(`Most liked:       ${stats.mostLikedComment?.authorName}`)

CommentStats

PropertyTypeDescription
videoIdstringVideo ID
totalCommentsnumberNumber of top-level comment threads
totalRepliesnumberTotal replies across all threads
uniqueAuthorsnumberUnique commenters (top-level + replies)
mostLikedCommentComment | nullThe comment with the most likes
avgLikesnumberAverage likes per comment
replyRationumberReplies per top-level comment

client.flattenComments(threads)

Flatten threads + replies into a single flat Comment[] array. Pure utility — no API call.

const threads = await client.comments('dQw4w9WgXcQ')
const flat = client.flattenComments(threads)

console.log(`Total items: ${flat.length}`) // top-level + replies combined

client.commentQuery(videoUrlOrId)

Fluent query builder for filtering and slicing comments.

const result = await client.commentQuery('dQw4w9WgXcQ')
  .order('relevance')
  .search('love this')
  .limit(20)
  .withAllReplies()
  .execute()

console.log(`Found ${result.totalResults} threads`)
console.log(`Stats: ${result.stats.uniqueAuthors} unique authors`)

Builder methods

MethodDescription
.order(order)"time" or "relevance"
.search(query)Filter by keyword
.limit(n)Max number of threads to return
.withAllReplies()Auto-fetch all replies for each thread
.textFormat(format)"html" or "plainText"
.execute()Execute the query and return result

CommentQueryResult

PropertyTypeDescription
videoIdstringVideo ID
threadsCommentThread[]Result threads
totalResultsnumberNumber of threads returned
statsCommentStatsAggregate statistics

Error handling

import { yt, NotFoundError, QuotaError } from 'lyra-sdk'

try {
  const threads = await client.comments('INVALID_ID')
} catch (error) {
  if (error instanceof NotFoundError) {
    console.log('Video not found or comments disabled')
  } else if (error instanceof QuotaError) {
    console.log('Quota exceeded')
  }
}
HTTP StatusCause
403Comments disabled on the video
404Video or channel not found
429YouTube API quota exceeded

Quota usage

MethodQuota cost
comments()1 unit per page
commentReplies()1 unit per page
commentsWithReplies()1 + N pages (N = threads needing full replies)
topComments()1 unit per page
searchComments()1 unit per page
channelComments()1 unit per page
commentStats()0 (pure computation)
flattenComments()0 (pure computation)

On this page