Social Media Follower Count Tracker - 8 Networks, Change Alerts
Pricing
from $3.65 / 1,000 account row returneds
Social Media Follower Count Tracker - 8 Networks, Change Alerts
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.
Pricing
from $3.65 / 1,000 account row returneds
Rating
0.0
(0)
Developer
NeverEmpty
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
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.
roundingPrecisionsays 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
subscriberCountof"0"on Snapchat means "not shown", not "zero subscribers", so those accounts come back as a freeno-public-countrow instead of a zero. - Discord names the field
approximate_member_countitself, and the answer carriesCache-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
429on 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 returned200but 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.tvhas arobots.txttwo lines long that readsUser-agent: */Disallow: /, so this Actor never touches it, and the official Helix API needs OAuth. The channel pagewww.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, anAccept,Accept-Encoding: identityandAccept-Language.
Input
accounts takes one mixed list for all eight networks. Paste a profile URL, or write network:handle:
{"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 idUCX6OQ3DkcsbYNE6H8uQQuVA, 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 -
torvaldsorhttps://github.com/torvalds. Repository URLs are rejected. Organizations work and come back withaccountType: "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:
{"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 withstatus: "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-checkedrow 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-limitedrows 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.