100 크레딧 무료, 카드 등록 없이지금 시작하기
Logo
Back to blog

유튜브 댓글 크롤링, API로 5분 만에 끝내는 방법

·21 min read

유튜브 댓글 크롤링, API 호출 한 번이면 끝나요. 공식 API 할당량 계산법과 대댓글 5개 제한의 함정, 4가지 방법 비교표까지 코드로 정리했어요.

유튜브 댓글 크롤링, API로 5분 만에 끝내는 방법

유튜브 댓글 크롤링은 API 한 번 호출로 끝나요. 브라우저 자동화도, 셀레니움도 필요 없어요. 파이썬과 API 하나면 대댓글까지 코드 몇 줄로 받을 수 있어요. 공식 API 할당량을 실제 숫자로 계산해 보고, 대댓글이 5개만 오는 함정과 방법별 비교표까지 — 다른 글에서 잘 안 다루는 부분까지 담았어요.

이 글은 기술 개요일 뿐 법률 자문이 아니에요. 개인정보 보호법과 플랫폼 약관은 상황마다 다르게 적용되니, 실제 서비스에 쓰기 전에 전문가와 상담하세요.


유튜브 댓글 크롤링 전에 준비할 것

준비물은 셋이에요.

  • SocialCrawl API 키socialcrawl.dev에서 가입하면 바로 발급돼요
  • 파이썬 3.x + requests — curl로 그대로 따라 해도 돼요
  • JSON 다루는 기본기

유튜브 API 튜토리얼을 검색해 보면 대부분 Google Cloud 프로젝트를 만들고, API를 활성화하고, 자격증명을 발급받는 절차부터 시작해요. 여기서는 그 과정이 통째로 빠져요. x-api-key 헤더 하나면 끝이에요. OAuth 동의 화면도, 심사 대기도 없어요.


어떤 방법으로 모을까요? 4가지 방식 30초 비교

유튜브 댓글 크롤링 방법은 크게 넷으로 나뉘어요. 파이썬 크롤링 예제로 비교하면 차이가 더 명확해요.

방법설치 난이도속도대댓글 지원할당량·한도유지보수 리스크자동화비용
공식 API (YouTube Data API v3)높음 (Cloud 프로젝트 + 키 발급)빠름△ (5개 초과분은 별도 호출)하루 10,000 units낮음 (구글이 유지)가능무료 (할당량 내)
Selenium + BeautifulSoup중간 (드라이버 설정)느림 (스크롤·렌더링 대기)△ (토글을 눌러야 함)없음 (대신 IP 차단 위험)높음 (DOM 바뀌면 즉시 깨짐)어려움무료
노코드 툴 (pikk·Octoparse류)낮음 (브라우저만)보통툴마다 다름제공사 정책에 따름제공사 책임불가 (CSV 다운로드가 끝)무료~유료
youtube-comment-downloader (OSS, youtube comment scraper 계열)낮음 (pip install 한 줄)빠름문서에 명시 안 됨없음 (대신 레이트리밋 위험)중간 (내부 API 변경 시 깨질 수 있음)가능무료
SocialCrawl 통합 API낮음 (API 키만)빠름O (전용 엔드포인트 + 토큰 체인)요청당 1 크레딧, 일일 상한 없음낮음 (API 계약 유지)가능유료 (크레딧, 가입 시 100개 무료)

자동화 파이프라인에 붙일 게 아니라면 공식 API나 노코드 툴로도 충분해요. 정기적으로 돌리거나 대댓글까지 빠짐없이 받아야 한다면 공식 API의 할당량 벽과 Selenium의 유지보수 부담이 바로 발목을 잡아요.


공식 API 할당량, 숫자로 따져보면

유튜브 댓글 크롤링에서 가장 먼저 부딪히는 벽은 공식 API의 할당량이에요. YouTube Data API 할당량 문서에 나온 숫자 그대로예요.

메서드유닛 비용한 번에 최대
commentThreads.list1 unit댓글 100개
comments.list (답글용)1 unit답글 100개
videos.list1 unit
search.list100 unit (별도 버킷, 하루 100회)

프로젝트 기본 할당량은 공식 문서 기준으로 하루 10,000 units예요. search.list는 이 버킷과 별개로 하루 100회까지만 허용되니, 댓글 수집에는 크게 신경 쓸 필요 없어요.

숫자로 감을 잡아 볼게요.

  • maxResults=100으로 commentThreads.list를 1회 호출하면 1 unit이에요. 10,000 units를 전부 쓰면 이론상 하루 최대 100만 개의 최상위 댓글까지 받을 수 있어요.
  • 댓글 5만 개를 모으려면 대략 500회 호출, 즉 500 units가 필요해요. 하루 할당량의 5% 수준이에요.
  • 문제는 대댓글이에요. 답글이 많은 영상일수록 comments.list를 별도로 호출해야 하는 횟수가 늘어나서, 실효 처리량은 절반 이하로 떨어질 수 있어요.

여기서 많이 알려진 오해 하나를 정정할게요. "댓글을 많이 모으려면 결제해야 한다"는 말이 자주 보이는데, 사실이 아니에요. YouTube Data API는 할당량을 돈으로 사는 구조가 아니라, 증액 신청 폼을 내고 구글 심사를 거치는 구조예요.

SocialCrawl은 이 계정 단위 할당량 시스템 대신 요청 한 번에 1 크레딧으로 계산해요. API 키 하나로 시작하면 되고, 오늘 몇 시에 리셋되는지 신경 쓸 필요도 없어요.


1단계, 유튜브 댓글 크롤링 엔드포인트 호출하기

GET /v1/youtube/video/comments에 영상 URL만 넘기면 댓글이 와요.

import os
import requests

API_KEY = os.environ["SOCIALCRAWL_API_KEY"]
headers = {"x-api-key": API_KEY}

params = {
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "order": "top",  # 공식 API의 relevance에 대응해요
}

resp = requests.get(
    "https://www.socialcrawl.dev/v1/youtube/video/comments",
    headers=headers,
    params=params,
)
resp.raise_for_status()
data = resp.json()["data"]

comments = data["items"]
print(f"이번 페이지 댓글 수: {len(comments)}")
print(comments[0]["comment"]["text"])

ordertopnewest 둘뿐이에요. top이 공식 API의 relevance와 같은 개념이라고 보면 돼요. 응답은 data.items[].comment 형태로 오는데, SocialCrawl이 어떤 플랫폼이든 같은 통합 스키마로 돌려주는 방식이라 댓글 하나의 구조를 한 번만 익히면 다른 플랫폼에도 그대로 써먹을 수 있어요. 이 호출은 1 크레딧이에요.


2단계, 댓글 데이터 전부 가져오기 (페이지네이션)

한 페이지에 오는 댓글 수는 제한돼 있어서, 영상 전체 댓글을 받으려면 페이지를 넘겨야 해요.

def fetch_all_comments(video_url, order="top"):
    all_comments = []
    cursor = None

    while True:
        params = {"url": video_url, "order": order}
        if cursor:
            params["continuationToken"] = cursor

        resp = requests.get(
            "https://www.socialcrawl.dev/v1/youtube/video/comments",
            headers=headers,
            params=params,
        )
        resp.raise_for_status()
        data = resp.json()["data"]

        all_comments.extend(data["items"])
        cursor = data.get("next_cursor")

        if not cursor:
            break

    return all_comments


comments = fetch_all_comments("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
print(f"전체 댓글 수: {len(comments)}")

이전 응답의 next_cursor를 다음 요청의 continuationToken 파라미터에 그대로 넣어 보내는 구조예요. next_cursor가 없으면 마지막 페이지라는 뜻이니 루프를 끝내면 돼요.


3단계, 답글(대댓글)까지 빠짐없이 가져오기

공식 API에서 가장 많이 놓치는 부분이 여기예요. commentThreads.listpart=replies를 넣어도 답글을 최대 5개까지만 얹어줘요. 공식 문서 원문도 "목록의 항목 수가 snippet.totalReplyCount와 같지 않으면 일부만 온 것"이라고 명시해요. 전체를 받으려면 comments.listparentId로 또 호출해야 하고, 그마저도 답글의 답글은 지원하지 않아요.

SocialCrawl은 답글을 위한 엔드포인트가 따로 있어서 이 분기 로직이 필요 없어요. 댓글 응답에 실려 오는 토큰을 답글 엔드포인트로 그대로 넘기면서 체인을 끝까지 돌리기만 하면 돼요.

def fetch_all_replies(replies_token):
    all_replies = []
    token = replies_token

    while token:
        resp = requests.get(
            "https://www.socialcrawl.dev/v1/youtube/video/comment/replies",
            headers=headers,
            params={"continuationToken": token},
        )
        resp.raise_for_status()
        data = resp.json()["data"]

        all_replies.extend(data["items"])
        token = data.get("next_cursor")

    return all_replies


for item in comments:
    comment = item["comment"]
    # 답글 토큰은 comment.ext 아래에 있어요. 없으면 답글이 없는 댓글이에요.
    replies_token = (comment.get("ext") or {}).get("repliesContinuationToken")

    if replies_token:
        replies = fetch_all_replies(replies_token)
        print(f"{comment['id']}의 답글 {len(replies)}개 수집")

필드 이름이 헷갈리면 print(comment)로 한 번 찍어서 실제 구조를 확인해 보는 게 제일 빨라요. 이 방식이면 "대댓글이 일부만 수집됐어요" 문제 자체가 안 생겨요.


4단계, 수집한 댓글을 CSV로 저장하기

import csv

def save_to_csv(comments, filename="comments.csv"):
    with open(filename, "w", newline="", encoding="utf-8-sig") as f:
        writer = csv.writer(f)
        writer.writerow(["id", "author", "text", "likes", "published_at"])
        for item in comments:
            c = item["comment"]
            writer.writerow([
                c["id"],
                c["author"]["username"],
                c["text"],
                c["engagement"]["likes"],
                c["published_at"],
            ])

save_to_csv(comments)

엑셀보다 판다스 데이터프레임이 더 편하면 pd.DataFrame([item["comment"] for item in comments]) 한 줄로도 충분해요.


5단계, 채널 전체 영상의 댓글을 한 번에 모으기

영상 하나가 아니라 채널 전체를 돌리고 싶을 때는 GET /v1/youtube/channel/videos로 영상 목록부터 받고, 영상마다 2단계·3단계 함수를 그대로 재사용하면 돼요. 크롤링 봇 만들기의 핵심은 실패한 영상 때문에 전체가 멈추지 않게 하는 거예요.

def get_channel_videos(handle):
    videos = []
    cursor = None

    while True:
        params = {"handle": handle, "sort": "latest"}
        if cursor:
            params["continuationToken"] = cursor

        resp = requests.get(
            "https://www.socialcrawl.dev/v1/youtube/channel/videos",
            headers=headers,
            params=params,
        )
        resp.raise_for_status()
        data = resp.json()["data"]

        videos.extend(data["items"])
        cursor = data.get("next_cursor")

        if not cursor:
            break

    return videos


def crawl_channel_comments(handle):
    results = {}

    for item in get_channel_videos(handle):
        video_url = item["post"]["url"]
        try:
            results[video_url] = fetch_all_comments(video_url)
        except requests.HTTPError as e:
            print(f"{video_url} 스킵 — {e}")
            continue

    return results

매번 채널 전체를 다시 돌 필요는 없어요. 마지막으로 수집한 시각을 저장해 두고, 그 이후 업로드된 영상만 골라 돌리면 호출 수를 크게 줄일 수 있어요.


어떤 부분에서 막힐 수 있을까요?

이 코드는 2026년 8월 기준으로 직접 확인했어요.

  • commentsDisabled (403): 댓글이 꺼진 영상이에요. 예외 처리로 잡아서 다음 영상으로 넘어가세요.
  • videoNotFound (404): URL을 다시 확인하거나, 비공개·삭제된 영상인지 확인하세요.
  • quotaExceeded (403, 공식 API에서만 발생): 공식 API를 직접 쓰고 있다면 증액 신청 폼을 내야 해요. 결제로 바로 풀리는 문제가 아니에요.
  • continuationToken 만료 또는 누락: 토큰을 오래 보관해뒀다면 만료됐을 수 있어요. 처음부터 다시 요청하세요.
  • "대댓글이 일부만 수집됐어요": 3단계의 토큰 체인이 끝까지 돌았는지 확인하세요. 토큰이 남아 있는데 중간에 멈추면 일부만 받게 돼요.

위 크롤링 API 비교로 돌아가면, 오류 처리를 코드 몇 줄로 끝낼 수 있다는 게 스크래퍼를 직접 유지보수하는 것과 가장 크게 갈리는 지점이에요.


다음에는 뭘 할까요?

같은 구조로 틱톡 크롤링이나 인스타그램 크롤링 API로도 그대로 확장할 수 있어요. 엔드포인트만 바뀌고 페이지네이션 패턴은 똑같아요. 이렇게 SNS 데이터 수집 파이프라인을 넓혀 가다 보면, 수집한 텍스트를 텍스트 감정 분석 API로 넘겨서 댓글 여론을 자동으로 분류하는 단계로 자연스럽게 이어져요.

공식 API의 할당량 구조를 더 깊게 보고 싶다면 유튜브 API 2026: 할당량, 비용, 진짜 한계를 참고하세요. 같은 "OO 크롤링" 시리즈로는 네이버 크롤링 2026도 있어요. YouTube 엔드포인트 전체 목록은 SocialCrawl 문서에서 확인할 수 있어요.


자주 묻는 질문

유튜브 댓글 크롤링은 합법인가요?

공개된 댓글을 보는 것 자체는 문제없지만, 자동화된 수단으로 가져가는 건 별개예요. 유튜브 이용약관은 로봇·스크래퍼 같은 자동화 접근을 금지하고, 개발자 정책 III.E.6은 스크래핑을 명시적으로 막아요. 대법원 2022. 5. 12. 선고 2021도1533 판결은 "크롤링은 합법"이라는 뜻이 아니라, 보호조치·이용약관·복제 분량 같은 구체적인 사정에 따라 결론이 갈린다는 취지예요. 댓글 작성자의 채널명·ID는 대법원 2016. 8. 17. 선고 2014다235080 판결 기준으로 보면 개인정보로 취급될 여지가 있어서, 분석에 불필요하면 저장 단계에서 해싱하거나 지우고, 원본은 개발자 정책의 30일 보관 한도에 맞추는 걸 권해요.

API 키 없이도 유튜브 댓글을 수집할 수 있나요?

돼요. pip install youtube-comment-downloader로 설치하는 오픈소스 라이브러리가 있어요. CLI에서 --url 또는 --youtubeid로 실행하고, sort=0(인기)·sort=1(최신)로 정렬하고, --limit으로 개수를 제한해서 JSON·JSONL·CSV로 저장할 수 있어요. GitHub 스타 약 1.2k인 꽤 쓰이는 도구예요. 다만 API 키도 쿼터도 없는 대신 유튜브 내부 엔드포인트를 직접 부르는 방식이라, 위 질문의 스크래핑 금지 조항과 이어지는 리스크는 그대로예요. 무료지만 리스크는 쓰는 사람 몫이에요.

대댓글(답글)까지 한 번에 가져올 수 있나요?

네, 되는데 공식 API와 방식이 달라요. 공식 API는 commentThreads.list가 답글을 최대 5개까지만 얹어주고, 전체를 받으려면 comments.listparentId로 또 호출해야 해요. 여기서는 답글 전용 엔드포인트(/v1/youtube/video/comment/replies)가 따로 있어서, 댓글에 실려 오는 답글 토큰을 그대로 넘기면서 체인을 끝까지 돌리기만 하면 돼요. 위 3단계 코드를 그대로 재사용하면 돼요.

유튜브 분석 사이트를 쓰면 되지 않나요?

대시보드로 트렌드나 채널 지표만 훑어보는 거라면 유튜브 분석 사이트나 유튜브 데이터 분석 사이트로 충분해요. 하지만 원본 댓글 텍스트를 저장하거나, 감성 분석·워드클라우드 같은 후처리를 자동화하거나, 정기적으로 파이프라인을 돌려야 한다면 분석 사이트는 그 역할을 못 해줘요. 그건 직접 API를 호출하는 쪽이 답이에요.

Topics
#유튜브-댓글-크롤링#유튜브-api-튜토리얼#파이썬-크롤링#sns-데이터-수집#틱톡-크롤링#인스타그램-크롤링-api#유튜브-분석-사이트#유튜브-데이터-분석-사이트

함께 읽으면 좋은 글

🤖 AI agent or LLM? Read this page as markdown