# Twitch Channel & Category Scraper (`axery/twitch-channel-scraper`) Actor

Scrape Twitch channel stats and live streams - follower counts, live viewer counts, stream title, category, uptime, recent VODs and top clips. No login, no API key.

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

## Pricing

from $4.00 / 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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Twitch Channel & Category Scraper

Scrapes Twitch channel stats and live streams — follower counts, live viewer counts, stream title, category, uptime, recent VODs and top clips. No login, no OAuth, no API key, no developer registration.

Useful for influencer discovery, sponsorship research, competitor tracking, category trend monitoring, and building a live-status dashboard across many channels.

### Two modes

- **Channels** — look up specific channels by name. Live *and* offline channels both return a row.
- **Category** — list the streams live in a category right now, e.g. `Just Chatting`, with each broadcaster's follower count attached.

### What makes this different

**Follower and live-viewer counts, which the page alone won't give you.** These come from the same public gateway the Twitch web app uses. A scraper that only parses the channel HTML gets structured data with clip listings but no follower count and no live viewer count — the two numbers most of this data is actually wanted for.

**Offline channels still produce a row.** `is_live` is a real field, not an inference, and an offline channel keeps `last_broadcast_title`, `last_broadcast_game` and `last_broadcast_started_at`. Monitoring a roster of channels tells you what each one last streamed and when — not just silence.

**Category ranking that's actually ranked.** Twitch's own browse order only approximates viewer count; promoted streams sit near the top regardless of size. Because a whole category arrives in one request, this Actor re-ranks it exactly and stamps a `rank` on every row. Turn `sortByViewers` off to keep Twitch's ordering.

**`category_total_viewers` on every category row.** Total viewers across the category at scrape time, so a stream's *share* of its category is a division rather than a second run.

**The tags are the real tags.** Twitch exposes two tag fields; one is permanently empty and the other is the one the site displays. This reads the one that isn't empty — a detail that silently costs a naive scraper every tag on every row.

**Box-art URLs that actually load.** Twitch returns category art containing literal `{width}`/`{height}` placeholders. Passed through unmodified those 404 in any browser; here they're filled in.

**Channel lookups are batched.** 25 channels cost one request, not 25 — so a roster of 100 channels with VODs and clips finishes in about four calls.

**Uptime is precomputed.** `stream_uptime_minutes` is derived at scrape time, so "who has been live over four hours" is a filter rather than a date-arithmetic pass.

### Input

| Field | Type | Notes |
|---|---|---|
| `mode` | enum | `channels` or `category`. |
| `targets` | array | Channel names (URLs accepted) or category names. |
| `includeVideos` | integer | Recent VODs per channel, `0` to skip. Channels mode. |
| `includeClips` | integer | Top clips per channel, `0` to skip. Channels mode. |
| `clipPeriod` | enum | Window clips are ranked within. |
| `maxItems` | integer | Streams per category, up to 100. |
| `sortByViewers` | boolean | Exact viewer ranking. Default on. |
| `proxyConfiguration` | object | Not normally needed. |

#### Two limits worth knowing up front

**Category depth caps at 100 streams.** Twitch rejects a page size above 100 outright, and gates cursor pagination behind an integrity check that cannot be satisfied without a browser. So 100 per category per run is the honest ceiling — this Actor takes the largest page the API allows and does not pretend to page past it. For a large category, re-run on a schedule instead.

**Category names must match Twitch's spelling exactly.** `Just Chatting`, not `just chatting` or `Chatting`. A name that doesn't match is reported as a failure for that target rather than returning silently empty.

### Output

```json
{
  "channel_id": "twitch.tv:37402112",
  "login": "shroud",
  "display_name": "shroud",
  "follower_count": 11288146,
  "is_partner": true,
  "account_created_at": "2012-11-03T15:50:32Z",
  "is_live": true,
  "stream_title": "going for apache",
  "viewer_count": 11450,
  "stream_uptime_minutes": 273,
  "game_name": "WARDOGS",
  "stream_tags": ["English", "DropsEnabled"],
  "url": "https://www.twitch.tv/shroud"
}
```

A channel that does not exist is logged and skipped rather than emitting a hollow row. Each run also writes a `RUN_COVERAGE` record to the key-value store with what was requested, what came back, and any per-target failures — so a partial run is visible rather than silent.

### Local development

```bash
pip install -r requirements.txt
python test_local.py --mode channels shroud pokimane --videos 5 --clips 5
python test_local.py --mode category "Just Chatting" --max 25 --out sample_output.json
```

`sample_output.json` is real output from a live category run.

# Actor input Schema

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

`Channels` looks up specific channels by name. `Category` lists the live streams currently in a category such as Just Chatting.

## `targets` (type: `array`):

In `channels` mode: Twitch channel names (a full twitch.tv URL also works). In `category` mode: category names exactly as Twitch spells them, e.g. `Just Chatting`, `Grand Theft Auto V`.

## `includeVideos` (type: `integer`):

How many recent VODs to attach to each channel row, newest first. `0` skips them. Channels mode only.

## `includeClips` (type: `integer`):

How many top clips to attach to each channel row, most-viewed first. `0` skips them. Channels mode only.

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

Time window that top clips are ranked within. Only applies when `Top clips per channel` is above 0.

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

How many live streams to return per category, up to 100 - which is Twitch's own hard ceiling for a single page. Category mode only.

## `sortByViewers` (type: `boolean`):

Re-rank category results strictly by live viewer count. Twitch's own browse order only approximates this - promoted streams sit near the top regardless of size. Uncheck to keep Twitch's ordering.

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

Apify Proxy settings. Twitch's GQL gateway is public, but Apify's own container IP range can still be rate-limited or blocked by services that treat cloud IPs as suspicious regardless of any WAF - defaults to Residential as a precaution.

## Actor input object example

```json
{
  "mode": "channels",
  "targets": [
    "shroud"
  ],
  "includeVideos": 5,
  "includeClips": 5,
  "clipPeriod": "LAST_MONTH",
  "maxItems": 30,
  "sortByViewers": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Follower counts, live viewer counts, stream metadata, and optionally recent VODs and top clips.

# 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 = {
    "targets": [
        "shroud",
        "pokimane"
    ],
    "includeVideos": 5,
    "includeClips": 5,
    "maxItems": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("axery/twitch-channel-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 = {
    "targets": [
        "shroud",
        "pokimane",
    ],
    "includeVideos": 5,
    "includeClips": 5,
    "maxItems": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("axery/twitch-channel-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 '{
  "targets": [
    "shroud",
    "pokimane"
  ],
  "includeVideos": 5,
  "includeClips": 5,
  "maxItems": 30
}' |
apify call axery/twitch-channel-scraper --silent --output-dataset

```

## MCP server setup

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