---
title: "Twitch scraper"
description: "Scrape Twitch channels as JSON: username, display name, follower count, bio, profile image and social links. One API request from Python, Node.js, the CLI or MCP."
canonical: https://www.zenrows.com/scrape/twitch
updated: 2026-10-20
---

# Twitch scraper

The Zenrows Twitch scraper turns a Twitch channel URL into structured JSON: username, display name, follower count, channel description, profile image, channel URL, social links and the videos listed on the page. You send the channel URL, Fetch in Adaptive Stealth Mode opens and renders the page, and Extract returns the fields. Run it from an API call, the CLI or an AI agent.

- Site: twitch.tv
- Returns: Channels, followers, bios and profile images

## Run it: one Twitch channel in, JSON out

```json Input
{
  "url": "https://www.twitch.tv/shroud",
  "mode": "auto",
  "extract": "auto"
}
```

```json Output
{
  "channel": {
    "description": "I'm back baby ",
    "display_name": "shroud",
    "follower_count": 11294080,
    "profile_image_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/c754eebf-745b-4e0a-814a-10bcaecaabbc-profile_image-300x300.png",
    "profile_url": "https://www.twitch.tv/shroud",
    "username": "shroud"
  },
  "social_links": [],
  "videos": []
}
```

Request and output of a live call to a Twitch channel page on Oct 20, 2026. A field is returned when the page shows it, so `social_links` and `videos` fill in on channels that list them.

## What data can you scrape from Twitch?

A Twitch channel page returns the channel record: who the streamer is, how big the audience is, and what the channel links to. These are the fields, with the path where each one lives in the JSON.

| Field | What it holds | Example |
|---|---|---|
| `channel.username` | The login name in the channel URL, lowercase | `shroud` |
| `channel.display_name` | The name shown on the channel, with the streamer's own capitalisation | `shroud` |
| `channel.follower_count` | Followers, as an exact number | `11294080` |
| `channel.description` | The channel bio | `I'm back baby` |
| `channel.profile_image_url` | The channel's profile picture, 300 by 300 | `https://static-cdn.jtvnw.net/jtv_user_pictures/…-profile_image-300x300.png` |
| `channel.profile_url` | The canonical channel URL | `https://www.twitch.tv/shroud` |
| `social_links[]` | The social and website links in the channel's About panel | `[]` on this capture |
| `videos[]` | The past broadcasts, highlights and uploads listed on the page | `[]` on this capture |

Follower count is the number brands and agencies ask for first, and Twitch's own API only returns it to an app with an access token. The scraper reads it from the public channel page.

## How to scrape Twitch with Zenrows

1. **Create a free Zenrows account** and copy your API key from the dashboard.
2. **Pick the channel URL.** Every channel lives at `https://www.twitch.tv/<username>`. The `/about` and `/videos` tabs of the same channel work the same way.
3. **Send it with the default configuration.** Twitch builds its pages in the browser, so Adaptive Stealth Mode renders the page before Extract reads it. You do not need to set that up yourself.
4. **Read `parsed`** from the response. To keep only the audience numbers, list the paths you want and the response returns just those.
5. **Run your streamer list in Batch** and repeat it weekly to track follower growth.

```python Python
# pip install requests
import requests

params = {
    "apikey": "YOUR_ZENROWS_API_KEY",
    "url": "https://www.twitch.tv/shroud",
    "mode": "auto",      # Adaptive Stealth Mode
    "extract": "auto",   # structured JSON
}
response = requests.get("https://api.zenrows.com/v1/", params=params, timeout=180)
response.raise_for_status()

channel = response.json()["parsed"]["channel"]
print(channel["display_name"], channel["follower_count"])
print(channel["description"])
```

```javascript Node.js
// Node 18+ (built-in fetch)
const params = new URLSearchParams({
  apikey: "YOUR_ZENROWS_API_KEY",
  url: "https://www.twitch.tv/shroud",
  mode: "auto",
  extract: "auto",
});

const response = await fetch(`https://api.zenrows.com/v1/?${params}`, {
  signal: AbortSignal.timeout(180_000),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);

const { parsed } = await response.json();
console.log(parsed.channel.username, parsed.channel.follower_count);
```

```bash cURL
curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.twitch.tv%2Fshroud&mode=auto&extract=auto"

# Only the fields you need
curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.twitch.tv%2Fshroud&mode=auto&extract=auto&extract_fields=channel.username%2Cchannel.follower_count%2Cchannel.description"
```

```python Python SDK
# pip install zenrows
from zenrows import ZenRowsClient

client = ZenRowsClient("YOUR_ZENROWS_API_KEY")
for name in ["shroud", "pokimane", "xqc"]:
    response = client.get(
        f"https://www.twitch.tv/{name}",
        params={"mode": "auto", "extract": "auto"},
    )
    channel = response.json()["parsed"]["channel"]
    print(name, channel["follower_count"])
```

## Input

The scraper takes one Twitch URL per request, plus the options below. A Batch job applies the same options to every URL, so the input for a roster of streamers is a list of channel URLs with these settings.

| Parameter | Type | Default | Description |
|---|---|---|---|
| `url` | string | required | A Twitch channel page, `https://www.twitch.tv/<username>`, or its `/about` or `/videos` tab |
| `mode` | string | `auto` | Adaptive Stealth Mode: starts with the lightest setup and adds rendering and protected-site handling only when the page needs them |
| `extract` | string | `auto` | Returns the channel fields as JSON in `parsed`, next to the raw `html` |
| `extract_fields` | string | all fields | Comma-separated paths to keep, such as `channel.username,channel.follower_count` |
| `proxy_country` | string | any | Two-letter country code, to read Twitch as viewers in one country see it |
| `wait_for` | string | none | A CSS selector to wait for before the page is read, such as the About panel |
| `session_id` | integer | none | Reuse the same session across several requests, up to 10 minutes |

```json Batch input
{
  "type": "regular",
  "status": "closed",
  "zenrows_params": {
    "mode": "auto",
    "extract": "auto"
  },
  "tasks": [
    { "url": "https://www.twitch.tv/shroud", "external_id": "shroud" },
    { "url": "https://www.twitch.tv/pokimane", "external_id": "pokimane" },
    { "url": "https://www.twitch.tv/xqc", "external_id": "xqc" }
  ]
}
```

## Output

Every response is JSON with two keys: `html`, the rendered page, and `parsed`, the structured record. A channel page returns `channel`, `social_links` and `videos`. The sample below is the full output of a live request on Oct 20, 2026.

```json Channel page
{
  "channel": {
    "description": "I'm back baby ",
    "display_name": "shroud",
    "follower_count": 11294080,
    "profile_image_url": "https://static-cdn.jtvnw.net/jtv_user_pictures/c754eebf-745b-4e0a-814a-10bcaecaabbc-profile_image-300x300.png",
    "profile_url": "https://www.twitch.tv/shroud",
    "username": "shroud"
  },
  "social_links": [],
  "videos": []
}
```

The follower count is an integer, ready for a database column, and the description keeps the streamer's text as written, trailing spaces included, so trim it before display. Need a spreadsheet? Load `parsed` into pandas with `pd.json_normalize(...)` and write CSV or Excel. Need the page for an LLM? Ask for Markdown instead of JSON.

## Scrape Twitch from your coding agent

Claude Code, Cursor, Codex and any MCP client can look up Twitch channels from a prompt.

The agent sends the same Fetch and Extract request a developer would, so it reads the JSON shown above. Connect the Zenrows MCP server once, or install the CLI and let the agent run it in the terminal.

```bash Connect the MCP server (Claude Code)
claude mcp add zenrows -e ZENROWS_API_KEY=YOUR_ZENROWS_API_KEY -- npx -y @zenrows/mcp
```

```json MCP config (Cursor, Claude Desktop, Windsurf)
{
  "mcpServers": {
    "zenrows": {
      "command": "npx",
      "args": ["-y", "@zenrows/mcp"],
      "env": { "ZENROWS_API_KEY": "YOUR_ZENROWS_API_KEY" }
    }
  }
}
```

```bash Or run the CLI
npx -y @zenrows/cli init
zenrows extract "https://www.twitch.tv/shroud"
```

```text Then ask your agent
Use Zenrows to get the follower count and bio of these Twitch channels
and return a table sorted by followers:
https://www.twitch.tv/shroud
https://www.twitch.tv/pokimane
https://www.twitch.tv/xqc
```

## Scrape Twitch at scale with Batch and Crawl

**Batch** runs a list of channel URLs as one job, in parallel, with the username as your `external_id` on each result. Run it every week and the difference between two runs is each streamer's follower growth, the number sponsorship decks are built on.

**Crawl** collects a channel's past broadcasts. Start it on the channel's `/videos` tab, keep only links that contain `/videos/`, and it returns each video page it reaches. Use it to archive what a sponsored streamer published during a campaign.

```bash Batch (cURL)
curl -X POST "https://async.api.zenrows.com/v1/jobs" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "regular",
    "status": "closed",
    "zenrows_params": { "mode": "auto", "extract": "auto" },
    "tasks": [
      { "url": "https://www.twitch.tv/shroud", "external_id": "shroud" },
      { "url": "https://www.twitch.tv/pokimane", "external_id": "pokimane" }
    ]
  }'

# Read the results when the job finishes
curl "https://async.api.zenrows.com/v1/jobs/JOB_ID/results?status=successful" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY"
```

```bash Batch (CLI)
# streamers.jsonl: one {"url": "...", "external_id": "...", "extract": "auto"} per line
zenrows batch create streamers.jsonl --wait
zenrows batch results <job-id> --out twitch-channels.jsonl
```

```bash Crawl (cURL)
curl -X POST "https://api.zenrows.com/v1/crawls" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.twitch.tv/shroud/videos",
    "depth": 1,
    "max_pages": 100,
    "include_patterns": ["/videos/"]
  }'
```

**Scheduled jobs** run the same Batch job on a timetable, on Zenrows' side: every few hours, once a day, at set times on chosen days, or once at a future date. Each run keeps its own results, a webhook can tell your app when a run finishes, and you can pause or resume the schedule at any time, with no cron server to keep alive.

```bash Scheduled job (cURL)
# Runs every day on Zenrows' side; each run keeps its own results
curl -X POST "https://async.api.zenrows.com/v1/jobs" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
      "type": "scheduled",
      "status": "closed",
      "schedule": {
        "rate": {
          "every": 1,
          "unit": "day"
        }
      },
      "zenrows_params": {
        "mode": "auto",
        "extract": "auto"
      },
      "tasks": [
        {
          "url": "https://www.twitch.tv/shroud",
          "external_id": "twitch"
        }
      ]
    }'

# Or at set times: "schedule": { "calendar": { "times_of_day": ["09:00"],
#   "cadence": { "weekly": { "days": ["mon", "thu"] } } }, "timezone": "Europe/Madrid" }
```

## What teams do with Twitch data

| Use case | Data they pull | Who runs it |
|---|---|---|
| Streamer discovery and vetting | Follower count, bio and profile per channel | Influencer and esports agencies |
| Sponsorship reporting | Weekly follower counts across a sponsored roster | Brand teams and gaming marketers |
| Talent scouting | Channels in a game category, ranked by followers | Esports organisations and talent managers |
| Game launch research | Who streams a game and how large their audience is | Game publishers and analysts |
| Creator CRM enrichment | Username, display name, profile image and social links | Partnerships and creator-economy platforms |

## Tips for scraping Twitch

- **Use the lowercase username as your key.** `channel.username` is the login in the URL and is always lowercase; `display_name` can carry capitals or non-Latin characters. Join tables on the username.
- **Build URLs from usernames.** `https://www.twitch.tv/` plus the username is every channel's URL. Strip `?sr=a` and other query parameters from links you collect.
- **Snapshot followers on a fixed day.** Follower counts change constantly. Request the roster on the same weekday each week so growth figures compare like with like.
- **Read the About panel for links.** `social_links[]` comes from the channel's About panel; channels that fill it give you their YouTube, X and website links in one request.
- **Find channels from the directory.** `https://www.twitch.tv/directory/category/<game>` lists the channels streaming a game right now. Collect the usernames there, then send the channel URLs to Batch.
- **Trim the bio.** Streamers paste text with trailing spaces and line breaks, so strip `channel.description` before you display or compare it.

## Frequently asked questions

### Is it legal to scrape Twitch?

Collecting publicly available Twitch data, such as channel names, follower counts and bios shown to every visitor, is common practice for influencer and market research. Channels belong to people, and personal data is protected by laws such as the GDPR and the CCPA, so collect only what you have a legitimate reason to use. Streams and videos are also protected by copyright. Check Twitch's terms for your use case and ask your lawyer if you are unsure.

### Is there an official Twitch API?

Yes. The Twitch Helix API returns users, channels, live streams, videos and clips. Every call needs an app registered in the Twitch developer console and an OAuth access token, calls are rate limited per minute, and some data, such as a channel's follower list, needs extra permissions from the broadcaster. A scraper reads the public channel page with none of that setup.

### What Twitch pages can I scrape?

Channel pages ( https://www.twitch.tv/<username> ) and their /about and /videos tabs, plus the category directory pages you use to find channels. A channel page returns the username, display name, follower count, bio, profile image, social links and listed videos.

### Can I scrape Twitch follower counts?

Yes. channel.follower_count holds the exact follower number of the channel. Run the same channels weekly in Batch and store the counts with the date to see growth.

### How do I scrape Twitch with Python?

Send a GET request to https://api.zenrows.com/v1/ with your API key, the channel URL, Adaptive Stealth Mode and Extract turned on, as in the Python example above. The parsed key of the response holds the channel as a Python dictionary. The zenrows package on PyPI wraps the same request.

### How many Twitch channels can I scrape?

Send one URL per request, or a whole roster as a Batch job that runs the URLs in parallel and keeps your own ID on each result. One Batch job accepts more than 10,000 URLs, sent inline or as a CSV file.

### Do I need to log in to scrape Twitch?

No. Channel pages, follower counts and bios are public to logged-out visitors, and that is what the scraper reads. Anything behind a login, such as subscriber-only content, stays out of scope.

### Can AI agents scrape Twitch with Zenrows?

Yes. Connect the Zenrows MCP server to Claude, Cursor, Codex or any MCP client, or give your agent the Zenrows CLI. Ask for the channels you want in plain language and the agent calls Fetch and Extract for you.

### Can I scrape Twitch on a schedule?

Yes. Create a scheduled Batch job with your Twitch URLs and the same settings as a single request, and Zenrows runs it on its side: every few hours, once a day, at set times on chosen days, or once at a future date. Each run keeps its own results, a webhook can notify your app when a run finishes, and the schedule can be paused or resumed at any time.

### Which integrations work with the Twitch scraper?

Zenrows works with n8n, Make, Zapier, Clay, Dify, LangChain, LlamaIndex, CrewAI and Mastra, plus the Python, Node.js and Go SDKs and any HTTP client. A common setup logs weekly follower counts to Google Sheets from n8n or Make. See the integrations page for the full list.

### What format does the data come in?

JSON by default, with the structured record in parsed and the original page in html . You can also ask for the page as Markdown or plain text, which is what most LLM and RAG pipelines want.

All scrapers: https://www.zenrows.com/scrape. Start free: https://app.zenrows.com/register. Docs: https://docs.zenrows.com
