# Kick Streamer Finder by Category - Emails, Socials, New Only (`neverempty/kick-streamer-finder`) Actor

Find the Kick streamers live in any category right now, with follower and viewer counts, stream title, language, social links and the business email each streamer published in the channel bio or panels. Filter by followers, viewers, language or email; get only new streamers on each scheduled run.

- **URL**: https://apify.com/neverempty/kick-streamer-finder.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Social media, Lead generation, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 streamer returneds

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

## Kick Streamer Finder by Category - Emails, Socials, New Only

Find the Kick streamers who are live in any category right now, with follower count, current viewers, stream title, language, tags, bio, social links and the **business email the streamer published** in the channel bio or About panels. Filter by followers, viewers, language or "has an email", and put it on a schedule with monitoring on to receive **only streamers you have not received before**.

You pay per streamer row returned. Categories that do not exist, categories nobody is streaming, filters that match nobody and limits that cut the run short come back as free rows that say why.

### Best for

- **Influencer outreach for a game launch or sponsorship** - list the streamers live in your game on Kick, or in the games your players play, with the contact address each one published for business.
- **Finding small and mid-size creators** - set `maxFollowers` and `minViewers` to skip the giants and find channels that answer emails and fit a smaller budget.
- **A daily feed of new streamers** - with `monitoringMode` on a daily schedule, each run returns only streamers who were not in an earlier run, so the list grows without repeats.
- **Market lists by language** - the streamers live in a category in Spanish, Portuguese, Turkish, Arabic or any other language Kick offers.

### What each row contains

- **Who** - `username`, `slug`, `url`, `channelId`, `userId`, `profileImageUrl`, `verified`, `isAffiliate`, `bio`.
- **Size** - `followerCount`, and `viewerCount` at the moment of the run.
- **The stream** - `game`, `gameSlug`, `categoryId`, `inputGame` (what you typed), `streamTitle`, `language`, `tags`, `isMature`, `streamStartedAt`, `liveForMinutes`, `streamId`.
- **Contact** - `email` (the first business email found), `emailOwner`, `emails` (all of them), and `emailDetails` with where each address was found (`bio` or `panel`) and who it seems to belong to.
- **Social links** - `xUrl`, `instagramUrl`, `youtubeUrl`, `tiktokUrl`, `discordUrl`, `facebookUrl`, all links found in `socialLinks`, the profile links the streamer filled in on Kick in `profileSocials`, and every panel link in `linkUrls`.

#### Emails: only what the streamer published

The email comes **only from text the streamer published on the channel page**: the bio and the title and text of the About panels. Addresses written in a common disguised form, such as `name [at] domain [dot] com`, are turned back into a normal address. Nothing is guessed and nothing is looked up elsewhere. An address that appears only inside a panel **image** is not read, so a streamer can have a contact address that this Actor does not return.

`emailOwner` says whose address it seems to be, as far as the text shows:

| `emailOwner` | Meaning |
|---|---|
| `streamer` | The address contains the channel name, so it is most likely the streamer's own. |
| `agency` | The address follows words such as management, agency or booking, or it is on a company domain that does not contain the channel name. It may belong to a talent agency, a team or a company the streamer works with. |
| `unknown` | A free email address (Gmail, Outlook and similar) without the channel name. It may be the streamer's, a manager's or a team's. |

This is a reading of the text, not a confirmation from the streamer. Check before you write.

### Monitoring: only new streamers

Turn on `monitoringMode` and the Actor remembers every streamer it returned **and charged for**. Later runs skip them and return only streamers not returned before. A category where everyone matching was already returned gives one free `no-new-since-last-run` row.

- A streamer who was found but not returned, for example because the run reached its maximum total charge, is **not remembered**, so they still count as new next time.
- The memory is shared by all your runs of this Actor, across all categories. `resetMonitoringState` clears it.
- Two monitoring runs that start at the same time do not both charge you for the same streamer: before returning anything, each run marks the streamers it is about to return, waits briefly, and leaves out anyone another run marked first. This works on runs that overlap by more than a couple of seconds; the storage it uses has no atomic update, so it cannot be fully watertight for runs that write at exactly the same instant.
- The 100,000 most recently returned streamers are remembered.

### Rows that are never charged

When there is nothing to return, the run says why instead of returning an empty result:

- `no-such-game` - Kick has no category with that name or slug. The row lists Kick's closest matches.
- `no-live-streams` - nobody is streaming in that category on Kick right now.
- `no-match` - streamers are live, but none matches your filters. The row says how many each filter left out.
- `no-new-since-last-run` - monitoring is on, and every matching streamer was already returned by an earlier run, or is being returned by another monitoring run that started at the same time.
- `blocked` - Kick answered with a rate limit, a bot check or an empty answer three times in a row. The category is not reported as empty.
- `unreadable` - Kick sent an error or an answer that could not be read. Its message is included.
- `robots-disallowed` - Kick's robots.txt does not allow a page the run needed, so it was not requested.
- `invalid-input` - the text is not a category name, slug, URL or number, a language code is not one Kick accepts, or a filter value is not valid.
- `max-records-reached` - `maxRecords` was reached, or more than 50 categories were given. The row says which category was not searched to the end and which categories were not searched.
- `request-limit-reached` - `maxRequests` was used up. The row says which categories were not searched to the end.
- `budget-reached` - the run's maximum total charge was reached. The row says how many streamers fit and which categories were not searched.

### Input

| Field | What it does |
|---|---|
| `games` | Categories, one per line: the name (`VALORANT`, `Just Chatting`), the slug (`grand-theft-auto-v`), the category URL or the category number. Up to 50 per run. Empty = the example category VALORANT. |
| `maxStreamersPerGame` | Streamers to return per category (1 to 1,000, default 100). |
| `maxRecords` | Charged rows per run in total (default 1,000). |
| `maxRequests` | Safety limit on pages read (default 300, about 140 streamers). |
| `minFollowers`, `maxFollowers` | Follower range. |
| `minViewers`, `maxViewers` | Current viewer range. |
| `languages` | Stream language codes, for example `en`, `es`, `pt`, `tr`, `ar`. |
| `onlyWithEmail` | Return only streamers with a published email. Streamers without one are not charged. |
| `monitoringMode` | Return only streamers not returned before. |
| `resetMonitoringState` | Forget the remembered streamers. |
| `useProxy` | Retry through Apify Proxy when Kick slows the run down (on by default). |

Example: the English-speaking Grand Theft Auto V streamers with 1,000 to 50,000 followers who published an email.

```json
{
    "games": ["Grand Theft Auto V"],
    "minFollowers": 1000,
    "maxFollowers": 50000,
    "languages": ["en"],
    "onlyWithEmail": true
}
```

Rows come sorted by current viewers within each category, and each streamer appears once per run even if you list two categories they could match.

### Good to know

- **Up to 1,000 streamers per category.** In the largest category measured on 2026-10-19 (Just Chatting, with more than 1,000 streams live), the whole list could be read to the end.
- **Live right now only.** Streamers who are offline at the moment of the run are not found.
- **The language filter uses the language each stream is set to**, as the streamer chose it.
- **Social links come from the bio, the profile links and the About panels.** Links shown only inside panel images are not read.
- **Follower and viewer counts are the numbers at the moment of the run.**
- The Actor reads public channel pages only, without logging in, with a short pause between requests and a wait before trying again when Kick asks it to slow down. Kick can change its pages without notice; if that happens, runs return `unreadable` or `blocked` rows instead of wrong data, and we fix the Actor.
- Use the emails for genuine business contact, and follow the anti-spam and privacy laws that apply to you.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

## `games` (type: `array`):

The Kick categories to search, one per line: the name as Kick shows it (VALORANT, Just Chatting, Grand Theft Auto V), the slug (grand-theft-auto-v), the category URL (https://kick.com/category/valorant) or the category number. A name Kick does not know comes back as a free row with Kick's closest matches. Up to 50 per run. If you leave this empty, the example category VALORANT is searched and every row says so in inputGame.

## `maxStreamersPerGame` (type: `integer`):

How many matching streamers to return for each category. Streamers come in order of current viewers, most first.

## `maxRecords` (type: `integer`):

The most charged rows this run returns across all categories. When it is reached, a free row says which categories were not searched to the end.

## `maxRequests` (type: `integer`):

A safety limit on how many pages this run reads. Each streamer takes 2 (the channel and its panels), and each list page of up to 100 live streams takes 1, so the default of 300 covers about 140 streamers. Raise it for bigger runs. When the limit is hit, a free row says what was not searched.

## `minFollowers` (type: `integer`):

Return only channels with at least this many followers. Leave empty for no lower limit.

## `maxFollowers` (type: `integer`):

Return only channels with at most this many followers, for example to find small and mid-size streamers. Leave empty for no upper limit.

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

Return only streams with at least this many viewers at the moment of the run.

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

Return only streams with at most this many viewers at the moment of the run.

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

Language codes of the stream as Kick sets them, for example en, es, pt, de, fr, ar, tr. Leave empty for all languages. A code Kick does not accept comes back as a free row.

## `onlyWithEmail` (type: `boolean`):

On = return only streamers who published an email address in their channel bio or panels. Streamers without one are read but not returned, so they cost nothing.

## `monitoringMode` (type: `boolean`):

On = the Actor remembers every streamer it returned and charged for, and later runs return only streamers it has not returned before. Put it on a schedule to receive new streamers in a category each day. Streamers who were found but not returned (for example because the run hit its maximum total charge) are not remembered, so they still count as new next time. The memory is shared by all your runs of this Actor.

## `resetMonitoringState` (type: `boolean`):

Clears the list of streamers already returned, so the next monitoring run returns everyone again. This affects all your monitoring runs of this Actor.

## `useProxy` (type: `boolean`):

On = if Kick answers with a bot check or a rate limit, the run retries through Apify Proxy instead of stopping. Off = such an answer is reported as a free row.

## Actor input object example

```json
{
  "games": [
    "VALORANT"
  ],
  "maxStreamersPerGame": 100,
  "maxRecords": 1000,
  "maxRequests": 300,
  "onlyWithEmail": false,
  "monitoringMode": false,
  "resetMonitoringState": false,
  "useProxy": true
}
```

# Actor output Schema

## `results` (type: `string`):

One row per Kick streamer live in the categories you asked for: username, channel URL, follower count, current viewer count, stream title, language, tags, start time, verified flag, bio, the business email the streamer published in the bio or panels with whether it looks like the streamer's own or an agency's, and links to X, Instagram, YouTube, TikTok, Discord and Facebook. Categories Kick does not know, categories nobody is streaming, filters that match nobody and limits that cut the run short come back as their own free rows.

# 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 = {
    "games": [
        "VALORANT"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/kick-streamer-finder").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 = { "games": ["VALORANT"] }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/kick-streamer-finder").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 '{
  "games": [
    "VALORANT"
  ]
}' |
apify call neverempty/kick-streamer-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/kick-streamer-finder"
        }
    }
}
```

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/2mhViQbVlSOyfw6vr/builds/ZRT9vFkNW6aLe61Pl/openapi.json
