Skip to content
← All posts
TutorialJavaScript

How to Scrape YouTube Comments in JavaScript

Hussein Hakizimana··5 min read

Scraping YouTube comments is annoying. The page loads them dynamically, pagination is tied to scroll events, and replies are a separate request entirely. The official API has a comments endpoint, but it's quota-limited and the data model is clunky.

This post shows how to pull comments — with pagination and replies — using the Stophy API. One POST request gets you a page of comments with full metadata. Continuation tokens handle the rest.

Setup

Node.js 18+ (fetch is built in) and a Stophy API key from stophy.dev/dashboard.

Fetch the first page

js
1async function getComments(videoUrl, sortBy = 'top') {
2 const res = await fetch('https://api.stophy.dev/v1/video', {
3 method: 'POST',
4 headers: {
5 'Authorization': `Bearer ${process.env.STOPHY_API_KEY}`,
6 'Content-Type': 'application/json',
7 },
8 body: JSON.stringify({ videoUrl, type: 'comments', sortBy }),
9 });
10
11 if (!res.ok) throw new Error(`Request failed: ${res.status}`);
12 const { data } = await res.json();
13 return data;
14}
15
16const data = await getComments('https://www.youtube.com/watch?v=YOUR_VIDEO_ID');
17
18for (const comment of data.items) {
19 console.log(`${comment.author}: ${comment.text}`);
20}

sortBy takes "top" or "latest". Each comment has author, text, likeCount, replyCount, publishedAt, isPinned, isHearted, isChannelOwner, and a repliesToken for fetching replies.

Paginate through all comments

If data.continuationToken is set, there are more pages. Pass it back in the next request:

js
1async function getAllComments(videoUrl, sortBy = 'top') {
2 const headers = {
3 'Authorization': `Bearer ${process.env.STOPHY_API_KEY}`,
4 'Content-Type': 'application/json',
5 };
6 const all = [];
7 let token = null;
8
9 while (true) {
10 const body = { videoUrl, type: 'comments', sortBy };
11 if (token) body.continuationToken = token;
12
13 const res = await fetch('https://api.stophy.dev/v1/video', {
14 method: 'POST',
15 headers,
16 body: JSON.stringify(body),
17 });
18
19 if (!res.ok) throw new Error(`Request failed: ${res.status}`);
20 const { data } = await res.json();
21
22 all.push(...data.items);
23 token = data.continuationToken ?? null;
24 if (!token) break;
25 }
26
27 return all;
28}

Fetch replies

Each top-level comment has a repliesToken. Pass it as continuationToken with type: 'replies':

js
1async function getReplies(repliesToken) {
2 const res = await fetch('https://api.stophy.dev/v1/video', {
3 method: 'POST',
4 headers: {
5 'Authorization': `Bearer ${process.env.STOPHY_API_KEY}`,
6 'Content-Type': 'application/json',
7 },
8 body: JSON.stringify({ type: 'replies', continuationToken: repliesToken }),
9 });
10
11 if (!res.ok) throw new Error(`Request failed: ${res.status}`);
12 const { data } = await res.json();
13 return data.items;
14}

Full script: export top 200 comments to CSV

js
1import { writeFileSync } from 'node:fs';
2
3async function fetchComments(videoUrl, max = 200) {
4 const headers = {
5 'Authorization': `Bearer ${process.env.STOPHY_API_KEY}`,
6 'Content-Type': 'application/json',
7 };
8 const results = [];
9 let token = null;
10
11 while (results.length < max) {
12 const body = { videoUrl, type: 'comments', sortBy: 'top' };
13 if (token) body.continuationToken = token;
14
15 const res = await fetch('https://api.stophy.dev/v1/video', {
16 method: 'POST',
17 headers,
18 body: JSON.stringify(body),
19 });
20
21 if (!res.ok) throw new Error(`Request failed: ${res.status}`);
22 const { data } = await res.json();
23
24 results.push(...data.items);
25 token = data.continuationToken ?? null;
26 if (!token) break;
27 }
28
29 return results.slice(0, max);
30}
31
32function toCSV(comments) {
33 const fields = ['author', 'text', 'likeCount', 'replyCount', 'publishedAt', 'isPinned'];
34 const header = fields.join(',');
35 const rows = comments.map(c =>
36 fields.map(f => JSON.stringify(c[f] ?? '')).join(',')
37 );
38 return [header, ...rows].join('\n');
39}
40
41const comments = await fetchComments('https://www.youtube.com/watch?v=YOUR_VIDEO_ID', 200);
42writeFileSync('comments.csv', toCSV(comments));
43console.log(`Saved ${comments.length} comments`);
Terminal
1STOPHY_API_KEY=your_key node --input-type=module script.js

The docs have the full reference.