The official YouTube Data API has a comments endpoint, but the quota runs out fast and the data model requires multiple requests to get everything you need. Scrapers work until they don't — YouTube changes its page structure regularly.
This post shows how to pull comments in Python using the Stophy API. You get a full page of comments per request, continuation tokens for pagination, and a separate call for replies. No browser automation, no quota headaches.
Setup
1pip install httpxGet a Stophy API key from stophy.dev/dashboard.
Fetch the first page
1import os2import httpx34def get_comments(video_url: str, sort_by: str = "top") -> dict:5 res = httpx.post(6 "https://api.stophy.dev/v1/video",7 headers={"Authorization": f"Bearer {os.environ['STOPHY_API_KEY']}"},8 json={"videoUrl": video_url, "type": "comments", "sortBy": sort_by},9 )10 res.raise_for_status()11 return res.json()["data"]1213data = get_comments("https://www.youtube.com/watch?v=YOUR_VIDEO_ID")1415for comment in data["items"]:16 print(f"{comment['author']}: {comment['text']}")sort_by takes "top" or "latest". Each comment has author, text, likeCount, replyCount, publishedAt, isPinned, isHearted, isChannelOwner, and a repliesToken.
Paginate through all comments
Pass continuationToken back in the next request to get the next page:
1def get_all_comments(video_url: str, sort_by: str = "top") -> list:2 headers = {"Authorization": f"Bearer {os.environ['STOPHY_API_KEY']}"}3 all_comments = []4 token = None56 while True:7 body = {"videoUrl": video_url, "type": "comments", "sortBy": sort_by}8 if token:9 body["continuationToken"] = token1011 res = httpx.post("https://api.stophy.dev/v1/video", headers=headers, json=body)12 res.raise_for_status()13 data = res.json()["data"]1415 all_comments.extend(data["items"])16 token = data.get("continuationToken")17 if not token:18 break1920 return all_commentsFetch replies
Use the repliesToken from any top-level comment:
1def get_replies(replies_token: str) -> list:2 res = httpx.post(3 "https://api.stophy.dev/v1/video",4 headers={"Authorization": f"Bearer {os.environ['STOPHY_API_KEY']}"},5 json={"type": "replies", "continuationToken": replies_token},6 )7 res.raise_for_status()8 return res.json()["data"]["items"]Full script: export top 200 comments to CSV
1import csv2import os3import httpx45def fetch_comments(video_url: str, max_comments: int = 200) -> list:6 headers = {"Authorization": f"Bearer {os.environ['STOPHY_API_KEY']}"}7 results = []8 token = None910 while len(results) < max_comments:11 body = {"videoUrl": video_url, "type": "comments", "sortBy": "top"}12 if token:13 body["continuationToken"] = token1415 res = httpx.post("https://api.stophy.dev/v1/video", headers=headers, json=body)16 res.raise_for_status()17 data = res.json()["data"]1819 results.extend(data["items"])20 token = data.get("continuationToken")21 if not token:22 break2324 return results[:max_comments]2526def save_csv(comments: list, filename: str) -> None:27 fields = ["author", "text", "likeCount", "replyCount", "publishedAt", "isPinned"]28 with open(filename, "w", newline="", encoding="utf-8") as f:29 writer = csv.DictWriter(f, fieldnames=fields, extrasaction="ignore")30 writer.writeheader()31 writer.writerows(comments)3233if __name__ == "__main__":34 comments = fetch_comments("https://www.youtube.com/watch?v=YOUR_VIDEO_ID", 200)35 save_csv(comments, "comments.csv")36 print(f"Saved {len(comments)} comments to comments.csv")The docs have the full reference.