# Twitch Scraper — Channels, Streams, Videos, Clips & Chat (`teodor_banea/twitch-scraper`) Actor

Scrape public Twitch data without login: channel profiles with followers and live status, live streams by category and language, top streams and categories, channel videos, clips, stream schedules, search and VOD chat replay. Flat rows, date filters, GDPR-minded.

- **URL**: https://apify.com/teodor_banea/twitch-scraper.md
- **Developed by:** [Banea Teodor](https://apify.com/teodor_banea) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Twitch Scraper — Channels, Streams, Videos, Clips, Schedule & Chat

### What does Twitch Scraper do?

Twitch Scraper collects public Twitch data — no login, no proxy setup, no API key needed. Pick one mode per run:

| Mode | You enter | You get |
|---|---|---|
| **Channel profiles** | channel names or URLs (up to 1,000 per run) | followers, partner / affiliate, live now (viewers, title, category, tags), last stream, video count, team, images; optional social links, business e-mail and panels |
| **Live streams in categories** | category names, slugs or URLs (+ optional languages) | live streams with viewers, start time, language, tags, preview image and broadcaster followers |
| **Top live streams** | — (optional languages) | the most watched live streams right now — Twitch lists the top 30 per language, so add languages for more |
| **Top categories** | — | the 100 most watched categories with viewers, live channels, followers, box art and tags |
| **Channel videos** | channel names or URLs | past broadcasts, highlights and uploads with length, views, category, chapters |
| **Clips** | channels and/or categories + period | clips with views, duration, clip creator, source video and offset |
| **Search** | search terms | channels (full profile rows), categories or videos |
| **Stream schedules** | channel names or URLs | the next 25 upcoming schedule segments (start, end, title, categories, cancelled) |
| **VOD chat replay** | video IDs or video URLs | every chat message of a past broadcast with its offset, time, text and emotes — authors pseudonymised by default |

Every row is flat, has the same keys for its type (missing values are `null`, never left out), uses ISO 8601 UTC dates, integer counters and absolute image URLs.

### Why use this Actor?

- **Nine data types in one Actor** — profiles, live directories, videos, clips, schedules, search and chat replay.
- **Fast and cheap** — up to 35 channels per request; 1,000 channel profiles take about 2 minutes.
- **More than a first page** — Twitch shows visitors 30-100 items per list (other Twitch actors stop at 30 per page); this Actor reads category and channel lists in several orders, languages and types and merges them without duplicates.
- **Privacy-minded defaults** — social links, e-mails, panels and chat usernames are off unless you turn them on.
- **Scheduling-friendly** — "Started / created after" keeps only new streams, videos and clips; the Actor leaves no storage behind in your account.

### How much does it cost?

The Actor is priced per result: **$1.50 per 1,000 rows** plus **$0.005 per run start**. Platform usage is included.

| Example run | Rows | Price |
|---|---|---|
| 20 channel profiles (the prefilled input) | 20 | $0.035 |
| 1,000 channel profiles | 1,000 | $1.505 |
| 1,000 live streams of one category in 11 languages | 1,000 | $1.505 |
| 300 newest videos of 3 channels | 300 | $0.455 |
| 2,000 chat messages of one broadcast | 2,000 | $3.005 |
| The whole chat of a busy 2.4-hour broadcast (≈ 73,000 messages) | 73,000 | ≈ $110 |

Channels, categories or videos that do not exist produce no rows and cost nothing beyond the start fee.

### Input

| Field | Description | Example |
|---|---|---|
| `mode` | What to scrape (see the table above). | `"categoryStreams"` |
| `channels` | Channel names or channel URLs. | `["examplestreamer", "https://www.twitch.tv/anotherchannel"]` |
| `categories` | Category names as Twitch shows them, slugs or category URLs. | `["Just Chatting", "valorant"]` |
| `searchQueries` / `searchTarget` | Search terms and what to search for (channels, categories, videos). | `["speedrun"]`, `"channels"` |
| `videoIds` | Video IDs or URLs for chat replay. | `["https://www.twitch.tv/videos/1234567890"]` |
| `languages` | Stream languages (category and top streams). Each language is its own list, so several languages also return more streams. | `["en", "de"]` |
| `sort` | Streams: most viewers, fewest viewers, most recent. Videos: newest, most viewed. | `"viewers"` |
| `videoTypes` | Past broadcasts, highlights, uploads. | `["ARCHIVE"]` |
| `clipPeriod` | Last 24 hours, 7 days, 30 days or all time. | `"LAST_WEEK"` |
| `startedAfter` | Keep only streams started, videos created and clips created from this date or period on. | `"2026-10-01"` or `"7 days"` |
| `maxChatMessagesPerVideo`, `chatFromSeconds`, `chatToSeconds` | Chat replay limit per video (0 = up to 100,000) and time window. | `2000`, `0`, `3600` |
| `includeContactInfo`, `includePanels`, `includeChatUsernames` | Optional personal / long fields (all off by default). | `false` |
| `maxResultsPerTarget` | Rows per channel, category or search term (0 = all Twitch shows). | `100` |
| `maxResults` | Rows per run (0 = unlimited, capped at 10,000). | `200` |

### Output

One dataset per run; the row type follows the mode. Example rows (fictitious):

```json
{
    "rowType": "channel",
    "channelId": "123456789",
    "login": "examplestreamer",
    "displayName": "ExampleStreamer",
    "url": "https://www.twitch.tv/examplestreamer",
    "description": "Variety streams every evening.",
    "createdAt": "2019-04-01T12:00:00.000Z",
    "followers": 125000,
    "isPartner": false,
    "isAffiliate": true,
    "isLive": true,
    "viewers": 1520,
    "streamTitle": "Ranked grind until diamond",
    "streamGame": "Example Game",
    "streamStartedAt": "2026-10-22T17:00:00.000Z",
    "streamLanguage": "en",
    "streamTags": ["English", "Chill"],
    "isMature": false,
    "language": "en",
    "lastStreamAt": "2026-10-22T17:00:00.000Z",
    "lastStreamTitle": "Ranked grind until diamond",
    "lastStreamGame": "Example Game",
    "totalVideos": 340,
    "teamName": "Example Team",
    "primaryColorHex": "#00ADFF",
    "profileImageUrl": "https://static-cdn.jtvnw.net/jtv_user_pictures/example-profile_image-300x300.png",
    "bannerImageUrl": "https://static-cdn.jtvnw.net/jtv_user_pictures/example-profile_banner-480.png",
    "offlineImageUrl": null,
    "socialLinks": [],
    "businessEmail": null,
    "panels": [],
    "searchQuery": null,
    "scrapedAt": "2026-10-23T10:00:00.000Z"
}
```

```json
{
    "rowType": "chatMessage",
    "messageId": "00000000-0000-4000-8000-000000000001",
    "videoId": "1234567890",
    "videoOffsetSeconds": 3605,
    "createdAt": "2026-10-21T19:43:05.120Z",
    "authorId": null,
    "authorLogin": "user-1a2b3c4d",
    "authorDisplayName": null,
    "text": "gg :ExampleEmote:",
    "emoteNames": ["ExampleEmote"],
    "isSubscriber": true,
    "isModerator": false,
    "scrapedAt": "2026-10-23T10:00:00.000Z"
}
```

Stream, video, clip, category and schedule rows are documented field by field in the dataset schema (the Output tab has one table view per row type). Channels, categories or videos that could not be found or read are listed in the run's key-value store under **ERRORS**.

### Tips and tricks

- **What is complete and what is a sample.** Twitch shows visitors only the first 100 items of each list (30 for the site-wide top streams). The Actor reads each list in several orders (and languages for streams; video types for videos; periods for clips) and merges them, which typically gives a few hundred streams per category or videos per channel — not a full archive. For more live streams of a big category, add languages. Search returns up to about 1,000 results per term. Search returns what Twitch shows, and the status says when that is fewer than the matches Twitch counts ("Twitch shows 923 of 7,984 matches"). Channel profiles and chat replay are complete; schedules are the next 25 upcoming segments, not the history.
- **Chat replay size and cost.** Busy broadcasts have 3.7-8.5 chat messages per second: a busy 2.4-hour broadcast ≈ 73,000 messages (≈ $110 at $1.50 per 1,000), a busy 10-hour one ≈ 133,000 (≈ $200). About 27 new messages are read per request. Use the time window (`chatFromSeconds` / `chatToSeconds`) and `maxChatMessagesPerVideo` to read only the part you need. Twitch deletes past broadcasts after 7-60 days.
- **Stream languages.** Twitch files streams under the broadcaster's language; the Actor also drops the few streams whose own language is another one.
- **Followers lists and the live viewer list** are not public on Twitch — the Actor returns the counts only.
- **Category names** must match Twitch ("Just Chatting"); the slug from the category URL (`just-chatting`) always works.

### Scheduling

Schedule the Actor (for example hourly or daily) with **Started / created after** set to a period slightly longer than the schedule interval (e.g. `"2 days"` for a daily run). Rows carry stable IDs (`streamId`, `videoId`, `clipId`, `messageId`), so downstream tools can de-duplicate the small overlap. The Actor keeps nothing between runs — no named storage is created in your account.

### Personal data

Streamers are public figures; their public profile data is returned. Note that a public bio or a video description can itself contain an e-mail address or other contact details even when contact info is off — the text is returned as written. Contact details (social links, business e-mail found in descriptions or panels) and panel texts are only added when you turn them on. Chat authors are replaced by a pseudonym that stays the same within one run ("user-1a2b3c4d") unless you turn on real usernames — names inside the message text (@mentions, the viewer named in subscription and gift notices, gift recipients) get the same pseudonyms; chat colours and badge lists are never output (only whether the author was a subscriber or moderator). Make sure you have a legitimate purpose when you process personal data.

### Integrations

Export the dataset as JSON, CSV, Excel or XML, or connect it to Google Sheets, Zapier, Make, Slack, Airbyte or your own code through the Apify API and webhooks. Each run has table views per row type (Channels, Streams, Videos, Clips, Categories, Schedule, Chat).

# Changelog

This Actor's version history is a separate document: https://apify.com/teodor_banea/twitch-scraper/changelog.md

# Actor input Schema

## `mode` (type: `string`):

Choose what to collect. Channel profiles, videos, clips and schedules use Channels; category streams and category clips use Categories; search uses Search terms; chat replay uses Video IDs.

## `channels` (type: `array`):

Enter Twitch channel names or channel URLs (e.g. "streamer_name" or "https://www.twitch.tv/streamer_name"). Used by Channel profiles, Channel videos, Clips and Stream schedules. Up to 1,000 per run.

## `categories` (type: `array`):

Enter category (game) names exactly as Twitch shows them (e.g. "Just Chatting"), slugs from the category URL (e.g. "just-chatting") or category URLs. Used by Live streams in categories and Clips.

## `searchQueries` (type: `array`):

Enter what to search for (Search mode). Twitch shows up to about 1,000 results per term.

## `searchTarget` (type: `string`):

Choose what the search returns (Search mode).

## `videoIds` (type: `array`):

Enter video IDs or video URLs (e.g. "https://www.twitch.tv/videos/1234567890") whose chat replay to read (VOD chat replay mode).

## `languages` (type: `array`):

Keep only streams in these languages (Live streams in categories, Top live streams). Each language is read as its own list, so choosing several also returns more streams — Twitch lists the top 30 live streams per language. Leave empty for all languages.

## `sort` (type: `string`):

Choose the order to read first. Streams: most viewers (default), fewest viewers (category streams only) or most recently started. Videos: newest (default) or most viewed. Other orders are added automatically when more rows are wanted than the first list holds.

## `videoTypes` (type: `array`):

Choose which videos to read (Channel videos mode). Leave empty for all three.

## `clipPeriod` (type: `string`):

Choose how far back clips may have been created (Clips mode). Twitch lists clips by views or trending, not by date.

## `startedAfter` (type: `string`):

Keep only streams started, videos created and clips created on or after this date (UTC), or within a recent period such as "7 days". Useful for scheduled runs.

## `maxChatMessagesPerVideo` (type: `integer`):

Limit the chat messages read from each video (VOD chat replay). 0 = up to 100,000 per video. A busy broadcast has 4-9 messages per second (a busy 10-hour broadcast ≈ 130,000), so use the Chat from / Chat to window to read only the part you need.

## `chatFromSeconds` (type: `integer`):

Start reading the chat replay at this point of the video (VOD chat replay).

## `chatToSeconds` (type: `integer`):

Stop reading the chat replay at this point of the video (VOD chat replay). Leave empty for the end of the video.

## `includeContactInfo` (type: `boolean`):

Add the channel's social media links and the business e-mail written in its description or panels (Channel profiles and channel search). Turn on only if you have a legitimate reason to process contact details.

## `includePanels` (type: `boolean`):

Add the panels under the channel's About section (title, text, link, image). Panel text can be long.

## `includeChatUsernames` (type: `boolean`):

Output the real usernames of chat authors (VOD chat replay). By default each author gets a stable pseudonym for the run ("user-1a2b3c4d"), which keeps per-author counts possible without personal data.

## `maxResultsPerTarget` (type: `integer`):

Limit the rows taken from each channel, category or search term. 0 = as many as Twitch shows (a few hundred per category or channel).

## `maxResults` (type: `integer`):

Limit the total rows of the run. 0 = unlimited (capped at 10,000 to prevent a surprise bill).

## Actor input object example

```json
{
  "mode": "channels",
  "channels": [
    "shroud",
    "pokimane"
  ],
  "categories": [
    "Just Chatting",
    "valorant"
  ],
  "searchQueries": [
    "speedrun"
  ],
  "searchTarget": "channels",
  "videoIds": [
    "https://www.twitch.tv/videos/1234567890"
  ],
  "videoTypes": [
    "ARCHIVE",
    "HIGHLIGHT",
    "UPLOAD"
  ],
  "clipPeriod": "LAST_DAY",
  "maxChatMessagesPerVideo": 2000,
  "includeContactInfo": false,
  "includePanels": false,
  "includeChatUsernames": false,
  "maxResultsPerTarget": 100,
  "maxResults": 20
}
```

# Actor output Schema

## `results` (type: `string`):

Every row of the run as JSON.

## `channels` (type: `string`):

Channel profiles: followers, live status, current and last stream, team, images.

## `streams` (type: `string`):

Live streams: title, viewers, start, language, category, tags, broadcaster followers.

## `videos` (type: `string`):

Videos: type, dates, length, views, category, chapters.

## `clips` (type: `string`):

Clips: title, views, duration, broadcaster, clip creator, source video and offset.

## `categories` (type: `string`):

Categories: viewers, live channels, followers, box art, tags.

## `schedule` (type: `string`):

Schedule segments: start, end, title, categories, cancelled.

## `chat` (type: `string`):

Chat replay: offset, time, author pseudonym, text, emotes, subscriber / moderator.

## `resultsCsv` (type: `string`):

The same rows as a CSV download.

## `errors` (type: `string`):

Channels, categories or videos that could not be found or read. Only present when something went wrong.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "channels": [
        "shroud",
        "pokimane"
    ],
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("teodor_banea/twitch-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "channels": [
        "shroud",
        "pokimane",
    ],
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("teodor_banea/twitch-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "channels": [
    "shroud",
    "pokimane"
  ],
  "maxResults": 20
}' |
apify call teodor_banea/twitch-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,teodor_banea/twitch-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/leOfvrAUUNTPpwHQG/builds/gokhQcoCqNG3Kcyz8/openapi.json
