# Kick Channel Scraper (`crawlerbros/kick-channel-scraper`) Actor

Scrape Kick.com streamer channels - profile info, follower counts, live status, VODs, clips, gift leaderboards, custom emotes, and the full category/subcategory taxonomy. No login, no proxy, public JSON API.

- **URL**: https://apify.com/crawlerbros/kick-channel-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, Social media, Videos
- **Stats:** 20 total users, 10 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

## Kick Channel Scraper

Scrape Kick.com — the live-streaming platform — for streamer channel profiles, follower counts, live status, past broadcasts (VODs), clips, gift leaderboards, custom emotes, and the site-wide category/subcategory taxonomy. Uses Kick's public JSON API directly. No login, no cookies, no proxy required.

### What this actor does

- **Channel profiles** — follower count, live status, bio, social links, subscriber badges, chatroom settings, recent categories
- **VODs (past broadcasts)** — title, duration, views, thumbnail, stream categories, per-video playback URL
- **Clips** — either a specific channel's clips or site-wide trending clips, with sort/period/category filters
- **Gift leaderboards** — top gifters per channel, all-time / weekly / monthly
- **Category taxonomy** — browse subcategories (games, IRL activities, etc.), optionally filtered to one of Kick's 6 top-level categories, plus the 6 top-level categories themselves
- **Channel emotes** — a channel's own custom emote set (name, subscriber-only flag, full-size image URL)

### Modes

| Mode | Description | Requires |
|---|---|---|
| `channel` | One channel's profile + live status | `channelSlug` |
| `videos` | A channel's recent VODs | `channelSlug` |
| `clips` | A channel's clips, or global trending clips if `channelSlug` is omitted | — |
| `subcategories` | Browse the subcategory list | — |
| `leaderboard` | A channel's top-gifter leaderboard | `channelSlug` |
| `categories` | The 6 fixed top-level categories | — |
| `emotes` | A channel's own custom emote set | `channelSlug` |

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `categories` (shown as `channel` in the Console) | `channel` / `videos` / `clips` / `subcategories` / `leaderboard` / `categories` / `emotes` |
| `channelSlug` | string | – (shown as `xqc` in the Console) | Kick username, e.g. `xqc`, `adinross` |
| `clipSort` | string | `date` | `date` (newest) or `view` (most viewed) — global clips only |
| `clipPeriod` | string | `all` | `day` / `week` / `month` / `all` — global clips only |
| `clipCategory` | string | – | Restrict global trending clips to one top-level category |
| `subcategoryCategory` | string | – | Restrict subcategory browsing to one top-level category |
| `maxItems` | integer | `20` | Cap on emitted records (1–2000); ignored by `channel` (always 1 record) |

**Note on defaults vs. Console prefill:** `mode`'s underlying schema default is `categories` (Kick's fixed, always-available 6-category list) so that any API/integration call that omits `mode` and `channelSlug` entirely still gets real data back deterministically. The Console UI shows `channel` + `channelSlug=xqc` pre-filled as a friendlier starting point for manual runs — clicking "Start" without editing anything runs the channel-profile example above. `channelSlug` itself has no default (only a Console prefill) so that a `mode=clips` call which omits `channelSlug` correctly falls through to global trending clips instead of silently being scoped to `xqc`.

#### Example: channel profile

```json
{ "mode": "channel", "channelSlug": "xqc" }
```

#### Example: a channel's recent VODs

```json
{ "mode": "videos", "channelSlug": "adinross", "maxItems": 10 }
```

#### Example: global trending clips this week, gambling category

```json
{ "mode": "clips", "clipSort": "view", "clipPeriod": "week", "clipCategory": "gambling", "maxItems": 50 }
```

#### Example: a channel's own clips

```json
{ "mode": "clips", "channelSlug": "trainwreckstv", "maxItems": 30 }
```

#### Example: browse subcategories under "Games"

```json
{ "mode": "subcategories", "subcategoryCategory": "games", "maxItems": 100 }
```

#### Example: top gifters for a channel

```json
{ "mode": "leaderboard", "channelSlug": "xqc" }
```

#### Example: the 6 top-level categories

```json
{ "mode": "categories" }
```

#### Example: a channel's custom emotes

```json
{ "mode": "emotes", "channelSlug": "xqc" }
```

### Output

Fields vary by `recordType` (`channel`, `video`, `clip`, `subcategory`, `leaderboardEntry`, `category`, `emote`). Empty/unavailable fields are omitted rather than emitted as null.

**Channel:** `slug`, `channelId`, `username`, `bio`, `profilePicUrl`, `followersCount`, `verified`, `isAffiliate`, `isBanned`, `vodEnabled`, `subscriptionEnabled`, `socials` (instagram/twitter/youtube/discord/tiktok/facebook), `bannerUrl`, `chatroom` (chatMode, slowMode, followersMode, subscribersMode, emotesMode), `recentCategories[]`, `isLive`, `streamTitle`, `viewerCount`, `startTime`, `streamThumbnailUrl`, `liveCategories[]`, `kickUrl`

**Video (VOD):** `videoId`, `channelSlug`, `title`, `language`, `isMature`, `durationSeconds`, `views`, `viewerCount`, `createdAt`, `startTime`, `tags[]`, `thumbnailUrl`, `streamUrl`, `videoStatus`, `categories[]`, `videoUrl`

**Clip:** `clipId`, `title`, `isMature`, `privacy`, `durationSeconds`, `views`, `likes`, `createdAt`, `clipUrl`, `thumbnailUrl`, `channelSlug`, `channelUsername`, `channelProfilePicUrl`, `creatorUsername`, `creatorSlug`, `category` (id/name/slug), `parentCategory`, `kickUrl`

**Subcategory:** `subcategoryId`, `name`, `slug`, `tags[]`, `description`, `isMature`, `isPromoted`, `viewers`, `bannerUrl`, `parentCategory` (id/name/slug), `kickUrl`

**Leaderboard entry:** `channelSlug`, `period` (`allTime`/`week`/`month`), `rank`, `username`, `userId`, `quantity`, `kickUrl`

**Category (top-level):** `categoryId`, `name`, `slug`, `icon`, `kickUrl`

**Emote:** `emoteId`, `name`, `channelSlug`, `subscribersOnly`, `emoteUrl`, `kickUrl`

### Use cases

- **Streamer analytics** — track a creator's follower growth, live status, and VOD/clip performance over time
- **Talent scouting / esports** — discover trending clips per game category to spot rising streamers
- **Content aggregation** — pull recent VODs and clips for a highlight roundup
- **Creator-economy research** — analyze gift-leaderboard data to study viewer spending behavior
- **Category/tag discovery** — enumerate Kick's full subcategory taxonomy for content classification
- **Emote/brand asset collection** — pull a streamer's custom emote set and image URLs for chat overlays, merch, or Discord servers

### FAQ

**Do I need a Kick account or API key?** No. Every mode uses Kick's public JSON endpoints, the same ones the kick.com website itself calls.

**Why is `isLive` sometimes `false` with no other live fields?** Kick only returns live-stream data (title, viewer count, thumbnail) while the channel is actually broadcasting. Offline channels still return their full profile — follower count, bio, socials, etc.

**Why does `videos` mode return at most ~18-20 items?** Kick's public VOD endpoint returns only the most recent broadcasts per channel and doesn't paginate further; this actor surfaces everything the API exposes.

**What are the 6 top-level categories?** Games, IRL, Music, Gambling, Creative, Alternative — used to filter global trending clips and the subcategory browser.

**Why does `subcategories` mode return at most ~200 records (per `subcategoryCategory` filter or overall)?** Kick's subcategory-browse endpoint reports a much larger `total`/`last_page`, but silently caps real pagination at an internal ceiling (page 20 of 10 items each) — requesting a page past that ceiling just re-serves the same last page instead of erroring or returning empty. This actor detects the ceiling via the endpoint's own `current_page` field and stops there, so it never fabricates duplicate or phantom records; ~200 is the genuine amount Kick exposes per query through this endpoint.

**Why is `clips` mode slower for some `clipCategory` values than others?** Kick's global clips endpoint silently ignores the `category` query parameter server-side, so this actor filters client-side against each clip's own category instead. Popular categories (`games`, `gambling`, `irl`) are common in the trending feed and fill `maxItems` quickly; niche categories (`music`, `creative`, `alternative`) are genuinely rarer in the feed, so reaching a large `maxItems` for one of those can require scanning many more pages and take noticeably longer. This is an upstream data-distribution characteristic, not a bug — the actor always returns only correctly-matching records, just at different speeds per category.

**Why doesn't `emotes` mode return Kick's global/emoji emotes too?** Kick's emotes endpoint returns 3 sets per request: the channel's own custom set, plus a site-wide "Global" set and an "Emoji" set that are identical for every channel. Only the channel-specific set is returned so the output actually reflects the requested `channelSlug` — the Global/Emoji sets would otherwise look like a bug (same records for every channel).

**Is there a search mode?** Not currently. Kick's search endpoints require an unpublished parameter format that returns `400` for every guessed name; a client-rendered `kick.com/search` page was the only route that returned data, and no public JSON endpoint could be confirmed to back it reliably. Adding search would risk shipping a mode that silently breaks, so it's left out until a stable public endpoint is found.

**How fresh is the data?** Real-time — every request hits Kick's live API directly.

# Actor input Schema

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

What to fetch.

## `channelSlug` (type: `string`):

Kick channel/streamer username, e.g. `xqc`, `adinross`, `trainwreckstv`. Required for `channel`, `videos`, `leaderboard`, `emotes` modes. Leave blank for `clips` global trending or `subcategories`/`categories`/`leaderboard`-less browsing.

## `clipSort` (type: `string`):

Sort order for global trending clips. Ignored when `channelSlug` is set (channel clips are returned newest-first by the API).

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

Time window for global trending clips. Ignored when `channelSlug` is set.

## `clipCategory` (type: `string`):

Restrict global trending clips to one top-level category. Ignored when `channelSlug` is set.

## `subcategoryCategory` (type: `string`):

Restrict the subcategory browse list to one of Kick's 6 top-level categories.

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

Hard cap on emitted records (ignored by `channel` mode, which always emits exactly 1 record).

## Actor input object example

```json
{
  "mode": "channel",
  "channelSlug": "xqc",
  "clipSort": "date",
  "clipPeriod": "all",
  "clipCategory": "",
  "subcategoryCategory": "",
  "maxItems": 20
}
```

# Actor output Schema

## `kickRecords` (type: `string`):

Dataset containing all scraped Kick.com records.

# 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": "channel",
    "channelSlug": "xqc",
    "clipSort": "date",
    "clipPeriod": "all",
    "clipCategory": "",
    "subcategoryCategory": "",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/kick-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 = {
    "mode": "channel",
    "channelSlug": "xqc",
    "clipSort": "date",
    "clipPeriod": "all",
    "clipCategory": "",
    "subcategoryCategory": "",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/kick-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 '{
  "mode": "channel",
  "channelSlug": "xqc",
  "clipSort": "date",
  "clipPeriod": "all",
  "clipCategory": "",
  "subcategoryCategory": "",
  "maxItems": 20
}' |
apify call crawlerbros/kick-channel-scraper --silent --output-dataset

```

## MCP server setup

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