# Twitch Public Streams, Channels, Videos and Clips Scraper (`w3crawler/twitch-scraper`) Actor

Extract public Twitch streams, games, channels, videos, clips, and search results through Twitch's anonymous web GraphQL surface with bounded pagination and request pacing.

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

## Pricing

from $2.99 / 1,000 streams

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Public Streams, Channels, Videos and Clips Scraper

This actor extracts public Twitch discovery data through Twitch's anonymous web GraphQL surface. It supports live streams, games/categories, search results, channel profiles, VODs, clips, and public Twitch URLs without a login or developer API key. Every response is bounded by `maxResponseBytes`; a local fixture mode is available for deterministic runs.

### What it collects

- Live streams: title, current viewers, broadcaster, game, language/tags, images, and public URLs.
- Games/categories: names, slugs, viewer counts, tags, box art, and public category URLs.
- Channels: profile/description, follower count, partner/affiliate flags, live snapshot, and public URLs.
- VODs and clips: title, views, duration, timestamps, language, game, broadcaster/curator, thumbnails, and public URLs.
- Minimal four-field diagnostics when validation, GraphQL, blocking, or record extraction prevents public data collection.

### Input

Top streams example:

```json
{
  "mode": "topStreams",
  "language": "EN",
  "maxItems": 10,
  "pageSize": 10,
  "maxPages": 1
}
```

Other modes are `topGames`, `search`, `byChannel`, `byCategory`, `topClips`, `byVideo`, `byClip`, and `byUrl`. Use `channelName`, `categorySlug`, `videoId`, `clipSlug`, or `twitchUrls` as required by the selected mode. Filters include `searchType`, `videoSort`, `streamType`, `clipPeriod`, `minViewersCount`, `minViewCount`, and `containsKeyword`.

Request pacing and bounds are explicit: `maxItems` 1–300, `pageSize` 1–30, `maxPages` 1–10, `minDelayMs` 100–5000, and request timeout 10–90 seconds.

Set `fixtureFile` to an Actor-relative JSON file containing a `responses` array
of GraphQL response objects to run without network access. The fixture responses
are consumed in request order and are capped at 100 entries. The committed local
input uses this mode.

### Example output

```json
{
  "recordType": "stream",
  "source": "twitch.tv",
  "provenance": "public_twitch_anonymous_graphql",
  "streamId": "123456789",
  "title": "Public stream title",
  "channelName": "example_channel",
  "gameName": "Just Chatting",
  "viewersCount": 12000,
  "url": "https://www.twitch.tv/example_channel"
}
```

Every normal record has a `recordType`, public provenance fields, a stable identity where available, a canonical Twitch URL, and `scrapedAt`. Run status and availability are in `OUTPUT`; diagnostics contain exactly `url`, `error`, `errorCode`, and `scrapedAt`.

### Storage

- Streams, games, channels, VODs, clips, and minimal diagnostics are written to the default dataset.
- The `OUTPUT` key-value-store record contains mode, public endpoint, requested limit, result count, record types, duration, and final status.

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### Cost and limits

Platform runtime depends on the selected pages, result limit, and request delay. The actor uses bounded GraphQL pagination, bounded retries, timeouts, response-size limits, and a minimum delay between public requests. No paid Twitch API plan is used.

### Local verification

```bash
npm ci --ignore-scripts --no-audit --no-fund --prefer-offline
npm test
npm run lint
npm run schema
apify run --purge --input-file .actor/input.json
npm run validate
```

The local QA workflow does not use `apify push` or `apify call`.

### FAQ

#### Does this require a Twitch account or API key?

No. It is intended for information visible to anonymous public visitors.

#### Does it scrape chat or subscriber-only data?

No. Chat, private dashboards, subscriber-only content, and authenticated controls are outside scope.

#### Why can a valid Twitch mode return no records?

Twitch may return no match for the identifier/filter, change its public GraphQL contract, or limit anonymous access. The run summary and error record preserve the result.

#### Is the viewer count real-time or guaranteed?

No. It reflects the public response at extraction time and may be delayed or unavailable.

### Disclaimer

Use this actor only for lawful, respectful access to publicly available information. Follow Twitch's terms, API/site policies, robots guidance, rate limits, and applicable laws. Do not use the output to harass creators, infer private attributes, or make decisions without independent verification.

# Actor input Schema

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

Choose the public Twitch resource to extract.

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

Required for search mode.

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

Return all supported search types or only channels, games, or videos.

## `channelName` (type: `string`):

Channel login, for example lirik.

## `categorySlug` (type: `string`):

The value after /directory/category/, for example just-chatting.

## `videoId` (type: `string`):

Numeric Twitch VOD identifier for byVideo mode.

## `clipSlug` (type: `string`):

Public Twitch clip slug for byClip mode.

## `twitchUrls` (type: `array`):

Public channel, category, VOD, or clip URLs for byUrl mode.

## `language` (type: `string`):

Filter stream queries by Twitch broadcast language. Select Any for no language filter.

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

Sort channel VODs by publication time or public view count.

## `streamType` (type: `string`):

Optionally keep only a specific channel video broadcast type.

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

Time window used for channel and category clip queries.

## `includeChannelVideos` (type: `boolean`):

Include recent public videos when using byChannel mode.

## `includeChannelClips` (type: `boolean`):

Include public clips when using byChannel mode.

## `minViewersCount` (type: `integer`):

Discard live streams below this current viewer count.

## `minViewCount` (type: `integer`):

Discard videos and clips below this public view count.

## `containsKeyword` (type: `string`):

Case-insensitive stream, VOD, or clip title filter.

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

Hard cap on unique dataset records.

## `pageSize` (type: `integer`):

Number of connection items requested from Twitch per page.

## `maxPages` (type: `integer`):

Maximum pages fetched from each paginated Twitch connection.

## `minDelayMs` (type: `integer`):

Minimum delay between public Twitch GraphQL requests.

## `requestTimeoutSecs` (type: `integer`):

Abort an individual Twitch request after this many seconds.

## `maxResponseBytes` (type: `integer`):

Maximum size of an individual Twitch GraphQL response or fixture response.

## `fixtureFile` (type: `string`):

Optional Actor-relative JSON fixture with a responses array; when set, no network request is made.

## Actor input object example

```json
{
  "mode": "topStreams",
  "searchQuery": "lirik",
  "searchType": "all",
  "twitchUrls": [],
  "language": "EN",
  "videoSort": "TIME",
  "streamType": "",
  "clipPeriod": "LAST_WEEK",
  "includeChannelVideos": true,
  "includeChannelClips": true,
  "minViewersCount": 0,
  "minViewCount": 0,
  "maxItems": 10,
  "pageSize": 30,
  "maxPages": 5,
  "minDelayMs": 350,
  "requestTimeoutSecs": 30,
  "maxResponseBytes": 2000000
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing public Twitch streams, channels, games, videos, clips, and errors.

## `runSummary` (type: `string`):

JSON run summary stored in key-value store record OUTPUT.

# 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 = {
    "mode": "topStreams",
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("w3crawler/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 = {
    "mode": "topStreams",
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("w3crawler/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 '{
  "mode": "topStreams",
  "maxItems": 10
}' |
apify call w3crawler/twitch-scraper --silent --output-dataset

```

## MCP server setup

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