# Twitch Streams Scraper (`axiomworks/twitch-streams-scraper`) Actor

Collect Twitch live streams, top categories, or channel profiles and return viewer counts, titles, language, followers, category details, and tags. Live stream queries can fan out across categories and languages; each query returns up to 30 streams, without requiring a Twitch login or OAuth token.

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

## Pricing

from $2.97 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Streams Scraper

**Returns:** one row per live stream, category or channel with title, viewersCount, language, channelLogin, followers, categoryName and sourceUrl.
**Input:** `{"mode":"liveStreams","categories":["valorant"],"languages":["EN"],"maxItems":20}`
**Best for:** tracking live viewers by game, finding creators in a viewer band, and checking stream titles for events.

```json
{
  "id": "320588667868",
  "title": "EG FNS | G2 vs Team Liquid - VCT Champions Group Stage Elimination #VCTWatchparty | !vote !inzone !noYT",
  "viewersCount": 40495,
  "language": "EN",
  "channelLogin": "gofns",
  "categoryName": "VALORANT",
  "sourceUrl": "https://www.twitch.tv/gofns"
}
```

### What does Twitch Streams Scraper do?

Twitch Streams Scraper is a Twitch scraper and Twitch API alternative that reads the same public data the Twitch website shows to anyone who is not logged in. It collects three kinds of records. In `liveStreams` mode it returns the live streams of one or more categories (for example VALORANT or League of Legends), sorted by viewer count, optionally limited to one or more broadcast languages. You can keep streams in a viewer range or with text in the title. When no category is supplied, you can scan the top categories to reach more streams than the site-wide first page. In `topCategories` mode it returns the most-watched categories on Twitch right now, with viewers, number of live broadcasters and followers. In `channels` mode it returns a profile for each channel you name, with the follower count, bio, account creation date and whether the channel is live at the moment.

You do not need a Twitch developer account, an OAuth token or a browser. The Actor sends a small number of requests to Twitch's public web endpoint, one at a time and at a polite pace, and writes clean rows into an Apify dataset that you can download as JSON, CSV, Excel or HTML, or read through the Apify API.

This Actor is an independent tool. It is not affiliated with, endorsed by or sponsored by Twitch.

Typical uses:

- Compare how many people watch a game right now in English, Spanish, Portuguese or Japanese.
- Build a list of the biggest streamers in a category for sponsorship or partnership research.
- Snapshot top categories every hour to see which games are rising.
- Look up follower counts and bios for a list of channels you already know.
- Keep only live streams whose current viewer count falls inside a selected range.
- Find live stream titles containing an event name within the fetched category pages.

#### Limits you should know about

Twitch only returns up to 30 live streams for each category and language query without a signed-in session, and up to 100 categories in the top-categories list. The Actor does not try to get around this. To collect more streams, it fans out: one query for every combination of category and language. If you give it three categories and four languages you can receive up to 360 streams (30 per query). With an empty `categories` list, `topCategoriesToScan` selects up to 100 leading categories and queries their live streams. Each category's page is sorted by viewers; the combined dataset is emitted in category order, not globally ranked. Viewer and title filters apply to those fetched pages only, so they cannot discover matches beyond each page's first 30 streams. `maxItems` is a ceiling, not a promise: with one category and one language you get at most 30 streams. If Twitch ever asks for an extra integrity check, the Actor stops cleanly and keeps the rows it has already saved. It never attempts to bypass such a check.

### What data can you get?

Not every field exists in every mode. Fields marked "channels only" or "topCategories only" are empty (and left out) in the other modes.

| Field | Type | Description |
|---|---|---|
| `id` | string | Stream ID (liveStreams), category ID (topCategories) or user ID (channels) |
| `title` | string | Stream title; category name in topCategories; display name in channels |
| `viewersCount` | number | Current viewers; 0 for an offline channel |
| `language` | string | Broadcaster language code such as EN or ES |
| `startedAt` | string | ISO time the stream went live |
| `streamType` | string | Twitch stream type such as live or rerun (liveStreams only) |
| `channelLogin` | string | Channel login name used in the channel URL |
| `channelName` | string | Channel display name |
| `followers` | number | Channel followers (category followers in topCategories) |
| `categoryName` | string | Game or category name |
| `categorySlug` | string | Category slug used in the Twitch URL |
| `tags` | array of strings | Stream tags; content tags for categories |
| `thumbnailUrl` | string | Stream preview, category box art or channel profile image |
| `broadcastersCount` | number | Live broadcasters in the category (topCategories only) |
| `streamTitle` | string | Last broadcast title (channels only) |
| `description` | string | Channel bio (channels only) |
| `createdAt` | string | Channel creation time (channels only) |
| `isLive` | boolean | Whether the channel is live now (channels only) |
| `sponsorshipCategory` | string | Optional AI label, present only when AI enrichment is on |
| `sourceUrl` | string | Twitch page the record belongs to |

Every record has a stable `id`, and the Actor never outputs the same `id` twice in a run.

### How to use

1. Open the Actor in Apify Console and choose a mode.
2. For live streams, enter one or more category slugs such as `valorant` or `league-of-legends`. You can also paste a category name, including accented names such as `Pokémon`, or a twitch.tv directory URL. Leave the list empty to get the top streams across all of Twitch.
3. Add language codes (EN, ES, PT, JA, KO and so on) if you only want streams in certain languages. Leave it empty for all languages.
4. Optionally set `minViewers`, `maxViewers`, or `titleContains`. With no categories, set `topCategoriesToScan` to search several leading categories.
5. Set `maxItems` and press Start.
6. When the run finishes, open the Output tab to preview the table or download the data.

The default run (VALORANT, English, 20 items) finishes in a few seconds.

If a category slug does not exist, or a channel login is unknown, the Actor logs a warning and carries on with the rest of your input. If nothing at all is found, the run ends successfully with an empty dataset and a warning. It does not write placeholder rows.

### Input

| Field | Type | Description |
|---|---|---|
| `mode` | string | `liveStreams`, `topCategories` or `channels`. Default `liveStreams`. |
| `categories` | array | Category slugs, names or directory URLs for liveStreams mode. Empty means site-wide top streams. |
| `languages` | array | Twitch language codes for liveStreams mode. One query per language and category. Empty means all languages. |
| `channels` | array | Channel logins or twitch.tv URLs for channels mode. |
| `maxItems` | integer | Maximum records to output, 1 to 1000, default 50. |
| `minViewers` | integer | Minimum current viewers for live streams; default 0. |
| `maxViewers` | integer | Maximum current viewers for live streams; omit for no upper bound. |
| `titleContains` | string | Text that a live stream title must contain, ignoring case; default empty. |
| `topCategoriesToScan` | integer | With empty `categories`, query live streams in the top 1-100 categories; default 0 for site-wide top streams only. |
| `enrichWithAI` | boolean | Add a `sponsorshipCategory` label using a third-party AI processor. Default false. |
| `proxyConfiguration` | object | Apify Proxy settings. Off by default because the public endpoint normally works without one. |

Example input for live streams in several languages:

```json
{
  "mode": "liveStreams",
  "categories": ["valorant"],
  "languages": ["EN", "ES", "PT", "JA"],
  "maxItems": 50
}
```

Example input for top categories:

```json
{
  "mode": "topCategories",
  "maxItems": 50
}
```

To find live streams in a viewer band across the leading categories, leave `categories` empty and use the discovery and filter inputs together:

```json
{
  "mode": "liveStreams",
  "categories": [],
  "topCategoriesToScan": 10,
  "minViewers": 500,
  "maxViewers": 5000,
  "titleContains": "ranked",
  "maxItems": 50
}
```

Example input for channel profiles:

```json
{
  "mode": "channels",
  "channels": ["shroud", "caedrel", "valorant"],
  "maxItems": 3
}
```

### Output

Each run writes its records to the default dataset. A live stream record looks like this:

```json
{
  "id": "316077019602",
  "title": "G2 vs. TL - VALORANT Champions Shanghai - Group Stage",
  "viewersCount": 24055,
  "language": "EN",
  "startedAt": "2026-10-03T08:30:09Z",
  "streamType": "live",
  "channelLogin": "valorant",
  "channelName": "VALORANT",
  "followers": 4901400,
  "categoryName": "VALORANT",
  "categorySlug": "valorant",
  "tags": ["Esports", "VCT", "English"],
  "thumbnailUrl": "https://static-cdn.jtvnw.net/previews-ttv/live_user_valorant-440x248.jpg",
  "sourceUrl": "https://www.twitch.tv/valorant"
}
```

A top category record has the category name as `title`, the number of viewers across the category, `broadcastersCount`, category `followers`, content `tags` and the box art as `thumbnailUrl`.

A channel record has the display name as `title`, `viewersCount` of 0 when the channel is offline, `isLive`, `followers`, `description`, `createdAt` and the last `streamTitle`.

Viewer counts change every minute, so two runs a few minutes apart will not match. Followers and viewers are the numbers Twitch shows at the time of the run.

### How much does it cost?

The Actor is charged per result: each record written to the dataset counts as one result. If you switch on AI enrichment, records that were successfully labelled count as enriched results as well. Records where enrichment failed or was skipped are charged as normal results only. See the Pricing tab of the Actor for the current rates. Your Apify plan's platform usage also applies, but runs of this Actor are small and short.

Because `maxItems` is honoured exactly, you can cap the cost of any run by lowering it.

### Use with AI agents (MCP)

You can call this Actor from any MCP-capable assistant through the Apify MCP server. Add this to your client configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=axiomworks/twitch-streams-scraper"
    }
  }
}
```

Example prompts:

- "Use the Twitch scraper to list the 20 most-watched VALORANT streams in Spanish."
- "Which 10 categories on Twitch have the most viewers right now?"
- "Get the follower count and bio for the Twitch channels shroud and caedrel."

### Integrations and API

You can start the Actor from code with the Apify API clients.

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("axiomworks/twitch-streams-scraper").call(run_input={
    "mode": "liveStreams",
    "categories": ["valorant"],
    "languages": ["EN"],
    "maxItems": 20,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["channelName"], item["viewersCount"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('axiomworks/twitch-streams-scraper').call({
    mode: 'topCategories',
    maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.info(items.length);
```

cURL:

```bash
curl -X POST "https://api.apify.com/v2/acts/axiomworks~twitch-streams-scraper/runs" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode":"channels","channels":["shroud"],"maxItems":1}'
```

You can also schedule the Actor to run every hour, send the dataset to Google Sheets, a webhook, Make, Zapier or n8n through Apify integrations, and compare snapshots over time.

### FAQ

**Do I need a Twitch account or API key?**
No. The Actor reads public data without logging in.

**Why do I get fewer streams than `maxItems`?**
Twitch returns at most 30 streams per category and language query. Add more languages or categories to widen the search. A language with no live streams in that category (for example Korean for some games) simply returns nothing.

**Are the streams sorted?**
Yes, within each query by viewer count, highest first. Queries run in the order of your categories and languages.

**What happens with a wrong category or channel?**
The Actor logs a warning for that item and continues. If the whole run has no results, it finishes with an empty dataset.

**Is the language the language of the stream?**
It is the language the broadcaster has set for the channel, which is the value Twitch uses for its language filter.

**Does the Actor use a proxy?**
It does not need one in most cases. If you enable Apify Proxy, requests that are blocked are retried with a fresh session.

**What does AI enrichment do?**
When switched on, each record is sent to a third-party AI processor, which picks one label for `sponsorshipCategory` from a fixed list. If the AI step fails, the record is still saved without the label.

**Can it get chat, VODs or clips?**
No. This Actor covers live streams, categories and channel profiles.

### Is it legal to scrape Twitch?

The Actor only reads public information that Twitch shows to visitors who are not logged in. It collects no private data, passwords or messages, and it does not get past any login or bot check. Public channel names and stream titles can still be personal data in some jurisdictions, so you should have a lawful reason for collecting them and handle them according to the rules that apply to you, such as GDPR. Twitch's terms of service discourage automated access, so review them for your use case and keep your request volume modest. This is general information, not legal advice.

### Feedback

If a field is missing, a category does not resolve or you need another mode, open an issue from the Actor page in Apify Console and include the input and the run link. Reports with a concrete example are fixed fastest.

# Actor input Schema

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

liveStreams only. Category slugs, names or twitch.tv/directory/category URLs, e.g. \['valorant', 'League of Legends', 'https://www.twitch.tv/directory/category/just-chatting']. Empty = site-wide top streams. Unknown categories are skipped with a warning.

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

What to collect. 'liveStreams' = current live streams (uses categories, languages, filters); 'topCategories' = top categories by viewers (max 100); 'channels' = channel profiles (requires 'channels'). Example: 'liveStreams'. Default 'liveStreams'.

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

liveStreams only. Twitch language codes, e.g. \['EN', 'ES', 'PT', 'JA', 'KO']. One query (max 30 streams) per category and language. Empty = all languages. Invalid codes fail the run.

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

channels mode only (required there). Channel logins or twitch.tv URLs, e.g. \['shroud', 'https://www.twitch.tv/ninja']. Unknown channels are skipped.

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

Maximum records to output, integer 1-1000, default 50. Twitch returns at most 30 streams per category and language query and 100 categories, so the real total is bounded by that. Example: 20.

## `minViewers` (type: `integer`):

liveStreams only. Keep streams with at least this many current viewers, integer >= 0, e.g. 100. Default 0. Applies within the first 30 streams per category and language.

## `maxViewers` (type: `integer`):

liveStreams only. Keep streams with at most this many current viewers, integer >= minViewers, e.g. 500. Omit for no upper bound.

## `titleContains` (type: `string`):

liveStreams only. Keep streams whose title contains this text, case-insensitive, e.g. 'tournament'. Default empty = all titles.

## `topCategoriesToScan` (type: `integer`):

When categories is empty, scan the top 1-100 categories by viewers for live streams, up to 30 per category and language. Set 0 (default) for only the site-wide top streams.

## `enrichWithAI` (type: `boolean`):

If true, a third-party AI processor adds sponsorshipCategory (esports-tournament, pro-player, variety-streamer, just-chatting-irl, creator-small, other) to each record. Default false.

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

Apify Proxy settings, e.g. {"useApifyProxy": true}. Twitch's public API normally works without a proxy; enable one only if runs report being blocked.

## Actor input object example

```json
{
  "categories": [
    "valorant"
  ],
  "mode": "liveStreams",
  "languages": [
    "EN"
  ],
  "channels": [],
  "maxItems": 20,
  "minViewers": 0,
  "titleContains": "",
  "topCategoriesToScan": 0,
  "enrichWithAI": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# 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 = {
    "categories": [
        "valorant"
    ],
    "mode": "liveStreams",
    "languages": [
        "EN"
    ],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("axiomworks/twitch-streams-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 = {
    "categories": ["valorant"],
    "mode": "liveStreams",
    "languages": ["EN"],
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("axiomworks/twitch-streams-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 '{
  "categories": [
    "valorant"
  ],
  "mode": "liveStreams",
  "languages": [
    "EN"
  ],
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call axiomworks/twitch-streams-scraper --silent --output-dataset

```

## MCP server setup

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