# Kwai Follower Count Scraper & Monitor - Profile Stats (`neverempty/kwai-follower-count-scraper`) Actor

For influencer tracking and campaign reports on Kwai: followers, following, likes received, video count, name, bio and verified flag of public accounts, as exact whole numbers (@carlinhos had 11,315,834 followers on 2026-09-19, not "11.3M"). Monitoring returns only accounts that moved. Unofficial.

- **URL**: https://apify.com/neverempty/kwai-follower-count-scraper.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Social media, Videos, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.92 / 1,000 profile row 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

## Kwai Follower Count Scraper & Monitor - Profile Stats

Get the **follower count** and profile stats of public Kwai accounts from their usernames or profile URLs: followers, following, likes received, number of videos, display name, bio, avatar, verified flag, creator level and category. The counts are the exact whole numbers Kwai stores for the profile (for example `11315834`), not a shortened figure such as "11.3M".

Turn on **monitoring mode**, schedule the Actor, and a run returns an account **only when its follower count moved** by at least the minimum you set since the row last returned for it, with the change and the followers per hour.

Unofficial. Public profile data only. This Actor is not affiliated with, endorsed by or connected to Kwai or its operator. It reads the public profile page that anyone can open in a browser without logging in, and it does not read private accounts, messages, follower lists or any data behind a login.

### What you can use it for

- **Influencer tracking**: schedule monitoring mode on the creators you work with and see who is gaining or losing followers, and how fast (`followerCountDelta`, `followersPerHour`).
- **Campaign reporting**: paste the accounts of a campaign and export follower, likes and video counts to a spreadsheet or dashboard.
- **Creator research**: compare accounts by followers, likes received and number of videos, with the verified flag and Kwai's category.
- **Lists of accounts**: turn a list of usernames into user ids, profile URLs, names and bios.

### How it works

1. Paste usernames (`@carlinhos`, `carlinhos`) or profile URLs (`https://www.kwai.com/@carlinhos`).
2. For each account the Actor opens the public profile page `https://www.kwai.com/@<username>` and reads the profile data Kwai includes in that page. The numbers shown in the page's HTML before it loads are placeholders ("0 Followers"), so the Actor reads Kwai's own profile data instead, without running any of the page's code.
3. Every row carries the **username Kwai answered with** (`username`) and the user id. Kwai sometimes answers a username with a different account's page (on 2026-09-19, `@-bad-` was answered with `@hernandezvicki670`); `usernameMatchesInput` is `false` on such rows.
4. Private accounts, usernames Kwai returns no profile for, bot checks and invalid input get a free row that says why.

**Kwai usernames are case-sensitive.** On 2026-09-19 `@carlinhos` (11.3 million followers), `@Carlinhos` (20 followers) and `@CARLINHOS` were three different accounts. Type usernames exactly as Kwai shows them; the Actor does not change their case.

### Input

| Field | Default | What it does |
| --- | --- | --- |
| `usernames` | example accounts | Usernames or profile URLs, one per line (commas also separate entries, and so do spaces between entries that are all usernames or profile URLs). The same account is read and charged once; a repeat gets a free `duplicate` row, including a different username that Kwai answers with the same user id. Short share links (`k.kwai.com`, `kwai.app`) are not followed. |
| `maxResults` | `100` | With monitoring off, stop after this many rows. In monitoring mode it does not cut changes. Up to 1,000 entries per run. |
| `monitoringMode` | `false` | Remember each account's follower count and return an account only when it moves by at least `minFollowerChange`. |
| `minFollowerChange` | `1` | Monitoring mode only: how many followers (up or down) an account must move since the row last returned for it before it is returned again. Small moves add up, because the comparison is always against the last returned row. |
| `resetMonitoringState` | `false` | Forget every remembered count, so the next monitoring run returns every account again. |
| `useProxy` | `true` | Pages are requested directly; only a page that answers with a bot check, an empty response or no response is retried through a proxy session. |

If you leave `usernames` out with monitoring off, the example accounts `@carlinhos` and `@flamengo` are read and every row says so in `inputUsername`. In monitoring mode `usernames` is required, so a schedule never pays to watch the examples.

Example input:

```json
{
    "usernames": ["@carlinhos", "https://www.kwai.com/@flamengo"],
    "monitoringMode": true,
    "minFollowerChange": 100
}
```

### Output

One row per account whose follower count was read (`status: "ok"`, charged). Example (monitoring mode, second run):

```json
{
    "source": "kwai-profile",
    "status": "ok",
    "scrapedAt": "2026-09-19T16:00:00.000Z",
    "inputUsername": "@carlinhos",
    "username": "carlinhos",
    "usernameMatchesInput": true,
    "userId": "150001659540962",
    "encryptedUserId": "3xaidyhckcztb9u",
    "profileUrl": "https://www.kwai.com/@carlinhos",
    "displayName": "Carlinhos Maia",
    "bio": "Perfil oficial do @carlinhos no Kwai.",
    "avatarUrl": "https://aws-br-pic.kwai.net/bs2/overseaHead/20241224000250_BMTUwMDAxNjU5NTQwOTYy_s.jpg",
    "isVerified": true,
    "isBanned": false,
    "creatorLevel": 1,
    "category": null,
    "followerCount": 11315834,
    "followingCount": 11,
    "likesReceivedCount": 15635111,
    "videoCount": 7670,
    "publicVideoCount": 7670,
    "change": "followers-changed",
    "isFirstCheck": false,
    "previousCheckedAt": "2026-09-19T10:00:00Z",
    "previousCountReadAt": "2026-09-19T10:00:00Z",
    "previousFollowerCount": 11314000,
    "previousUsername": "carlinhos",
    "hoursSincePreviousCount": 6,
    "followerCountDelta": 1834,
    "followersPerHour": 305.67
}
```

| Column | Meaning |
| --- | --- |
| `inputUsername` | What you typed for this row. |
| `username` | The username Kwai answered with. `usernameMatchesInput` is `false` when it differs from what you typed. |
| `userId` / `encryptedUserId` | Kwai's numeric user id and the short id Kwai uses in some links. Duplicates and monitoring are keyed on `userId`. |
| `profileUrl` | `https://www.kwai.com/@<username>` for the username Kwai answered with. |
| `displayName` / `bio` / `avatarUrl` | Name, profile text (phone numbers and e-mail addresses are masked) and profile picture. `displayName` and `avatarUrl` are `null` on a banned account (see `isBanned`). |
| `isVerified` / `creatorLevel` / `category` | Kwai's verified flag, creator level and the category Kwai gives the account (for example `sports`), `null` when Kwai gives none. |
| `isBanned` | `true` when Kwai marks the account as banned. Kwai then shows a placeholder name ("TA") and a placeholder picture instead of the account's own, so `displayName` and `avatarUrl` are `null`; the counts are the ones Kwai still stores for the account. On 2026-09-21 `@neymarjr` was such an account. |
| `followerCount` / `followingCount` | Followers and accounts followed, as whole numbers. |
| `likesReceivedCount` | Likes the account's videos received in total. |
| `videoCount` / `publicVideoCount` | Videos on the account, and how many of them are public. |
| `change` | Monitoring mode only: `"first-check"` (first time this account is seen) or `"followers-changed"` (moved by at least `minFollowerChange`). `null` with monitoring off. |
| `isFirstCheck` / `previousCheckedAt` / `previousCountReadAt` / `previousFollowerCount` / `previousUsername` | The row last returned for this account: when it was checked, when its count was read, its follower count and its username then. |
| `hoursSincePreviousCount` / `followerCountDelta` / `followersPerHour` | Time since that count, the change in followers (negative when followers were lost) and the change per hour. |

#### The counts are whole numbers

Kwai stores whole-number counts for a profile and the Actor passes them through. On 2026-09-19, read from Apify: `@carlinhos` 11,315,834 followers, `@flamengo` 10,312,492 followers, `@topfilmeseseriesnatv` 382,711 followers; for accounts that have videos these match the follower, like and video counts in the page's structured data. Reading the same three accounts four times about 20 seconds apart (from a home connection, the same day) gave the same or neighbouring follower counts (the counts moved by one or two followers, not back and forth), which is why monitoring compares follower counts directly.

The figure is what Kwai stores at the moment of the request; Kwai may count followers in its own way (for example, how quickly removed or banned followers are subtracted), and the Actor does not correct it.

### Rows that are never charged

| `status` | When |
| --- | --- |
| `private-account` | A private account. Kwai publishes no profile data for it; the follower and like counts Kwai prints in the page description are passed through as `followerCountShown` and `likeCountShown` and are not sold. |
| `no-profile-returned` | Kwai's page for this username carried no profile. Kwai answers usernames that do not exist this way, so check the spelling and the case. The row does not claim the account does not exist. |
| `no-count-returned` | Kwai returned the profile without a usable follower count. |
| `blocked` | Kwai answered with a bot check or an empty response (after the retries). The account is not reported as unavailable. |
| `unreadable` | The page could not be read. Nothing is guessed. |
| `invalid-input` | Not a Kwai username or profile URL (or the input as a whole was not usable). |
| `duplicate` | The same account as an earlier entry in the run (same username, or another username Kwai answered with the same user id). |
| `no-change` | Monitoring mode: none of the accounts checked moved by `minFollowerChange` or more. |
| `not-checked` | Entries at the end of the list that were not read because `maxResults` rows were already returned, or entries beyond the first 1,000. |
| `stopped-kwai-not-answering` | Kwai answered 3 accounts in a row with a bot check, no response or a page that could not be read (after the retries), so the rest of the list was not requested in this run. The row says how many entries were not read. |
| `budget-reached` | The run's maximum total charge had no room for more: says how many entries were not read, or that an account was read but its row did not fit. |

### Pricing

- **$4.00 per 1,000 profile rows**, charged only for rows with `status: "ok"`.
- Monitoring mode adds **$0.30 per 1,000 profile checks**: every account whose follower count is read is one check, changed or not. Private accounts, usernames without a profile, invalid input and bot checks are not checked or charged.
- Example: 50 accounts checked every hour is 36,000 checks a month, which is **$10.80**, plus $4.00 per 1,000 rows for the accounts that moved.

The Actor reads an account only when the run's maximum total charge still has room for its row (in monitoring mode, for a check and a row together), so a low limit ends the run with a `budget-reached` row instead of charges for checks whose rows cannot be returned.

### Monitoring mode

1. Run once with `monitoringMode: true`: every account comes back as `"first-check"` and its follower count is remembered.
2. Schedule the same input. Each run returns only the accounts whose follower count moved by at least `minFollowerChange` since the row last returned for them. If nothing moved, the run returns one free `no-change` row, and only the check fee applies.
3. Counts are remembered per Kwai user id, so a renamed account keeps its history, and adding or removing accounts from the list does not reset the others.
4. A count is remembered only after its row was delivered. A row cut off by the maximum total charge is not remembered, so it is still returned when the account is checked again.

Do not put the same account in two schedules that can run at the same time: the remembered counts are merged when saved, but Apify's key-value store has no atomic update, so two runs that finish at the same moment can still overwrite each other.

### Limits

- Up to 1,000 entries per run; split longer lists across runs.
- The Actor pauses half a second between pages, and stops requesting (with a free `stopped-kwai-not-answering` row) after Kwai fails to answer 3 accounts in a row.
- Only public profile pages are read. Follower lists, videos, comments and private accounts are not read.
- Counts are what Kwai's page carries at the time of the request.

# Actor input Schema

## `usernames` (type: `array`):

Accounts to read: @carlinhos, carlinhos, or https://www.kwai.com/@carlinhos (a /video/... path after the username is fine, and so is https://m.kwai.com/user/@carlinhos). One per line (commas also separate entries, and so do spaces between entries that are all usernames or profile URLs). Kwai usernames are case-sensitive: @carlinhos and @Carlinhos are different accounts, so type them exactly as Kwai shows them. Short share links (k.kwai.com, kwai.app) are not followed: open one in a browser and paste the profile URL. The same account is read and charged once, and a repeat gets a free 'duplicate' row. If you leave this field out with monitoring off, two example accounts are read; with monitoring on it is required. An empty list is rejected.

## `maxResults` (type: `integer`):

With monitoring off, reading stops once this many charged rows have been returned, and a free row says how many entries at the end of the list were not read. Private accounts, usernames without a profile and unreadable entries do not count. In monitoring mode it does not limit the changes returned: every account in the list is checked, as far as the run's maximum total charge allows. Up to 1,000 entries are read per run.

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

Off = every account comes back with its current counts, charged per row. On = the Actor remembers each account's follower count and, on later runs, returns an account only when its follower count moved (up or down) by at least the minimum below since the row last returned for it, with the change and the followers per hour. The first run returns every account once to set the baseline. **In monitoring mode every account whose follower count is read costs $0.30 per 1,000 checks, changed or not** (private accounts, usernames without a profile, unreadable entries and bot checks are free), plus the row price for the rows returned. Example: 50 accounts every hour = 36,000 checks a month = $10.80. The Actor reads only as many accounts as the run's maximum total charge can pay for with a check and a change row each. Counts are remembered per Kwai user id; do not put the same account in two schedules that can run at the same time.

## `minFollowerChange` (type: `integer`):

Monitoring mode only. An account is returned when its follower count differs from the count in the row last returned for it by at least this many followers, up or down. Smaller moves are not returned, and they add up: the comparison is always against the last returned row, so 3 followers a day with a minimum of 10 is returned on the fourth day. 1 = any change.

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

Clears every remembered count for this Actor, so the next monitoring run returns each account once again as a first check. This affects all your monitoring runs, because counts are stored per account rather than per list. Turn it off again after one run: left on in a schedule, every run returns every account as a first check and charges the row price for it.

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

Every page is requested directly first. Only if Kwai answers a page with a bot check, an empty response or no response is that page retried through a proxy session; the next page is requested directly again. With it off, that answer is retried directly and then returned as a free 'blocked' row, and no proxy is paid for.

## Actor input object example

```json
{
  "usernames": [
    "@carlinhos",
    "@flamengo"
  ],
  "maxResults": 100,
  "monitoringMode": false,
  "minFollowerChange": 1,
  "resetMonitoringState": false,
  "useProxy": true
}
```

# Actor output Schema

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

One row per public Kwai account whose follower count was read: username, user id, profile URL, display name, bio, avatar, verified flag, creator level, category, and the follower, following, likes-received and video counts as Kwai stores them; in monitoring mode the change in followers since the row last returned for the account and the followers per hour. Private accounts, usernames Kwai returns no profile for, bot checks and invalid input come back as free rows that say why.

# 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 = {
    "usernames": [
        "@carlinhos",
        "@flamengo"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/kwai-follower-count-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 = { "usernames": [
        "@carlinhos",
        "@flamengo",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/kwai-follower-count-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 '{
  "usernames": [
    "@carlinhos",
    "@flamengo"
  ]
}' |
apify call neverempty/kwai-follower-count-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/kwai-follower-count-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/acGZPbo1EVTE0ffRR/builds/eaf0VsgclN5rsRjk5/openapi.json
