틱톡 데이터 스크레이핑의 현실: 왜 이렇게 어려운가
틱톡은 전 세계에서 가장 봇 탐지가 까다로운 플랫폼 중 하나입니다. 구글이나 아마존과 달리, 틱톡은 모바일 퍼스트 플랫폼으로 설계되었으며, 바이트댄스(ByteDance)는 자체 개발한 정교한 봇 탐지 스택을 운영합니다. 공개 데이터에 접근하려는 개발자와 마케팅 분석가들은 _signature 파라미터, msToken, 기기 검증, WAF(Web Application Firewall) 등 여러 장벽에 직면합니다.
이 가이드에서는 프록시로 틱톡 공개 데이터를 스크레이핑하는 실전 방법을 다룹니다. 법적 경계를 준수하면서도 크리에이터 이코노미 도구와 마케팅 분석에 필요한 데이터를 수집하는 방법을 단계별로 설명합니다.
중요 고지: 이 가이드는 공개적으로 접근 가능한 데이터에 한정됩니다. 틱톡의 이용약관(Terms of Service)을 확인하고, robots.txt를 존중하며, 관할 법률(CFAA, GDPR, CCPA 등)을 준수하십시오. 공식 API가 제공하는 데이터가 있다면 우선적으로 사용하는 것이 권장됩니다.
틱톡의 봇 탐지 스택 이해하기
틱톡이 스크레이퍼를 차단하는 방식은 다층 구조로 되어 있습니다. 각 계층을 이해해야 우회 전략을 세울 수 있습니다.
1. 기기 지문(Device Fingerprinting)
틱톡은 방문자의 브라우저와 기기에 대한 상세 정보를 수집합니다:
- Canvas/WebGL 지문: 그래픽 렌더링 차이로 기기 식별
- 오디오 지문: 오디오 컨텍스트 처리 방식
- 폰트 감지: 설치된 폰트 목록
- 화면 해상도 및 색상 깊이
- 타임존 및 언어 설정
- User-Agent 및 플랫폼 정보
헤드리스 브라우저나 표준 스크레이퍼는 이러한 지문에서 일관되지 않은 패턴을 보여 차단됩니다.
2. WAF(Web Application Firewall)
틱톡의 WAF는 의심스러운 트래픽 패턴을 실시간으로 차단합니다:
- 동일 IP에서 과도한 요청
- 비정상적인 요청 속도(인간보다 빠른 클릭/스크롤)
- 필수 헤더 누락 또는 순서 오류
- 알려진 데이터센터 IP 대역
3. msToken 및 _signature 파라미터
틱톡 API 요청에는 두 가지 중요한 파라미터가 필요합니다:
msToken: 요청마다 생성되는 토큰으로, 브라우저 JavaScript 실행 결과 생성됩니다. 난독화된 난수처럼 보이지만 실제로는 암호화 서명이 포함되어 있습니다.
_signature: 요청 URL과 파라미터를 기반으로 생성된 암호화 서명입니다. 틱톡은 이를 통해 요청이 정상 브라우저에서 왔는지 검증합니다. 서명 알고리즘은 난독화되어 있으며 정기적으로 변경됩니다.
# 틱톡 API 요청 예시
https://www.tiktok.com/api/post/item_list/?
WebIdLastTime=...
aid=1988
app_name=tiktok_web
device_platform=web
msToken=...
_signature=...
로그인 없이 접근 가능한 공개 데이터
틱톡에서 로그인 없이 접근할 수 있는 데이터는 제한적이지만, 마케팅 분석에는 충분히 유용합니다.
접근 가능한 페이지 유형
| 페이지 유형 | URL 예시 | 수집 가능 데이터 |
|---|---|---|
| 크리에이터 프로필 | @username |
팔로워 수, 총 좋아요, 바이오, 프로필 이미지 |
| 비디오 페이지 | @username/video/123456 |
조회수, 좋아요, 댓글 수, 공유 수, 업로드 날짜 |
| 해시태그 페이지 | tag/trending |
해시태그 조회수, 관련 비디오 목록 |
| 트렌드/발견 페이지 | foryou |
현재 유행하는 콘텐츠 (개인화됨) |
| 사운드/음악 페이지 | music/원본-사운드-123 |
사운드 사용 횟수, 관련 비디오 |
로그인이 필요한 데이터
- 비공개 계정의 콘텐츠
- 개인화된 'For You' 피드 (정확한 재현 불가)
- DM(다이렉트 메시지)
- 댓글의 상세 정보 (일부 공개)
- 연령 제한 콘텐츠
왜 레지덴셜 및 모바일 프록시가 필수인가
틱톡은 모바일 퍼스트 플랫폼입니다. 전체 트래픽의 약 80% 이상이 모바일 앱에서 발생합니다. 이는 스크레이핑 전략에 중요한 시사점을 줍니다.
데이터센터 IP vs 레지덴셜 IP
| 프록시 유형 | 탐지 위험 | 성공률 | 비용 |
|---|---|---|---|
| 데이터센터 | 매우 높음 | 10-30% | 낮음 |
| 레지덴셜 | 낮음 | 70-90% | 중간 |
| 모바일 (4G/5G) | 최저 | 90-99% | 높음 |
모바일 프록시가 가장 효과적인 이유:
- 자연스러운 트래픽 패턴: 틱톡은 모바일 트래픽에 최적화되어 있어 모바일 IP에서 오는 요청을 '정상'으로 간주할 확률이 높습니다.
- IP 평판: 모바일 ISP IP는 실제 사용자가 공유하므로 평판이 좋습니다.
- 자연스러운 IP 로테이션: 모바일 IP는 자연스럽게 변경되므로 차단 패턴과 유사합니다.
웹 스크레이핑 사용 사례에서 다양한 프록시 유형의 상세 비교를 확인할 수 있습니다.
Python + Playwright로 틱톡 스크레이퍼 구현하기
다음은 Playwright의 스텔스(stealth) 모드와 레지덴셜 프록시를 사용하여 틱톡 크리에이터 페이지에서 데이터를 추출하는 Python 예제입니다.
필수 패키지 설치
pip install playwright asyncio
playwright install chromium
기본 스크레이퍼 코드
import asyncio
from playwright.async_api import async_playwright
class TikTokScraper:
def __init__(self, proxy_url=None):
self.proxy_url = proxy_url
async def scrape_creator(self, username: str) -> dict:
async with async_playwright() as p:
# 브라우저 실행 옵션
launch_options = {
"headless": True,
"args": [
"--disable-blink-features=AutomationControlled",
"--disable-features=IsolateOrigins,site-per-process",
]
}
# 프록시 설정 (ProxyHat 레지덴셜)
if self.proxy_url:
launch_options["proxy"] = {"server": self.proxy_url}
browser = await p.chromium.launch(**launch_options)
# 모바일 디바이스 에뮬레이션
context = await browser.new_context(
user_agent=(
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) "
"AppleWebKit/605.1.15 (KHTML, like Gecko) "
"Version/17.0 Mobile/15E148 Safari/604.1"
),
viewport={"width": 390, "height": 844},
device_scale_factor=3,
)
page = await context.new_page()
# 스텔스 스크립트 주입
await page.add_init_script("""
Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
Object.defineProperty(navigator, 'platform', {get: () => 'iPhone'});
window.chrome = {runtime: {}};
""")
try:
# 크리에이터 페이지 접속
url = f"https://www.tiktok.com/@{username}"
await page.goto(url, wait_until="networkidle", timeout=30000)
# 데이터 추출
data = await page.evaluate("""() => {
const stats = {};
// 팔로워 수
const followerEl = document.querySelector('[data-e2e="followers-count"]');
if (followerEl) stats.followers = followerEl.textContent;
// 좋아요 수
const likesEl = document.querySelector('[data-e2e="likes-count"]');
if (likesEl) stats.likes = likesEl.textContent;
// 바이오
const bioEl = document.querySelector('[data-e2e="profile-bio"]');
if (bioEl) stats.bio = bioEl.textContent;
return stats;
}""")
data["username"] = username
data["url"] = url
return data
except Exception as e:
print(f"Error scraping {username}: {e}")
return None
finally:
await browser.close()
# ProxyHat 레지덴셜 프록시 사용 예시
async def main():
# 사용자명에 국가 코드 추가로 지역 타겟팅
proxy_url = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"
scraper = TikTokScraper(proxy_url=proxy_url)
result = await scraper.scrape_creator("tiktok")
if result:
print(f"Username: {result['username']}")
print(f"Followers: {result.get('followers', 'N/A')}")
print(f"Likes: {result.get('likes', 'N/A')}")
asyncio.run(main())
코드 설명
- 모바일 에뮬레이션: 틱톡은 모바일 퍼스트이므로 iPhone User-Agent와 뷰포트를 사용합니다.
- 스텔스 스크립트:
navigator.webdriver등 봇 탐지 마커를 제거합니다. - 프록시 통합: ProxyHat 레지덴셜 프록시로 실제 사용자 IP처럼 보이게 합니다.
- data-e2e 선택자: 틱톡의 내부 테스트 선택자를 사용해 더 안정적으로 데이터를 추출합니다.
_signature 헤더 처리 방법
_signature는 틱톡 봇 탐지의 핵심입니다. 이를 처리하는 세 가지 접근법이 있습니다.
방법 1: 브라우저 JavaScript 실행 (권장)
Playwright나 Puppeteer에서 실제 브라우저를 실행하면 JavaScript가 자연스럽게 서명을 생성합니다. 위 예제에서처럼 페이지를 로드한 후 API 호출을 가로채거나, 페이지 내 JavaScript를 실행해 서명을 얻을 수 있습니다.
# 페이지 로드 후 API 요청 가로채기
async def intercept_api_requests(page):
api_data = []
async def handle_response(response):
if "/api/" in response.url:
try:
json_data = await response.json()
api_data.append({
"url": response.url,
"data": json_data
})
except:
pass
page.on("response", handle_response)
return api_data
방법 2: 타사 서명 서비스 사용
일부 서비스는 틱톡 서명 생성을 API로 제공합니다. 이 방식은 추가 비용이 들지만, 브라우저를 실행할 필요가 없어 더 빠릅니다. 단, 서비스의 신뢰성과 보안을 검토해야 합니다.
방법 3: 리버스 엔지니어링 (고급)
틱톡의 JavaScript 번들을 분석해 서명 알고리즘을 역추적하는 방법입니다. 난독화가 심하고 알고리즘이 자주 변경되므로 지속적인 유지보수가 필요합니다. 법적/윤리적 고려가 필요합니다.
현실적인 조언: 대부분의 경우 방법 1(브라우저 실행)이 가장 안정적입니다. 서명 알고리즘이 변경되어도 브라우저는 자동으로 업데이트된 JavaScript를 실행합니다.
확장 패턴: 크리에이터 추적 및 트렌드 분석
크리에이터 인플루언서 분석
인플루언서 마케팅 플랫폼을 구축할 때 필요한 데이터:
- 크리에이터 프로필 메타데이터 (팔로워, 참여율)
- 최근 비디오 성과 (조회수, 좋아요, 댓글)
- 콘텐츠 카테고리 및 해시태그 분포
- 협업 이력 (듀엣, 스티치)
import asyncio
from datetime import datetime
class CreatorTracker:
def __init__(self, proxy_url: str):
self.proxy_url = proxy_url
self.scraper = TikTokScraper(proxy_url)
async def track_creators(self, usernames: list[str]) -> list[dict]:
"""여러 크리에이터 추적"""
results = []
for username in usernames:
data = await self.scraper.scrape_creator(username)
if data:
data["scraped_at"] = datetime.now().isoformat()
results.append(data)
# 요청 간 지연 (차단 방지)
await asyncio.sleep(2 + (hash(username) % 3))
return results
async def calculate_engagement_rate(self, creator_data: dict) -> float:
"""참여율 계산"""
# 최근 비디오 데이터가 필요
pass
# 사용 예시
async def main():
proxy_url = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"
tracker = CreatorTracker(proxy_url)
creators = ["tiktok", "charlidamelio", "khaby.lame"]
results = await tracker.track_creators(creators)
for r in results:
print(f"{r['username']}: {r.get('followers', 'N/A')} followers")
asyncio.run(main())
해시태그 모니터링
브랜드 마케팅을 위한 해시태그 트렌드 추적:
async def scrape_hashtag(page, hashtag: str) -> dict:
"""해시태그 페이지에서 비디오 목록 수집"""
url = f"https://www.tiktok.com/tag/{hashtag}"
await page.goto(url, wait_until="networkidle")
# 스크롤하여 더 많은 비디오 로드
for _ in range(3):
await page.evaluate("window.scrollBy(0, 1000)")
await asyncio.sleep(1)
videos = await page.evaluate("""() => {
const items = [];
document.querySelectorAll('[data-e2e="search_video-item"]').forEach(el => {
const link = el.querySelector('a');
const views = el.querySelector('[data-e2e="video-views"]');
items.push({
url: link?.href,
views: views?.textContent
});
});
return items;
}""")
return {"hashtag": hashtag, "videos": videos}
요청 속도 제한 전략
틱톡은 속도 기반 차단을 사용합니다. 안전한 스크레이핑을 위한 패턴:
- 요청 간격: 최소 2-5초 대기
- 세션 로테이션: 일정 요청 후 새 세션 시작
- IP 로테이션: 프록시 세션 플래그 사용
- 랜덤 지연: 인간처럼 보이는 불규칙한 패턴
# ProxyHat 세션 로테이션 예시
proxy_urls = [
"http://user-session-abc1:PASSWORD@gate.proxyhat.com:8080",
"http://user-session-abc2:PASSWORD@gate.proxyhat.com:8080",
"http://user-session-abc3:PASSWORD@gate.proxyhat.com:8080",
]
import random
async def rotate_session():
return random.choice(proxy_urls)
ProxyHat 요금제에서 세션 로테이션과 지역 타겟팅 옵션을 확인할 수 있습니다.
Node.js 예제: 빠른 데이터 수집
Node.js와 Puppeteer를 사용한 대안:
const puppeteer = require('puppeteer');
async function scrapeTikTokCreator(username, proxyUrl) {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox'],
proxy: proxyUrl ? { server: proxyUrl } : undefined
});
const page = await browser.newPage();
// 모바일 뷰포트 설정
await page.setUserAgent(
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) ' +
'AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148'
);
await page.setViewport({ width: 390, height: 844 });
// 스텔스 플러그인 효과
await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
});
try {
await page.goto(`https://www.tiktok.com/@${username}`, {
waitUntil: 'networkidle2',
timeout: 30000
});
const data = await page.evaluate(() => {
const getText = (sel) => document.querySelector(sel)?.textContent || null;
return {
followers: getText('[data-e2e="followers-count"]'),
likes: getText('[data-e2e="likes-count"]'),
bio: getText('[data-e2e="profile-bio"]')
};
});
return { username, ...data };
} finally {
await browser.close();
}
}
// 사용 예시
const proxyUrl = 'http://user-country-US:PASSWORD@gate.proxyhat.com:8080';
scrapeTikTokCreator('tiktok', proxyUrl).then(console.log);
윤리적 스크레이핑과 공식 API 고려사항
언제 스크레이핑을 피해야 하는가
- 공식 API가 제공하는 데이터: 틱톡은 크리에이터용 분석 대시보드를 제공합니다.
- 비공개/로그인 필요 데이터: 법적 위험이 큽니다.
- 대량 수집: 플랫폼에 부하를 주는 수준의 수집.
- 경쟁사 데이터: 상업적 목적의 타인 데이터 무단 수집.
윤리적 가이드라인
- robots.txt 확인: 틱톡의 robots.txt를 준수합니다.
- 속도 제한: 합리적인 요청 속도를 유지합니다.
- 데이터 최소화: 필요한 데이터만 수집합니다.
- 개인정보 보호: 수집한 데이터를 안전하게 저장하고 GDPR/CCPA를 준수합니다.
- 공식 API 우선: 가능하면 틱톡 Research API 또는 파트너 API를 사용합니다.
틱톡 공식 API 대안
틱톡은 연구자와 파트너를 위한 제한적인 API를 제공합니다:
- TikTok Research API: 학술 연구 목적
- TikTok for Business API: 광고주 및 비즈니스 파트너
- TikTok Creator Marketplace API: 인플루언서 마케팅 플랫폼
이러한 API는 승인이 필요하지만, 데이터 품질과 법적 안전성이 보장됩니다.
주요 요약
- 틱톡은 강력한 봇 탐지 스택을 운영합니다: 기기 지문, WAF, msToken, _signature 등 다층 방어.
- 모바일 레지덴셜 프록시가 가장 높은 성공률을 제공합니다. 틱톡은 모바일 퍼스트 플랫폼이기 때문입니다.
- Playwright/Puppeteer 스텔스 모드로 브라우저 지문을 숨기고 JavaScript 서명을 자연스럽게 생성합니다.
- 로그인 없이 접근 가능한 데이터로 크리에이터 프로필, 공개 비디오, 해시태그, 트렌드 페이지가 있습니다.
- 속도 제한과 세션 로테이션이 차단 방지의 핵심입니다.
- 공식 API가 제공하는 데이터는 우선적으로 사용하고, 스크레이핑은 최후 수단으로 활용합니다.
SERP 추적 및 프록시 로케이션 페이지에서 ProxyHat의 글로벌 레지덴셜 프록시 네트워크에 대해 자세히 알아보세요.






