# Social Media Follower Count Tracker - 8 Networks, Change Alerts (`neverempty/social-media-follower-count-tracker`) Actor

For growth teams and agencies: follower, subscriber and member counts for TikTok, YouTube, Twitch, Telegram, Bluesky, Snapchat, GitHub and Discord in one table, with an isRounded column on every row. Five of the eight publish an exact figure. Monitoring returns an account only when its count moves.

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

## Pricing

from $3.65 / 1,000 account 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

## Social Media Follower Count Tracker - 8 Networks, Change Alerts

For growth teams and agencies: one row per account with `followerCount`, `followerLabel`, `isRounded`, `roundingPrecision`, `followingCount`, `postCount`, `displayName`, `profileUrl` and the account id the network itself reports, across TikTok, YouTube, Twitch, Telegram, Bluesky, Snapchat, GitHub and Discord. Measured on 2026-09-23: TikTok `@nasa` 1,568,256 followers, Twitch `shroud` 11,293,227 followers, Bluesky `bsky.app` 35,003,658 followers, GitHub `torvalds` 324,766 followers, Discord `python` 431,725 members. Put your whole watchlist in one list, get one table back, and in monitoring mode get a row only for the accounts whose count actually moved.

Export as JSON, CSV or Excel.

Unofficial. Public data only. Not affiliated with, endorsed by or connected to TikTok, YouTube, Twitch, Telegram, Bluesky, Snapchat, GitHub or Discord.

### The eight networks, and how exact each number is

Every row carries `isRounded` and `roundingPrecision`, because **three of the eight networks do not publish an exact figure and no scraper can make them**. Hiding that is how a "tracker" reports "no change" for weeks while an account grows.

| Network | The count is called | Measured 2026-09-23 | `isRounded` | `roundingPrecision` | Where it comes from |
|---|---|---|---|---|---|
| TikTok | `followers` | 1,568,256 (`@nasa`) | `false` | `1` | the exact figure on the profile page |
| YouTube | `subscribers` | 21,300,000 (`@mkbhd`) | `true` | `100000` | "21.3M subscribers" - three significant figures |
| Twitch | `followers` | 11,293,227 (`shroud`) | `false` | `1` | the channel page's own structured data |
| Telegram | `subscribers` | 10,671,626 (`durov`) | `false` | `1` | the full digits on the profile page |
| Bluesky | `followers` | 35,003,658 (`bsky.app`) | `false` | `1` | the public API |
| Snapchat | `subscribers` | 4,060,100 (`fcbarcelona`) | `true` | `100` | rounded to the nearest hundred |
| GitHub | `followers` | 324,766 (`torvalds`) | `false` | `1` | the official public REST API |
| Discord | `members` | 431,725 (`python`) | `true` | `null` | Discord's own `approximate_member_count` |

Details behind the three rounded ones:

- **YouTube** publishes only a rounded subscriber count. Below 1,000 it is exact ("726 subscribers"); above that it is three significant figures. `roundingPrecision` says how coarse: 21.3M rounds to the nearest 100,000, 6.58M to the nearest 10,000.
- **Snapchat** rounds to the nearest hundred. In a 28-account sample on 2026-09-14, all 17 accounts that showed a count were multiples of 100. A `subscriberCount` of `"0"` on Snapchat means "not shown", not "zero subscribers", so those accounts come back as a free `no-public-count` row instead of a zero.
- **Discord** names the field `approximate_member_count` itself, and the answer carries `Cache-Control: public, max-age=300`, so a server's count can be up to five minutes old.

On Twitch the number comes from the `ProfilePage` block of the channel page's JSON-LD, the same data Twitch publishes for search engines. All five channels measured on 2026-09-23 carried it, including channels that were not live at the time. Channels that do not exist answer `200` with a shell page that has no such block, and are reported as `no-such-account` rather than as zero followers.

On TikTok the page publishes an exact figure and a rounded one. The exact one is used for `followerCount`; the rounded one is kept in `followerCountText` so you can see both. On 14 accounts measured on 2026-09-06 the two differed on 11, by up to 41,519 followers.

### What is not here, and why

- **Instagram, Facebook, LinkedIn and Threads are not included.** Instagram's profile API answered `429` on every attempt from a datacenter address on 2026-09-23, which means the number is only reachable by routing around a rate limit through residential addresses - this Actor does not do that. Threads' public profile page returned `200` but contained no follower count at all. If those four networks are what you need, this Actor is the wrong one; say so before you run it rather than after.
- **Twitch is read only from the channel page.** Twitch's private GraphQL endpoint `gql.twitch.tv` has a `robots.txt` two lines long that reads `User-agent: *` / `Disallow: /`, so this Actor never touches it, and the official Helix API needs OAuth. The channel page `www.twitch.tv/<login>` is allowed by robots.txt and carries the follower count in its structured data, so that is the only Twitch address requested. Reserved paths that are not channels (`stream`, `search`, `login`, `videos`, `directory` ...) are rejected before any request is made.
- **Blocks, challenge pages and rate limits are never worked around.** A challenge page is not solved and the same address is not swapped for another one; the account comes back as a free row saying what happened. An Apify proxy is used for exactly one case: a request that did not reach the network at all (a connection failure).
- **No login, no tokens, no cookies.** The only headers sent are a browser `User-Agent`, an `Accept`, `Accept-Encoding: identity` and `Accept-Language`.

### Input

`accounts` takes one mixed list for all eight networks. Paste a profile URL, or write `network:handle`:

```json
{
  "accounts": [
    "tiktok:@nasa",
    "https://www.youtube.com/@mkbhd",
    "https://www.twitch.tv/shroud",
    "telegram:durov",
    "https://bsky.app/profile/bsky.app",
    "snapchat:fcbarcelona",
    "https://github.com/torvalds",
    "discord:python"
  ]
}
```

A bare handle with no network (`nasa`) is **rejected with a free row**, because the same name exists on several networks and guessing would return an account you did not ask for. If you would rather use bare handles, put them in the per-network list instead: `tiktokAccounts`, `youtubeChannels`, `twitchChannels`, `telegramChannels`, `blueskyAccounts`, `snapchatAccounts`, `githubAccounts`, `discordInvites`. The two styles can be mixed in one run.

Other settings: `maxAccounts` (cap on charged rows when monitoring is off), `monitoringMode`, `monitorOn`, `resetMonitoringState`, `useProxy`.

What each network accepts:

- **TikTok** - `@nasa`, `nasa`, `https://www.tiktok.com/@nasa`. Tag, music, search and embed URLs are rejected with a free row: robots.txt does not allow them.
- **YouTube** - `@MrBeast`, a channel id `UCX6OQ3DkcsbYNE6H8uQQuVA`, or a channel URL. Old `/user/` and `/c/` URLs are rejected with a free row, because resolving them needs a redirect this Actor does not follow.
- **Twitch** - `shroud`, `@shroud`, `https://www.twitch.tv/shroud`. Paths that are reserved by Twitch rather than channel names (`stream`, `search`, `login`, `videos`, `directory` ...) are rejected with a free row, because robots.txt disallows them.
- **Telegram** - `durov`, `@durov`, `https://t.me/durov`. Private invite links (`t.me/+...`, `t.me/joinchat/...`) are rejected: they publish no count. If you paste a `/s/` preview link the profile page is read instead, because the preview page rounds to three significant figures and the profile page does not.
- **Bluesky** - `bsky.app`, a DID, or a profile URL.
- **Snapchat** - `fcbarcelona`, `@fcbarcelona`, `https://www.snapchat.com/add/nfl`. Handles are lower-cased first, because Snapchat redirects uppercase ones.
- **GitHub** - `torvalds` or `https://github.com/torvalds`. Repository URLs are rejected. Organizations work and come back with `accountType: "Organization"`.
- **Discord** - a server named by an invite: `python`, `discord.gg/python`, `https://discord.com/invite/python`. Invite codes are case sensitive and are sent exactly as typed. `discord.com/channels/...` URLs are not invites and are rejected.

### Output

One row per account, the same columns on all eight networks:

```json
{
  "network": "github",
  "status": "ok",
  "scrapedAt": "2026-09-23T06:00:00.000Z",
  "inputAccount": "github:torvalds",
  "accountId": "1024025",
  "handle": "torvalds",
  "profileUrl": "https://github.com/torvalds",
  "displayName": "Linus Torvalds",
  "description": null,
  "followerCount": 324766,
  "followerLabel": "followers",
  "followerCountText": null,
  "isRounded": false,
  "roundingPrecision": 1,
  "followingCount": 0,
  "postCount": 12,
  "likeCount": null,
  "totalViews": null,
  "onlineCount": null,
  "accountType": "User",
  "country": null,
  "countNoun": null,
  "isVerified": null,
  "isPrivate": null,
  "accountCreatedAt": "2011-09-03T15:26:22.000Z",
  "handleMatchesInput": null,
  "change": null,
  "isFirstCheck": null,
  "previousCheckedAt": null,
  "previousFollowerCount": null,
  "followerCountChange": null,
  "previousFollowingCount": null,
  "previousPostCount": null
}
```

`accountId` is the identifier **the network itself reports** - TikTok's numeric user id, YouTube's `UC...` channel id, Bluesky's DID, GitHub's numeric id, Discord's server id, and the account's own handle where the network publishes no id (Telegram). Two different handles that lead to the same account are returned once and charged once, matched on that id. Monitoring is remembered per `network` + `accountId`. On TikTok, YouTube, Bluesky, Snapchat, GitHub and Discord that id is a number or a DID the network assigns, so renaming an account does not restart its history. **On Telegram and Twitch the account id is the handle itself** - neither network publishes a stable numeric id on the page this Actor is allowed to read - so if one of those accounts is renamed it is treated as a new account and comes back once as `first-check`.

`handleMatchesInput` is the mis-attribution check. On YouTube it is `true` only when the About panel names the same channel id as the page's own canonical link - a page carries several other channels' subscriber counts in its recommendation rail, and reading the first one found returns a different channel's number. If they disagree the row is not returned at all.

Columns that a network does not publish are `null`, never `0`.

### Free rows (never charged)

| `status` | What it means |
|---|---|
| `no-such-account` | the network returned no public account for that handle. A handle that never existed, one that was renamed and one that was removed all give the same answer, so the row does not claim which |
| `no-public-count` | the account exists but the network publishes no count for it. A count of zero is not assumed |
| `blocked` | a block, a challenge page or an empty response. Not retried from another address, and the account is not reported as gone |
| `rate-limited` | the network asked this run to slow down. Not worked around |
| `unreadable` | the response could not be read, or was a redirect this Actor does not follow. Nothing is guessed |
| `invalid-input` | not a handle or profile URL this Actor can use, so nothing was requested |
| `duplicate-account` | a second entry pointing at an account already returned in this run |
| `no-change` | monitoring mode, and nothing in the list moved |
| `not-checked` | `maxAccounts` or the 1,000-per-run cap stopped before the end of the list |
| `budget-reached` | the run's maximum total charge stopped it early, with the count of what was left |

### Pricing

- `profile-returned` - **$5.00 per 1,000 rows**, charged only for rows with `status: "ok"`. Every free row above costs nothing.
- `profile-checked` - **$0.30 per 1,000 checks**, charged in monitoring mode for each account actually read, changed or not. There is no start fee.

Outside monitoring mode only `profile-returned` applies, so 200 accounts in one run is $1.00.

In monitoring mode, **every account checked costs the check fee, changed or not** - that is what pays for the polling - and only the accounts that moved also cost a row. 50 accounts every hour = 36,000 checks a month = **$10.80**, plus $5.00 per 1,000 change rows. On the same schedule an Actor that charges a full row every time would bill 36,000 rows = $180.00.

The Actor reads only as many accounts as the run's maximum total charge can pay for **with a check and a row each**, so a low limit never spends the whole budget on check fees and returns nothing.

### Monitoring mode

Turn `monitoringMode` on and run on a schedule. The first run returns every account once to set the baseline (`change: "first-check"`). After that an account comes back only when its watched count changed, with `previousFollowerCount`, `previousCheckedAt` and `followerCountChange` filled in and `change` set to `followers-up` or `followers-down`.

`monitorOn` decides what counts as a change. `follower-count` (the default) watches the follower count only. `any-count` also returns an account when its following count or post count changed, which returns far more rows.

Two honest limits:

- **On the three networks that publish a rounded count, a small move is invisible.** A YouTube channel at 21.3M has to gain about 50,000 subscribers before the published number changes. TikTok, Twitch, Telegram, Bluesky and GitHub do not have this problem. This is a property of what those networks publish, not of this Actor.
- **Counts are remembered per account, not per list.** Do not put the same account in two schedules that can run at the same time; Apify's key-value store has no atomic update, so two runs finishing within milliseconds of each other can overwrite one another's records. The Actor re-reads and merges before writing, and warns in the log if it could not confirm its own records afterwards, but it cannot make this impossible.

`resetMonitoringState` clears every remembered count. **Turn it off again after that one run** - while it is on, every run starts from scratch and charges a full row for every account instead of only the ones that changed.

### Limits

- 1,000 accounts per run. Beyond that a free `not-checked` row says how many were left.
- Requests to the same network are spaced out; requests to different networks are not, because they are different servers.
- **GitHub allows 60 unauthenticated requests per hour from one address.** This Actor does not work around that: when GitHub says the allowance is used up, the remaining GitHub accounts come back as free `rate-limited` rows naming the time it resets, and the other seven networks carry on normally.
- If a network rate-limits this run, no further accounts on that network are requested in that run.

# Actor input Schema

## `accounts` (type: `array`):

One list for all eight networks. Paste a full profile URL (https://www.tiktok.com/@nasa, https://www.youtube.com/@mkbhd, https://www.twitch.tv/shroud, https://t.me/durov, https://bsky.app/profile/bsky.app, https://www.snapchat.com/@fcbarcelona, https://github.com/torvalds, https://discord.gg/python), or write network:handle (tiktok:@nasa, youtube:@mkbhd, twitch:shroud, telegram:durov, bluesky:bsky.app, snapchat:fcbarcelona, github:torvalds, discord:python). A bare handle with no network is rejected with a free row, because the same name exists on several networks and guessing would return an account you did not ask for. Use the per-network lists below if you prefer bare handles. If every list is empty and monitoring is off, a few example accounts are read and every row says so in inputAccount; if monitoring is on, nothing is read and nothing is charged.

## `tiktokAccounts` (type: `array`):

TikTok accounts as @nasa, nasa, or https://www.tiktok.com/@nasa. The follower count comes back exact, not rounded: TikTok publishes both an exact figure and a rounded one on the same page, and the exact one is used (on 14 accounts measured on 2026-09-06 the two differed on 11, by up to 41,519 followers). Tag, music, search and embed URLs are rejected with a free row, because robots.txt does not allow them.

## `youtubeChannels` (type: `array`):

YouTube channels as @MrBeast, a channel ID (UCX6OQ3DkcsbYNE6H8uQQuVA), or a channel URL. **YouTube only publishes a rounded subscriber count** ("21.3M subscribers"; exact only below 1,000), so isRounded is true on these rows and monitoring sees a change only when the rounded number itself moves. Old /user/ and /c/ URLs are rejected with a free row because resolving them needs a redirect this Actor does not follow.

## `twitchChannels` (type: `array`):

Twitch channels as shroud, @shroud, or https://www.twitch.tv/shroud. The follower count comes back exact, read from the channel page's own structured data (5 of 5 channels measured on 2026-09-23 carried it, including channels that were not live). Reserved paths that are not channels (stream, search, login, videos, directory ...) are rejected with a free row, because robots.txt does not allow them.

## `telegramChannels` (type: `array`):

Public Telegram channels as durov, @durov, or https://t.me/durov. The subscriber count comes back exact: the profile page prints the full digits (10 671 668 subscribers), while the /s/ preview page rounds to three significant figures, so only the profile page is requested. Private invite links (t.me/+... and t.me/joinchat/...) are rejected with a free row - they publish no count.

## `blueskyAccounts` (type: `array`):

Bluesky accounts as bsky.app, @bsky.app, a DID (did:plc:...), or https://bsky.app/profile/bsky.app. The follower count comes back exact. Read through Bluesky's public API, whose robots.txt says in full sentences that crawling the public parts is allowed.

## `snapchatAccounts` (type: `array`):

Snapchat public profiles as fcbarcelona, @fcbarcelona, or https://www.snapchat.com/@fcbarcelona. **Snapchat rounds the subscriber count to the nearest hundred** (all 17 accounts with a count in a 28-account sample on 2026-09-14 were multiples of 100), so isRounded is true on these rows. Accounts that show no count - including personal accounts - come back as a free row saying so; a count of zero is never assumed.

## `githubAccounts` (type: `array`):

GitHub accounts as torvalds, @torvalds, or https://github.com/torvalds. The follower count comes back exact, from GitHub's official public REST API. **GitHub allows 60 unauthenticated requests per hour from one address**; this Actor does not work around that - when it is reached, the remaining GitHub accounts come back as free rows that name the time the allowance resets. Repository URLs (github.com/owner/repo) are rejected with a free row.

## `discordInvites` (type: `array`):

Discord servers named by an invite: python, discord.gg/python, or https://discord.com/invite/python. Invite codes are case sensitive and are sent exactly as typed. **Discord itself calls this number approximate** (approximate\_member\_count), so isRounded is true on these rows, and the answer is cached for up to five minutes. Server URLs such as discord.com/channels/... are not invites and are rejected with a free row.

## `maxAccounts` (type: `integer`):

How many charged rows to return when monitoring is off: reading stops once this many accounts have been read, and a free row says how many entries were not checked. **It does not limit spending in monitoring mode** - there, every account you list is checked and every change among them comes back, and the run's maximum total charge is what caps the cost. Cutting changes here would mean the accounts at the end of your list never came back at all.

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

Off = every account you listed comes back with its counts right now, charged per row. On = the Actor remembers each account and, on later runs, returns it only when the watched count changed, with the previous value and the difference in the row. The first run returns every account once to set the baseline. **In monitoring mode every account checked costs $0.30 per 1,000 checks, changed or not** (handles the network returns nothing for, blocks and rate limits 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 account, so do not put the same account in two schedules that can run at the same time.

## `monitorOn` (type: `string`):

Which numbers make an account come back in monitoring mode. Follower count only is the default. Any count also returns an account when its following count or its post count changed - useful for spotting activity, but it returns far more rows.

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

Clears every remembered count for this Actor, so the next monitoring run returns each account once again. The counts are stored per account, not per list, so this affects all your monitoring runs. **Turn it off again after that one run**: while it is on, every run starts from scratch and charges a full account row for every account instead of only the ones that changed.

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

Requests go out directly. This option only covers the case where a request does not reach the network at all (a connection failure): it then retries through an Apify proxy. **Blocks and challenge pages are never retried from another address**, and rate limits are never worked around - the Actor waits the time the network asks for, up to 30 seconds, and otherwise returns a free row. With this off, a connection failure is reported as a free row and no proxy is paid for.

## Actor input object example

```json
{
  "accounts": [
    "tiktok:@nasa",
    "youtube:@mkbhd",
    "twitch:shroud",
    "telegram:durov",
    "bluesky:bsky.app",
    "snapchat:fcbarcelona",
    "github:torvalds",
    "discord:python"
  ],
  "tiktokAccounts": [
    "@nasa",
    "@duolingo"
  ],
  "youtubeChannels": [
    "@MrBeast",
    "@NASA"
  ],
  "twitchChannels": [
    "shroud",
    "ninja"
  ],
  "telegramChannels": [
    "durov",
    "telegram"
  ],
  "blueskyAccounts": [
    "bsky.app",
    "atproto.com"
  ],
  "snapchatAccounts": [
    "fcbarcelona",
    "nasa"
  ],
  "githubAccounts": [
    "torvalds",
    "apify"
  ],
  "discordInvites": [
    "python",
    "discord-developers"
  ],
  "maxAccounts": 100,
  "monitoringMode": false,
  "monitorOn": "follower-count",
  "resetMonitoringState": false,
  "useProxy": true
}
```

# Actor output Schema

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

One row per account, with the same columns on all eight networks: the network, the entry you asked for, the account id the network itself reported, the handle, the profile URL, the display name and description, the follower count, what that network calls it (followers, subscribers or members), the text the network displays, whether the number is rounded and to what precision, the following count, the post count, likes, total views, online members, account type, country, whether the account is verified or private, and the date it was created; in monitoring mode also what changed since the last run (followers up, followers down, following changed or post count changed), the previous count, when it was last checked and the difference. Handles the network returns nothing for, accounts that publish no count, blocks, rate limits, entries that point at an account another entry already returned, and anything cut short by the run's charge limit come back as their own free rows. In monitoring mode unchanged accounts are not returned.

# 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 = {
    "accounts": [
        "tiktok:@nasa",
        "youtube:@mkbhd",
        "twitch:shroud",
        "telegram:durov",
        "bluesky:bsky.app",
        "snapchat:fcbarcelona",
        "github:torvalds",
        "discord:python"
    ],
    "tiktokAccounts": [
        "@nasa",
        "@duolingo"
    ],
    "youtubeChannels": [
        "@MrBeast",
        "@NASA"
    ],
    "twitchChannels": [
        "shroud",
        "ninja"
    ],
    "telegramChannels": [
        "durov",
        "telegram"
    ],
    "blueskyAccounts": [
        "bsky.app",
        "atproto.com"
    ],
    "snapchatAccounts": [
        "fcbarcelona",
        "nasa"
    ],
    "githubAccounts": [
        "torvalds",
        "apify"
    ],
    "discordInvites": [
        "python",
        "discord-developers"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/social-media-follower-count-tracker").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 = {
    "accounts": [
        "tiktok:@nasa",
        "youtube:@mkbhd",
        "twitch:shroud",
        "telegram:durov",
        "bluesky:bsky.app",
        "snapchat:fcbarcelona",
        "github:torvalds",
        "discord:python",
    ],
    "tiktokAccounts": [
        "@nasa",
        "@duolingo",
    ],
    "youtubeChannels": [
        "@MrBeast",
        "@NASA",
    ],
    "twitchChannels": [
        "shroud",
        "ninja",
    ],
    "telegramChannels": [
        "durov",
        "telegram",
    ],
    "blueskyAccounts": [
        "bsky.app",
        "atproto.com",
    ],
    "snapchatAccounts": [
        "fcbarcelona",
        "nasa",
    ],
    "githubAccounts": [
        "torvalds",
        "apify",
    ],
    "discordInvites": [
        "python",
        "discord-developers",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/social-media-follower-count-tracker").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 '{
  "accounts": [
    "tiktok:@nasa",
    "youtube:@mkbhd",
    "twitch:shroud",
    "telegram:durov",
    "bluesky:bsky.app",
    "snapchat:fcbarcelona",
    "github:torvalds",
    "discord:python"
  ],
  "tiktokAccounts": [
    "@nasa",
    "@duolingo"
  ],
  "youtubeChannels": [
    "@MrBeast",
    "@NASA"
  ],
  "twitchChannels": [
    "shroud",
    "ninja"
  ],
  "telegramChannels": [
    "durov",
    "telegram"
  ],
  "blueskyAccounts": [
    "bsky.app",
    "atproto.com"
  ],
  "snapchatAccounts": [
    "fcbarcelona",
    "nasa"
  ],
  "githubAccounts": [
    "torvalds",
    "apify"
  ],
  "discordInvites": [
    "python",
    "discord-developers"
  ]
}' |
apify call neverempty/social-media-follower-count-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/social-media-follower-count-tracker"
        }
    }
}
```

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/sOloF9m1sIov3Qzkx/builds/2bC2Pw5zHJ6yVakdS/openapi.json
