Twitch Scraper API: Extract Profiles, VODs, and Clips Without the Hassle
TL;DR: SociaVault provides four Twitch endpoints — profile, user videos (VODs), user schedule, and clip details — each costing 1 credit per request. No OAuth tokens, no app registration, no Twitch Developer Console hoops. Pass a handle, get data. This guide covers all four endpoints with working Python examples.
Two months ago, a developer named Marcus was building an esports talent scouting tool. He started with the official Twitch API. By hour three, he had: one OAuth client-ID, one OAuth secret, a token refresh flow that broke twice, and exactly zero data in his database.
The official Twitch API isn't bad — it's actually well-documented. But the authentication overhead for simple data extraction is absurd when all you need is "give me this streamer's follower count and recent VODs." Marcus needed public profile data, not chat bot permissions or webhook subscriptions.
He switched to SociaVault's Twitch endpoints the next day. His scouting tool was pulling data from 200 streamers by lunch.
The thing is, most Twitch data use cases are read-only. You're pulling profiles, checking VOD history, analyzing clip virality, or monitoring schedules. None of that requires the ability to write to Twitch — so why go through an OAuth flow designed for apps that need write access?
The Four Twitch Endpoints
Here's what's available:
| Endpoint | Path | Cost | Use Case |
|---|---|---|---|
| Profile | /v1/scrape/twitch/profile | 1 credit | Streamer stats, bio, game, followers |
| User Videos | /v1/scrape/twitch/user/videos | 1 credit | VODs, highlights, uploads |
| User Schedule | /v1/scrape/twitch/user/schedule | 1 credit | Streaming schedule |
| Clip | /v1/scrape/twitch/clip | 1 credit | Individual clip details |
All endpoints accept a handle parameter (the streamer's Twitch username) except the clip endpoint, which takes a clip URL.
Endpoint 1: Streamer Profiles
The profile endpoint gives you the core stats you'd see on someone's Twitch channel page.
import requests
API_KEY = "your_sociavault_api_key"
BASE_URL = "https://api.sociavault.com/v1/scrape/twitch"
HEADERS = {"X-API-Key": API_KEY}
def get_twitch_profile(handle):
"""Fetch a Twitch streamer's profile data."""
response = requests.get(
f"{BASE_URL}/profile",
params={"handle": handle},
headers=HEADERS
)
if response.status_code != 200:
print(f"Error: {response.status_code}")
return None
data = response.json()
if data.get("success"):
return data["data"]
return None
# Example usage
profile = get_twitch_profile("shroud")
if profile:
print(f"Display Name: {profile.get('displayName')}")
print(f"Followers: {profile.get('followers', 0):,}")
print(f"Bio: {profile.get('bio', 'No bio')}")
print(f"Last Game: {profile.get('lastBroadcast', {}).get('game', 'Unknown')}")
print(f"Is Live: {profile.get('stream') is not None}")
What you get back:
- Display name, username, ID
- Follower count
- Bio/description
- Profile and banner images
- Current/last game played
- Stream status (live or offline)
- Broadcaster type (partner, affiliate, or none)
- Account creation date
- Last broadcast info
Common use cases:
- Building influencer databases with follower counts and categories
- Checking if a streamer is currently live
- Verifying partner/affiliate status for sponsorship deals
- Tracking follower growth over time (with periodic polling)
Endpoint 2: User Videos (VODs & Highlights)
The videos endpoint returns a streamer's video archive — past broadcasts, highlights, and uploads.
def get_twitch_videos(handle, filter_by="ARCHIVE", sort_by="TIME"):
"""Fetch a streamer's video history.
filter_by: ARCHIVE (past broadcasts), HIGHLIGHT, or UPLOAD
sort_by: TIME (newest first) or VIEWS (most viewed first)
"""
response = requests.get(
f"{BASE_URL}/user/videos",
params={
"handle": handle,
"filter_by": filter_by,
"sort_by": sort_by,
},
headers=HEADERS
)
if response.status_code != 200:
return None
data = response.json()
if data.get("success"):
return data["data"]
return None
# Get past broadcasts sorted by views
vods = get_twitch_videos("pokimane", filter_by="ARCHIVE", sort_by="VIEWS")
if vods:
videos = vods.get("videos", [])
print(f"Found {len(videos)} VODs\n")
for video in videos[:5]:
title = video.get("title", "Untitled")[:60]
views = video.get("viewCount", 0)
duration = video.get("lengthSeconds", 0)
hours = duration // 3600
minutes = (duration % 3600) // 60
game = video.get("game", {}).get("name", "Unknown")
print(f" {title}")
print(f" Views: {views:,} | Duration: {hours}h {minutes}m | Game: {game}")
print()
Filter options:
| Value | Description |
|---|---|
ARCHIVE | Past broadcasts (auto-saved VODs) |
HIGHLIGHT | Creator-curated highlights |
UPLOAD | Manually uploaded videos |
Sort options:
| Value | Description |
|---|---|
TIME | Newest first (default) |
VIEWS | Most viewed first |
Pagination: The response includes a cursor value. Pass it back as the cursor parameter to get the next page.
def get_all_videos(handle, filter_by="ARCHIVE", max_pages=5):
"""Paginate through all videos for a streamer."""
all_videos = []
cursor = None
for page in range(max_pages):
params = {
"handle": handle,
"filter_by": filter_by,
"sort_by": "TIME",
}
if cursor:
params["cursor"] = cursor
response = requests.get(
f"{BASE_URL}/user/videos",
params=params,
headers=HEADERS
)
if response.status_code != 200:
break
data = response.json()
if not data.get("success"):
break
videos = data.get("data", {}).get("videos", [])
all_videos.extend(videos)
cursor = data.get("data", {}).get("cursor")
if not cursor:
break
return all_videos
Endpoint 3: Streamer Schedule
The schedule endpoint returns a streamer's planned broadcast times — useful for knowing when they intend to be live.
def get_twitch_schedule(handle):
"""Fetch a streamer's broadcast schedule."""
response = requests.get(
f"{BASE_URL}/user/schedule",
params={"handle": handle},
headers=HEADERS
)
if response.status_code != 200:
return None
data = response.json()
if data.get("success"):
return data["data"]
return None
# Example
schedule = get_twitch_schedule("cohhcarnage")
if schedule:
segments = schedule.get("segments", [])
print(f"Schedule has {len(segments)} upcoming segments\n")
for segment in segments[:7]:
title = segment.get("title", "Untitled stream")
start = segment.get("startAt", "TBD")
end = segment.get("endAt", "TBD")
category = segment.get("category", {}).get("name", "No category")
print(f" {start[:10]} | {title} | {category}")
What you get:
- Scheduled stream segments with start/end times
- Stream titles (if set in advance)
- Categories/games planned
- Vacation/hiatus indicators
- Recurring vs. one-time segments
Use cases:
- Monitoring schedule consistency (do they stream when they say they will?)
- Planning sponsorship activations around confirmed stream times
- Competitive intel — know when rivals will be live before they go live
Endpoint 4: Clip Details
The clip endpoint takes a Twitch clip URL and returns full metadata about that clip.
def get_twitch_clip(clip_url):
"""Fetch details about a specific Twitch clip."""
response = requests.get(
f"{BASE_URL}/clip",
params={"url": clip_url},
headers=HEADERS
)
if response.status_code != 200:
return None
data = response.json()
if data.get("success"):
return data["data"]
return None
# Example
clip = get_twitch_clip("https://clips.twitch.tv/TastyBrightPigDuDudu-abc123xyz")
if clip:
print(f"Title: {clip.get('title')}")
print(f"Streamer: {clip.get('broadcaster', {}).get('displayName')}")
print(f"Views: {clip.get('viewCount', 0):,}")
print(f"Duration: {clip.get('durationSeconds', 0)}s")
print(f"Game: {clip.get('game', {}).get('name')}")
print(f"Created: {clip.get('createdAt')}")
print(f"Clipper: {clip.get('curator', {}).get('displayName')}")
What you get:
- Clip title, duration, view count
- Broadcaster info (who was streaming)
- Curator info (who clipped it)
- Game/category at time of clip
- Creation timestamp
- Thumbnail and video URLs
Putting It All Together: Streamer Assessment Script
Here's a combined script that profiles a streamer across all dimensions:
import requests
import json
from datetime import datetime
API_KEY = "your_sociavault_api_key"
BASE_URL = "https://api.sociavault.com/v1/scrape/twitch"
HEADERS = {"X-API-Key": API_KEY}
def assess_streamer(handle):
"""Full streamer assessment using all endpoints."""
print(f"\n{'='*50}")
print(f"TWITCH ASSESSMENT: {handle}")
print(f"{'='*50}\n")
assessment = {"handle": handle, "timestamp": datetime.now().isoformat()}
# Profile (1 credit)
profile_resp = requests.get(
f"{BASE_URL}/profile",
params={"handle": handle},
headers=HEADERS
)
if profile_resp.status_code == 200 and profile_resp.json().get("success"):
profile = profile_resp.json()["data"]
assessment["profile"] = {
"display_name": profile.get("displayName"),
"followers": profile.get("followers", 0),
"broadcaster_type": profile.get("broadcasterType", "none"),
"is_live": profile.get("stream") is not None,
"last_game": profile.get("lastBroadcast", {}).get("game"),
}
print(f"Profile: {profile.get('displayName')} | {profile.get('followers', 0):,} followers")
print(f" Type: {profile.get('broadcasterType', 'none')} | Live: {profile.get('stream') is not None}")
# Videos (1 credit)
videos_resp = requests.get(
f"{BASE_URL}/user/videos",
params={"handle": handle, "filter_by": "ARCHIVE", "sort_by": "TIME"},
headers=HEADERS
)
if videos_resp.status_code == 200 and videos_resp.json().get("success"):
videos = videos_resp.json()["data"].get("videos", [])
total_views = sum(v.get("viewCount", 0) for v in videos)
avg_views = total_views // len(videos) if videos else 0
avg_duration_hrs = sum(
v.get("lengthSeconds", 0) for v in videos
) / max(len(videos), 1) / 3600
assessment["videos"] = {
"recent_vod_count": len(videos),
"avg_views": avg_views,
"avg_duration_hours": round(avg_duration_hrs, 1),
"total_views_recent": total_views,
}
print(f"\nVODs: {len(videos)} recent | Avg views: {avg_views:,} | Avg duration: {avg_duration_hrs:.1f}h")
# Schedule (1 credit)
schedule_resp = requests.get(
f"{BASE_URL}/user/schedule",
params={"handle": handle},
headers=HEADERS
)
if schedule_resp.status_code == 200 and schedule_resp.json().get("success"):
schedule = schedule_resp.json()["data"]
segments = schedule.get("segments", [])
assessment["schedule"] = {
"has_schedule": len(segments) > 0,
"upcoming_streams": len(segments),
}
print(f"\nSchedule: {'Set' if segments else 'Not set'} | {len(segments)} upcoming segments")
# Total: 3 credits for a full assessment
print(f"\nTotal credits used: 3")
return assessment
# Run assessment
result = assess_streamer("shroud")
print(json.dumps(result, indent=2, default=str))
Credit Cost Summary
| Operation | Credits | What You Get |
|---|---|---|
| Single profile check | 1 | Full streamer stats |
| VOD history (1 page) | 1 | ~20 recent videos |
| Full VOD history (5 pages) | 5 | ~100 videos |
| Schedule check | 1 | All planned streams |
| Single clip lookup | 1 | Complete clip metadata |
| Full streamer assessment | 3 | Profile + VODs + schedule |
| Batch assess 50 streamers | 150 | Full portfolio overview |
Comparison: SociaVault vs. Official Twitch API
| Factor | Official Twitch API | SociaVault |
|---|---|---|
| Authentication | OAuth2 (Client ID + Secret + Token) | Single API key |
| Setup time | 30-60 minutes | 2 minutes |
| Rate limits | 800 requests/minute (with token) | No rate limits |
| Token management | Tokens expire, need refresh flow | No tokens |
| App review required | For some endpoints, yes | No |
| Webhook support | Yes (complex setup) | No (polling only) |
| Write access | Yes (chat, clips, etc.) | No (read-only) |
If you need to do things on Twitch (send chat messages, create clips, manage subscriptions), the official API is required. If you need to read data from Twitch, SociaVault removes the ceremony.
Error Handling and Best Practices
def safe_twitch_request(endpoint, params, retries=3):
"""Robust request wrapper with retries."""
for attempt in range(retries):
try:
response = requests.get(
f"{BASE_URL}/{endpoint}",
params=params,
headers=HEADERS,
timeout=30
)
if response.status_code == 200:
data = response.json()
if data.get("success"):
return data["data"]
else:
print(f"API returned error: {data.get('error')}")
return None
elif response.status_code == 402:
print("Insufficient credits")
return None
elif response.status_code == 429:
# Rate limited — wait and retry
import time
time.sleep(2 ** attempt)
continue
else:
print(f"HTTP {response.status_code} on attempt {attempt + 1}")
except requests.exceptions.Timeout:
print(f"Timeout on attempt {attempt + 1}")
except requests.exceptions.ConnectionError:
print(f"Connection error on attempt {attempt + 1}")
return None
Frequently Asked Questions
Does the profile endpoint show if someone is currently live?
Yes. If the streamer is live, the profile response includes a stream object with current viewer count, game, and stream title. If they're offline, stream is null.
Can I get subscriber count (not just followers)?
Twitch subscriber counts are private — they're only visible to the streamer and their moderators. The profile endpoint returns follower count, which is public.
How far back do VODs go?
Twitch auto-deletes VODs after 14 days for non-partners (60 days for partners/Turbo users). The videos endpoint returns whatever is currently available on the channel.
Can I search for Twitch streamers by game or category?
The current endpoints are per-streamer. You need to know the handle. For discovery by category, you'd combine this with other data sources to build your initial streamer list, then use SociaVault for detailed profile data.
What if a streamer changed their username?
Use their current handle. Twitch allows name changes, and the API resolves based on current username. Old handles won't work if they've been changed.
Are there any streamers that can't be looked up?
Banned or suspended accounts may return errors. Private/deleted accounts won't return data. Otherwise, any public Twitch channel is accessible.
Try SociaVault free → — 50 free credits, enough to assess 16 streamers end-to-end. No OAuth tokens, no Twitch Developer Console, just data.
Related reading:
- How Esports Teams Use Twitch Data for Sponsorships — Business use cases
- Monitor Twitch Streamer Schedules at Scale — Monitoring systems
- Build a Social Media Analytics Dashboard — Dashboard tutorial
- API Rate Limiting Strategies — Scaling your requests
Found this helpful?
Share it with others who might benefit
Ready to Try SociaVault?
Start extracting social media data with our powerful API. No credit card required.