Twitch Scraper — Channels, Streams, Clips & VODs
Pricing
from $2.10 / 1,000 results
Twitch Scraper — Channels, Streams, Clips & VODs
Scrapes public Twitch data with no login or API key: channel profiles and follower counts, live stream status and viewers, top categories, clips, past broadcasts and search. Anonymous access is capped at 30 rows per query by Twitch, and every run reports it.
Pricing
from $2.10 / 1,000 results
Rating
0.0
(0)
Developer
Ibnu Adzim
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Public Twitch data, with no login, no API key and no OAuth app to register.
⚠️ Requires a residential proxy
Twitch gates this API by exit-IP reputation. From a residential connection every request succeeds. From a datacenter IP — which is what Apify runs on by default — Twitch answers
failed integrity checkon even a single simple lookup, and a freshly mintedClient-Integritytoken does not lift it (verified on real cloud runs, bare and through two datacenter proxy groups).Set
proxyConfigurationto Apify Proxy with theRESIDENTIALgroup before running. Without it every row comes back as anintegrity_refusederror naming this exact cause — the actor fails loudly rather than returning empty data.
Six things in one actor, chosen with a mode setting:
| Mode | You give it | You get back |
|---|---|---|
| Channel profiles | channel names or URLs | profile, follower count, live status, social links |
| Live streams | a category name (or nothing) | who's live now, viewers, title, tags, category |
| Top categories | — | the most-watched categories right now, with viewer counts |
| Clips | channel names | top clips, views, duration, who clipped them |
| Videos (VODs) | channel names | past broadcasts, highlights, uploads |
| Search | search terms | matching channels and categories |
Why use this actor
- No credentials at all. Twitch's official API needs a registered developer app and an OAuth token. This needs neither — nothing to set up, nothing to expire.
- Live status in one field.
isLiveis a real boolean, plus viewer count, title, category and tags when the channel is streaming. - Exact numbers. Follower counts and viewer counts come back as integers
(
11287668), not"11.2M". - Working image URLs. Twitch serves preview images as templates containing
{width}x{height}; those are filled in, so the URLs actually load. - Honest about limits. Every run writes a summary row stating the 30-row ceiling and why a result is the size it is.
The one limit you need to know
Twitch caps anonymous access at 30 rows per query, and refuses pagination.
Every cursor is rejected with failed integrity check. That was tested hard
before this actor was designed around it — cursors inlined and as typed
variables, from the first/middle/last edge, across five different connections,
with a real integrity token, with device and session headers, and via Apollo
persisted queries. It is structural, not a missing header.
So this actor does not promise deep crawls. Coverage comes from widening the query, and that genuinely works:
- More channels or categories in
queries— each is its own 30. - Clips: pick several time periods. They barely overlap. Measured on one channel: last week (25 clips) + last month (30) = 54 unique clips.
- Live streams: pick several languages. The same category in three languages is three separate result sets.
Anyone claiming unlimited anonymous Twitch pagination is either using the official OAuth API or hasn't hit the ceiling yet.
Input
{"mode": "channel","queries": ["shroud", "https://www.twitch.tv/kaicenat"],"maxItems": 30}
| Field | Type | Description |
|---|---|---|
mode | string | channel, streams, games, clips, videos, search. |
queries | array | Channel names/URLs, category names, or search terms — depends on mode. Empty is valid for streams (global) and games. |
maxItems | integer | Rows per query, max 30 (Twitch's ceiling). |
clipPeriods | array | Clips mode: LAST_DAY, LAST_WEEK, LAST_MONTH, ALL_TIME. Several = more unique clips. |
clipSort | string | VIEWS_DESC (dependable), TRENDING, CREATED_AT_DESC. |
broadcastType | string | Videos mode: ARCHIVE, HIGHLIGHT, UPLOAD, PAST_PREMIERE. |
videoSort | string | TIME or VIEWS. |
streamSort | string | VIEWER_COUNT, RECENT, RELEVANCE. |
languages | array | Live streams mode: restrict to broadcast languages (EN, ES, …). |
maxConcurrency | integer | Requests in flight. Default 4. |
minRequestInterval | number | Seconds between request starts. Default 0.3. |
Output
Rows share one envelope, told apart by recordType: CHANNEL, STREAM,
GAME, CLIP, VIDEO, QUERY_SUMMARY, ERROR.
CHANNEL
{"_input": "shroud","recordType": "CHANNEL","queryMode": "channel","channelId": "37402112","channelLogin": "shroud","channelName": "shroud","url": "https://www.twitch.tv/shroud","description": "I'm back baby","followers": 11287668,"isPartner": true,"createdAt": "2012-11-03T15:50:32Z","primaryColorHex": "00ADFF","avatarUrl": "https://static-cdn.jtvnw.net/jtv_user_pictures/...","socialLinks": [{ "name": "discord", "title": "Discord", "url": "https://discord.gg/shroud" }],"isLive": false,"streamGameName": "WARDOGS","lastBroadcastTitle": "stream stops when my bank account hits 0$"}
When the channel is live it also carries liveTitle, liveViewerCount,
liveStartedAt, liveGameName, liveTags and livePreviewImageUrl.
STREAM
{"recordType": "STREAM", "queryMode": "streams", "resultRank": 1,"streamId": "316782123862","title": "LIVE: BLAST Premier Open Porto 2026 - MOUZ vs Falcons","viewerCount": 56973,"startedAt": "2026-08-31T08:11:01Z","channelLogin": "blastpremier","channelFollowers": 1284410,"gameName": "Counter-Strike","tags": ["Esports", "English", "CS2"],"previewImageUrl": "https://static-cdn.jtvnw.net/previews-ttv/live_user_blastpremier-1920x1080.jpg"}
CLIP
{"recordType": "CLIP", "resultRank": 1, "clipPeriod": "LAST_WEEK","clipId": "1222162697","title": "XDDD","url": "https://www.twitch.tv/shroud/clip/TentativeTenuousNeanderthalPanicBasket-...","viewCount": 153,"durationSeconds": 11,"createdAt": "2026-08-25T21:25:52Z","curatorLogin": "bonus_00","gameName": "WARDOGS"}
| Field | Type | Description |
|---|---|---|
channelLogin / channelName | string | Login (URL name) and display name. |
followers | integer | Exact follower count. |
isLive | boolean | Whether the channel is streaming right now. |
viewerCount | integer | Live viewers. |
tags | array | Stream tags. |
gameName | string | Category. |
viewCount / durationSeconds | integer | Clip and VOD metrics. |
previewImageUrl / thumbnailUrl | string | Ready-to-use image URLs. |
notes | array | Honesty flags on the summary row. |
ERROR
Every input produces at least one row, so a bad channel is visible in the data:
{"_input": "zzz_no_such_user_xyz","recordType": "ERROR","_error": "not_found","_errorDetail": "Twitch returned no channel for 'zzz_no_such_user_xyz'. The name may be misspelled, renamed, banned or deleted — this is a normal 200 with a null body, not a fetch failure."}
Known limits
- 30 rows per query, no pagination. Explained above. Widen the query instead.
TRENDINGclips are often empty, andCREATED_AT_DESCcurrently answers a server error upstream.VIEWS_DESCis the dependable sort; the run says so when a sort returns nothing.- Empty VOD lists are normal. Twitch auto-deletes past broadcasts after 7–60 days depending on channel status.
- No chat, no subscriber lists, no email addresses, no follower lists. Those are either private or require an authenticated account.
- Stream ordering is approximate. Twitch layers its own recommendation weighting over the sort you pick.