# Twitch Scraper - Streamer Emails, Followers, Streams & Games (`s-r/twitch-scraper`) Actor

Export public Twitch streamer profiles with follower counts, business emails and social links, plus live streams, past broadcasts and top games with viewer totals. Filter streamers by game, language and followers for influencer outreach, sponsorship and gaming analytics.

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

## Pricing

from $3.45 / 1,000 twitch profiles

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 - Streamer Emails, Followers, Live Streams & Games

This Twitch scraper exports public streamer profiles, follower counts, business emails, social links, live streams, past broadcasts and game categories, so influencer marketers, sponsorship teams and gaming analysts can build creator lists and track Twitch stats without a Twitch API key. Start with channel logins, game names, category URLs or a search term. Each dataset row identifies its record type so you can separate creators, content and categories after export.

Typical jobs: find every English Fortnite streamer with more than 10,000 followers and a public business email, check the follower count and live status of a list of creators you already work with, or rank the top games on Twitch by current viewers every hour.

### What the Twitch scraper collects

A profile includes the channel URL, Twitch identifier, display name, biography, follower count, partner and affiliate status, and whether the channel is currently live. Public social links and channel panels are included when Twitch supplies them. The actor extracts business email addresses already published in biographies or panel content. An address is evidence of a public contact detail; it does not establish consent to receive marketing messages or prove that the address remains deliverable.

Live stream rows include the title, broadcaster, game, language, stream identifier, start time and simultaneous viewer count. Archived video rows include a permanent video URL, title, publication time, duration and accumulated views. Game rows include the category name, URL, current viewer total, follower total where available, and the number of current broadcasters. Top categories also carry their position in Twitch's viewer ranking.

### How to scrape Twitch in four steps

1. Choose what to start from: a list of channels, one or more games or category URLs, a search term, or the top-games ranking.
2. For streamer discovery, set `maxStreamsPerGame`, enable `includeStreamerProfiles` and add `minFollowers`, `maxFollowers` or `languages` to narrow the list.
3. Start the run. The actor collects large selections in segments and writes every row to the dataset.
4. Export the dataset as JSON, CSV, Excel or through the Apify API, and filter on `_type` to split profiles, streams and games.

A streamer prospecting run for one game looks like this:

```json
{"games":["Fortnite"],"maxStreamsPerGame":50,"includeStreamerProfiles":true,"languages":["en"],"minFollowers":10000}
```

### Input

Use `channels` for logins such as `shroud`, handles with an initial @, or public channel URLs. The aliases `channelUsernames` and `logins` are also accepted. Channel names are normalized to lowercase and repeated creators are delivered once. You can provide up to 500 channel values in a run.

Use `games` for game names or Twitch directory URLs. `categories` accepts the same values, and `gameName` supplies one additional category. Category URLs can use the current directory/category path or the older directory/game path. Up to 20 category values are accepted. Set `maxStreamsPerGame` to choose the maximum number of unique live streams for each category. Zero returns category information without retrieving its streams. The default is 20 and the maximum is 1,000.

Enable `includeStreamerProfiles` to retrieve the full public profiles of creators discovered through the stream directory. `minFollowers` and `maxFollowers` filter those discovered profiles. They do not filter channels explicitly requested in `channels`. Public panels and email extraction are part of the profile retrieval, so there is no separate contact lookup option to enable.

Set `maxVideosPerChannel` to retrieve recent archived broadcasts as separate content rows. The default is zero; the maximum is 100 per loaded channel. Videos are available only when Twitch exposes them publicly. A creator with fewer available archives returns fewer rows.

Use `languages` to filter category streams by two-letter language codes. Both uppercase and lowercase input are accepted; output language codes are lowercase. Enable `topGames` and set `maxGames` to collect Twitch's ranked category list. `searchQuery`, or several terms in `searchQueries`, discovers channels and categories before retrieving their public data. Search follows the matches Twitch returns and does not promise an exhaustive list of every matching channel.

The `maxResults` alias supplies the fallback limit for top games and streams per category. Explicit `maxGames` and `maxStreamsPerGame` take precedence. Provide at least one channel, category, search term or the top-games option.

The following input was exercised against real Twitch responses:

```json
{"channels":["shroud","lacy","zzqqxxnonexist9876"],"maxVideosPerChannel":5}
```

### Output

The default dataset contains three row types, named by `_type` and `record_type`: `profile`, `post` and `topic`. Every row includes `source`, `platform`, `fetched_at` and discovery context. Profile rows use `profile_url`, `profile_id`, `handle`, `name`, `bio`, `followers`, `links`, `email` and `emails`. An offline creator remains a valid profile, with `is_live` false and unavailable live stream measurements set to null.

Content rows use `post_id`, `post_url`, `author_handle`, `author_id`, `text` and `posted_at`. The `kind` field distinguishes live streams from videos. `viewers` means simultaneous live viewers; `views` appears only on videos and means total plays. These measurements should be compared separately. A live stream links to its creator's channel because Twitch does not offer a permanent public URL for each live broadcast.

Category rows use `topic`, `topic_id`, `url`, `viewers` and `post_count`. Here `post_count` is the current broadcaster count, not the count of videos ever posted in that game. `rank` appears on categories found through `topGames`. `streams_delivered` counts streams returned alongside that category in the current response segment.

A missing explicitly requested channel appears as a diagnostic profile when other results exist. It carries `error: "not_found"` and does not invent a follower count or contact details. If nothing can be found, the run returns no dataset results. Download the dataset in JSON, CSV or another format supported by Apify. The OUTPUT record includes delivered counts and run status.

#### Example output

These rows come from a real run on 2026-10-05 (`examples/channels.json` and `examples/fortnite.json` in the actor source). Long lists such as panels and tags are shortened here; the dataset contains every field described above.

A creator profile:

```json
{
  "_type": "profile",
  "profile_url": "https://www.twitch.tv/shroud",
  "profile_id": "37402112",
  "handle": "shroud",
  "name": "shroud",
  "bio": "I'm back baby",
  "followers": 11293811,
  "is_partner": true,
  "is_affiliate": false,
  "links": ["https://discord.gg/shroud", "https://twitter.com/shroud", "https://youtube.com/shroud", "https://instagram.com/shroud"],
  "email": null,
  "emails": [],
  "is_live": false,
  "viewers": null,
  "channel_game": "AION 2",
  "channel_language": "en",
  "last_broadcast_at": "2026-10-05T01:40:46.877936Z",
  "fetched_at": "2026-10-05T03:41:33.000Z"
}
```

A live stream found in the Fortnite directory:

```json
{
  "_type": "post",
  "kind": "live",
  "post_id": "320656054880",
  "post_url": "https://www.twitch.tv/lacy",
  "author_handle": "lacy",
  "author_followers": 3465410,
  "author_is_partner": true,
  "text": "🎃 LACY X CLIX X PETERBOT 🎃 2027 FNCS TRIO 🎃 PRO SCRIMS 🎃 FNCS TOMORROW 🎃 SUBSCRIBE = NO ADS 🎃 !clipping !youngla",
  "posted_at": "2026-10-04T21:19:31Z",
  "viewers": 17329,
  "language": "en",
  "game_name": "Fortnite",
  "fetched_at": "2026-10-05T03:41:33.000Z"
}
```

The Fortnite category itself:

```json
{
  "_type": "topic",
  "topic": "Fortnite",
  "topic_id": "33214",
  "url": "https://www.twitch.tv/directory/category/fortnite",
  "viewers": 59894,
  "post_count": 5322,
  "followers": 108161645,
  "fetched_at": "2026-10-05T03:41:33.000Z"
}
```

### Use cases for Twitch data

- **Influencer marketing and sponsorship outreach.** Build a list of streamers in your game or niche with follower counts, partner status, language, social links and the business email they publish, then hand it to your CRM.
- **Twitch stats and creator tracking.** Re-run a fixed channel list on a schedule to follow follower growth, live status and what each creator is streaming.
- **Game and category analytics.** Track the top games on Twitch, the number of live channels per category and the viewer distribution across streams for launch monitoring or market research.
- **Agency and talent scouting.** Find smaller creators who stream in a specific language and stay below a follower ceiling, where sponsorship budgets go further.
- **Content research.** Collect recent past broadcasts with titles, duration and views to see which formats a creator repeats.

### Twitch scraper vs. the alternatives

| | This Twitch scraper | Official Twitch API | Streamer email databases | Stats websites |
|---|---|---|---|---|
| Setup | Paste channels or games, run | Register a developer app, manage access tokens and rate limits | Account and subscription | None |
| Profiles and follower counts | Yes, in bulk | Yes, through separate calls | Curated subset | One channel at a time |
| Public business emails and panel links | Yes, when the creator publishes them | No panel content | Yes, sold per contact or per month | No |
| Live streams per game with viewers | Yes, with language and follower filters | Yes | No | Partly |
| Top games ranking | Yes | Yes | No | Yes, on screen |
| Export | JSON, CSV, Excel, API | Your own code | Their format | Usually none |
| Cost | Pay per delivered row | Free, plus your engineering time | Often a fixed fee per contact or plan | Free for browsing |

The official API suits developers building a Twitch integration. This actor suits people who want the resulting dataset: it delivers creators, streams and games as ready rows and adds the public contact details that the API does not return.

### Pricing

The actor metadata distinguishes profile, contact, post and topic events. A successful profile is one profile event; a profile with a public email address additionally contributes one contact event. Each stream or video contributes one post event, and each category row contributes one topic event. Diagnostic missing-channel rows contribute no events. Empty results incur no result charges. Consult the pricing displayed on this actor's Apify page for the active event prices and your maximum run charge.

Free users receive at most ten dataset rows per run. Counts and result events follow the rows actually delivered after that cap. Paid runs can retrieve larger selections within the documented input limits. Choosing streamer profiles or videos adds additional rows, so include them only when those records serve your research.

For example, a run on one game with 50 streams and streamer profiles enabled delivers one category row, up to 50 stream rows and up to 50 profile rows, and adds a contact event only for the profiles that carry a public email. A channel list of 100 creators without videos delivers 100 profile rows plus the contact events for the creators with a public email.

### Completeness and changing data

Twitch streams and viewer totals change while a run is being collected. Pagination removes repeated stream identifiers, but no historical snapshot or exact cross-page viewer ordering is promised. Large runs are collected in successive segments automatically. Direct API consumers can continue with `next_cursor` while repeating the original input. A partial response includes warnings that explain which requested work could not finish. Availability restrictions or interrupted source access can leave fewer records than requested.

When Twitch cannot supply an optional detail, such as social links, about panels, the last broadcast or recent videos, the actor still delivers the profiles, streams and categories it did collect. The run is then marked partial with a warning naming the missing detail, so a lead list without contact links is never mistaken for a complete one. A live stream that Twitch lists without an identifiable broadcaster is skipped rather than guessed; it is not charged, and later pages can still fill the requested number of streams.

### FAQ

#### Do I need a Twitch login?

No. This actor collects publicly available channel, directory and video information. It does not retrieve private account data, subscriber identities or content that requires a login.

#### Will every creator have an email address?

No. An email is returned only when the creator published one in their biography or public panels. Social and panel links may still provide useful contact routes when no email is present. Missing addresses remain null, and the email list remains empty.

#### Can I use follower counts to select sponsorship prospects?

Yes. Enable streamer profiles for a category and set follower thresholds. Those thresholds apply to the discovered creator profiles; stream and category rows remain available so you can assess the context of each prospect.

#### Why are fewer streams returned than the limit?

The limit is a maximum. A language filter, a small category, directory changes or restricted source access can reduce the available unique streams. Streams that Twitch lists without an identifiable broadcaster are skipped and not charged. Inspect the run warnings before treating a partial collection as a complete inventory.

#### Can I compare viewer counts with video views?

Keep the measurements separate. Live `viewers` is an audience at one moment; video `views` is accumulated plays. Use the record kind and collection timestamp when comparing results across runs.

#### Is it legal to scrape Twitch?

The actor only collects information that Twitch shows publicly without logging in. You remain responsible for how you use the data, in particular for contacting people: follow the privacy and anti-spam rules that apply to you, such as GDPR and CAN-SPAM, and Twitch's terms.

#### Do I need a Twitch API key or client ID?

No. You do not register a Twitch developer application or manage tokens. Provide channels, games or a search term and the actor returns the rows.

#### Can I track Twitch stats over time?

Yes. Schedule the actor on Apify with the same channel list or games and compare `followers`, `viewers` and `fetched_at` across runs. Each run is a snapshot of that moment.

#### Does it scrape Twitch chat or clips?

No. This Twitch scraper covers profiles, live streams, past broadcasts and categories. Chat messages and clips are not part of the output.

# Actor input Schema

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

Channel logins, @handles or public Twitch channel URLs.

## `channelUsernames` (type: `array`):

Channel logins, @handles or public Twitch channel URLs.

## `logins` (type: `array`):

Channel logins, @handles or public Twitch channel URLs.

## `games` (type: `array`):

Game names, slugs or Twitch category URLs.

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

Game names, slugs or Twitch category URLs.

## `gameName` (type: `string`):

One game name or category URL; alias for a games entry.

## `searchQuery` (type: `string`):

Search Twitch channels and games; returned channels are fetched as full profiles.

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

Search terms; combined with searchQuery.

## `topGames` (type: `boolean`):

Return Twitch categories ranked by current viewers. Only topic rows are returned.

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

Fallback limit for maxGames and maxStreamsPerGame.

## `maxGames` (type: `integer`):

Maximum number of top categories across all cursor pages.

## `maxStreamsPerGame` (type: `integer`):

Maximum unique live streams per requested category across all pages; zero returns only category data.

## `maxVideosPerChannel` (type: `integer`):

Recent archived broadcasts per loaded channel; zero disables video retrieval.

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

Filter directory streams by two-letter language codes; output language is lowercase.

## `includeStreamerProfiles` (type: `boolean`):

Fetch full creator profiles, public panels and contact addresses for directory streamers.

## `minFollowers` (type: `integer`):

Follower threshold for profiles discovered through categories; explicit channels are not filtered.

## `maxFollowers` (type: `integer`):

Follower threshold for profiles discovered through categories; explicit channels are not filtered.

## `cursor` (type: `string`):

Opaque continuation token. Repeat the original input with this token to retrieve the next request chunk.

## Actor input object example

```json
{
  "channels": [
    "shroud",
    "lacy",
    "zzqqxxnonexist9876"
  ],
  "topGames": false,
  "maxResults": 20,
  "maxVideosPerChannel": 5,
  "includeStreamerProfiles": false
}
```

# Actor output Schema

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

Profile, post (live stream or video) and topic (game or category) rows.

## `output` (type: `string`):

Delivered rows, charges, free-tier status, warnings and the next cursor.

# 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",
        "lacy",
        "zzqqxxnonexist9876"
    ],
    "maxVideosPerChannel": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/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",
        "lacy",
        "zzqqxxnonexist9876",
    ],
    "maxVideosPerChannel": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("s-r/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",
    "lacy",
    "zzqqxxnonexist9876"
  ],
  "maxVideosPerChannel": 5
}' |
apify call s-r/twitch-scraper --silent --output-dataset

```

## MCP server setup

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