# Twitch Scraper — Channels, Streams, Clips & Top Games (`tortuga/twitch-scraper`) Actor

Scrape Twitch channels (followers, live status, socials, emails), live streams, VODs, top clips, schedules, top categories and search. No login, no API key.

- **URL**: https://apify.com/tortuga/twitch-scraper.md
- **Developed by:** [Trevor Ortega](https://apify.com/tortuga) (community)
- **Categories:** Videos, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.20 / 1,000 result items

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, Clips & Top Games

Scrape public Twitch data without a login or a Twitch API key: **channel profiles** (followers, partner/affiliate,
live status, current stream, social links, team, business emails from the bio), **videos / VODs**, **top clips**,
**stream schedules**, **live streams** (all of Twitch or per category), **top categories / games** by viewers, and
**search** results for channels or categories. Export to JSON, CSV or Excel, or call it from your app via the API.

### What data does Twitch Scraper extract?

Pick a **mode**. Every item has a `type` field, so mixed datasets stay easy to filter.

| Mode | One item per | Main fields |
|---|---|---|
| `channels` | channel | `login`, `displayName`, `followers`, `broadcasterType` (partner / affiliate), `isLive`, `viewers`, `title`, `gameName`, `streamStartedAt`, `streamTags`, `language`, `team`, `socialLinks`, `emails`, `panels`, `description`, `createdAt`, `lastBroadcastAt`, profile / banner / offline images |
| `videos` | video | `title`, `videoType` (archive / highlight / upload), `status`, `viewCount`, `durationSeconds`, `publishedAt`, `gameName`, `language`, `thumbnailUrl`, `channelLogin`, `url` |
| `clips` | clip | `rank`, `title`, `viewCount`, `durationSeconds`, `createdAt`, `gameName`, `channelLogin`, `creatorLogin` (who clipped it), `vodUrl` (VOD at the clip's timestamp), `thumbnailUrl`, `isFeatured`, `url` |
| `liveStreams` | live stream | `rank`, `channelLogin`, `title`, `viewers`, `startedAt`, `gameName`, `language`, `tags`, `channelFollowers`, `isPartner`, `thumbnailUrl`, `url` |
| `topCategories` | category / game | `rank`, `name`, `viewers`, `liveChannels`, `followers`, `tags`, `boxArtUrl`, `url` |
| `search` | channel or category | same as `channels` (plus `searchQuery`, `searchRank`) or as `topCategories` (plus `searchQuery`) |
| `schedule` | schedule segment | `startAt`, `endAt`, `title`, `categoryName`, `isCancelled`, `isNext`, `channelLogin` |

All items also carry `id` and `scrapedAt`. Live-only channel fields (`viewers`, `streamId`, `streamStartedAt`,
`streamTags`) are `null` / empty while the channel is offline; `title` and `gameName` then show the channel's current
stream title and category, as Twitch shows them on the offline channel page.

### How to scrape Twitch channels

1. Choose **Channel profiles + live status**.
2. Add channel names or URLs (`shroud`, `https://www.twitch.tv/pokimane`), as many as you like.
3. Run. Channels are fetched 30 per request, so thousands of channels take minutes.

```json
{
  "mode": "channels",
  "channels": ["shroud", "pokimane", "https://www.twitch.tv/sodapoppin"],
  "maxItems": 100
}
```

Output (shortened):

```json
{
  "type": "channel",
  "id": "26301881",
  "login": "sodapoppin",
  "displayName": "sodapoppin",
  "url": "https://www.twitch.tv/sodapoppin",
  "description": "Wtf do i write here? Click my stream, or i scream.Business inquiries - sodapoppin@mythictalent.com",
  "followers": 8990164,
  "broadcasterType": "partner",
  "createdAt": "2011-11-22T04:40:56.75883Z",
  "isLive": false,
  "title": "Farming gold for tournament and prepping. | !podcast !merch !gamersupps !starforge",
  "gameName": "World of Warcraft",
  "language": "en",
  "viewers": null,
  "lastBroadcastAt": "2026-10-10T00:17:57.966267Z",
  "team": "otk",
  "teamUrl": "https://www.twitch.tv/team/otk",
  "socialLinks": [
    { "name": "youtube", "title": "YouTube", "url": "https://www.youtube.com/c/sodapoppin" },
    { "name": "twitter", "title": "Twitter", "url": "https://twitter.com/Sodapoppintv/" }
  ],
  "emails": ["sodapoppin@mythictalent.com"],
  "panels": [{ "title": null, "description": null, "linkUrl": "https://gamersupps.gg/poor", "imageUrl": "https://panels.twitch.tv/panel-26301881-image-71e75376-1816-4a8f-9d7f-a398247ce976" }],
  "profileImageUrl": "https://static-cdn.jtvnw.net/jtv_user_pictures/...-profile_image-300x300.png",
  "scrapedAt": "2026-10-10T02:43:20Z"
}
```

`emails` are the addresses the streamer published in the channel bio or About panels (usually for business
inquiries). Nothing hidden or "click to reveal" is collected.

### How to scrape Twitch clips and VODs

- **Videos / VODs**: mode `videos`, your channels, **Video type** (`archive` = past broadcasts, `highlight`,
  `upload` or `all`) and **Video order** (newest or most viewed). Set **Max items per source** to e.g. 20 to get the
  20 newest videos of each channel.
- **Top clips**: mode `clips`, channels and/or categories, **Clips from the last** 24 hours, 7 days, 30 days or all
  time. Clips come sorted by views with `rank`; `vodUrl` links to the moment in the original broadcast.

```json
{
  "mode": "clips",
  "channels": ["xqc"],
  "categories": ["Just Chatting"],
  "clipPeriod": "7d",
  "maxItemsPerSource": 50
}
```

```json
{
  "type": "clip",
  "id": "256760451",
  "rank": 1,
  "url": "https://www.twitch.tv/xqc/clip/AbrasiveEsteemedSeahorseDBstyle-AQK13VBio_zKsRSX",
  "title": "LUL",
  "viewCount": 26016,
  "createdAt": "2026-10-04T02:09:01Z",
  "durationSeconds": 39,
  "gameName": "Grand Theft Auto V",
  "channelLogin": "xqc",
  "creatorLogin": "pankohh",
  "vodUrl": "https://www.twitch.tv/videos/2891086107?t=5h31m27s",
  "period": "7d"
}
```

### How to get top live streams and top games on Twitch

- **Live streams**: mode `liveStreams`. Leave **Categories** empty for the most-watched streams on all of Twitch, or
  add categories (`Just Chatting`, `league-of-legends`, a directory URL) for each category's live streams by
  viewers. **Stream tags** applies Twitch's tag filter (`English`, `Deutsch`, `Español`, `DropsEnabled`, ...).
- **Top categories**: mode `topCategories` returns games and categories ranked by current viewers, with the number
  of live channels and followers.
- **Search**: mode `search` with search terms; choose channels (full channel profiles) or categories.

```json
{ "mode": "liveStreams", "categories": ["Fortnite"], "streamTags": ["English"], "maxItems": 200 }
```

```json
{
  "type": "stream",
  "id": "320682700508",
  "rank": 1,
  "channelLogin": "theburntpeanut",
  "url": "https://www.twitch.tv/theburntpeanut",
  "title": "[DROPS] !Subway X Arc Raiders - Fuel The Raid | w/ HUTCHMF | DAY 2 ...",
  "viewers": 49952,
  "startedAt": "2026-10-09T23:20:03Z",
  "language": "en",
  "tags": ["English", "funny", "gaming", "DropsEnabled"],
  "gameName": "ARC Raiders",
  "channelFollowers": 2568605,
  "isPartner": true
}
```

### Does it work without login or a Twitch API key?

Yes. The Actor reads the same public GraphQL API that Twitch's own apps use, without an account, an OAuth token or
a Helix API key, and without a browser. Runs are fast (300 live streams in about 6 seconds) and the default Apify
datacenter proxy is enough; a residential proxy is not needed.

### Monitor changes on a schedule

Turn on **Only new or changed items** and the Actor remembers what earlier runs of the same input returned. Videos,
clips, search and top-category runs then output only items that are new since the last run; channel runs output a
channel only when it went live or offline or changed its stream title or category; schedule runs report new,
moved, renamed or cancelled segments; live-stream runs report new broadcasts and streams that switched category.
Unchanged items are dropped before they are saved, so they are not charged. Save the input as a task and add a
Schedule in Apify (for example hourly for live status, daily for new VODs); give each watch its own
**Monitoring key** if several schedules share an input. Output items get `changeType` (`new` or `changed`) and,
for changed items, `previousValues` with the old values of the fields that changed.

### Pricing

Pay per result: one channel, video, clip, live stream, category or schedule entry saved to the dataset is one
result. There is no start fee. Channels that do not exist and items skipped by monitoring are free. Platform usage
is small: about $0.01 per 1,000 results on 512 MB.

### Is it legal to scrape Twitch?

The Actor only reads what Twitch shows to any logged-out visitor: public profiles, stream titles, viewer counts,
public videos and clips, and contact details streamers chose to publish in their bio or panels. It does not log in,
does not read chats, subscriptions or private data, and does not download video. Clips and videos are the
creators' content; check Twitch's terms and data-protection rules (e.g. GDPR when you contact streamers) for your
use case. You are responsible for how you use the data.

### Support

Missing a field or found a channel that fails? Open an issue in the **Issues** tab with your input. Issues are
usually answered within a day.

# Actor input Schema

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

channels = one profile per channel (followers, live status, current stream, socials, team). videos = VODs, highlights and uploads of the channels. clips = top clips of channels and/or categories. liveStreams = live streams of the categories, or of all Twitch. topCategories = games and categories ranked by viewers. search = channels or categories matching your terms. schedule = stream schedule of the channels.

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

Twitch channel names or URLs, e.g. shroud or https://www.twitch.tv/shroud. Used by the channels, videos, clips and schedule modes.

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

Category names, slugs or directory URLs, e.g. Just Chatting, league-of-legends or https://www.twitch.tv/directory/category/minecraft. Used by liveStreams (leave empty for all of Twitch) and clips (top clips of the category).

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

Terms to search for in search mode, e.g. minecraft or valorant. Results come in Twitch's relevance order; use Max items per source to keep only the best matches of each term.

## `searchType` (type: `string`):

Search mode: find channels (output as full channel profiles) or categories.

## `videoType` (type: `string`):

Videos mode: past broadcasts (archive), highlights, uploads, or all of them.

## `videoSort` (type: `string`):

Videos mode: newest first or most viewed first.

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

Clips mode: top clips (by views) created in this period.

## `streamTags` (type: `array`):

liveStreams mode: only streams with these Twitch tags, e.g. English, Deutsch, Español or DropsEnabled (Twitch's own tag filter).

## `maxItemsPerSource` (type: `integer`):

Limit for each channel, category or search term (e.g. the 20 newest videos of each channel, or the top 50 streams of each category). Leave empty to use only Max items.

## `maxItems` (type: `integer`):

Stop after this many results in total. You pay per result, so this caps the cost.

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this input returned and output only new items (new videos, clips, streams, channels) or items whose watched fields changed (channels: live status, stream title, category; schedules: time, title, cancellation). Use with a Schedule; unchanged items are not charged.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same input stay separate; defaults to a key derived from the input.

## `proxyConfiguration` (type: `object`):

Apify datacenter proxy (the default) works: Twitch's API does not block it. Residential proxy is not needed.

## Actor input object example

```json
{
  "mode": "channels",
  "channels": [
    "shroud",
    "pokimane",
    "lirik"
  ],
  "searchType": "channels",
  "videoType": "all",
  "videoSort": "newest",
  "clipPeriod": "7d",
  "maxItems": 100,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

# 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",
        "lirik"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/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",
        "lirik",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/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",
    "lirik"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call tortuga/twitch-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tortuga/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/M2bgZLpIN5MOeRLC4/builds/CWJhqs1WDPHktgRsb/openapi.json
