Discord Server Stats Scraper
Pricing
from $1.67 / 1,000 results
Discord Server Stats Scraper
Get public Discord server metadata from invite links: member and online counts, description, boost tier, features, verification level, icon and banner URLs, and the channel list.
Pricing
from $1.67 / 1,000 results
Rating
0.0
(0)
Developer
Farhan Febrian Nauval
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Discord Server Stats — Member Counts, Boosts & Channels from Invite Links
Turn a list of Discord invite links into structured server data: member and online counts, description, boost tier, feature flags, verification level, icon/banner URLs and — when the owner has the widget enabled — the channel list and live presence count. HTTP-only, no bot token, no account, no browser.
What this actor does not do
It does not read messages. Discord message history requires a logged-in session and a WebSocket gateway connection; there is no anonymous HTTP surface for it. This actor covers server metadata only. If you need messages, you need a bot token and the Gateway API — a different tool.
Input
| Field | Type | Default | Description |
|---|---|---|---|
invites | array | required | https://discord.gg/python, discord.gg/python or bare python — all three parse |
fetchWidget | boolean | true | Also call the widget endpoint for the channel list and live presence |
includeOnlineMembers | boolean | false | Add usernames of up to 100 online members (widget servers only) |
maxItems | integer | all | Stop after this many invites |
Output
{"_input": "https://discord.gg/python","_source": "S1-invite-api","_scrapedAt": "2026-09-09T09:12:04Z","inviteCode": "python","inviteUrl": "https://discord.gg/python","guildId": "267624335836053506","name": "Python","description": "We're a large community focused around the Python programming language…","memberCount": 430790,"onlineCount": 29564,"boostCount": 30, "boostTier": 3,"verificationLevel": 2,"vanityUrlCode": "python","features": ["ANIMATED_BANNER", "COMMUNITY", "DISCOVERABLE", …], // 49 flags"nsfw": false, "nsfwLevel": 0,"iconUrl": "https://cdn.discordapp.com/icons/267624335836053506/a_421bf….gif","bannerUrl": "…", "splashUrl": "…","inviteChannelId": "…", "inviteChannelName": "python-discussion","inviteExpiresAt": null, // null = permanent invite"widgetEnabled": true, // ← gates the four fields below; null = fetchWidget was off"channelCount": 6,"channels": [{ "id": "…", "name": "Code/Help", "position": 1 }, …],"widgetPresenceCount": 29648,"instantInvite": "https://discord.com/invite/x298zHMz"}
Three things worth knowing
widgetEnabled tells you which rows are complete. The channel list comes from a second
endpoint that server owners can switch off, and most do — in testing 1 of 4 large servers had it
on. A disabled widget answers 403, which this actor treats as a configuration fact, not a block:
you get the row with widgetEnabled: false and the four widget fields absent, never a silent
failure. Filter on that flag rather than assuming a missing channels means something went wrong.
Icons are hashes upstream, URLs here. Discord returns a_421bfdb0…; the leading a_ means
animated, which changes the extension from .png to .gif. Building the CDN URL with the wrong
extension yields a 404 image, so that is resolved for you in iconUrl/bannerUrl/splashUrl.
Online member usernames are opt-in. includeOnlineMembers is false by default. Those are
real people's usernames and presence status; the counts (onlineCount, widgetPresenceCount)
answer most questions without publishing them, so turn it on only if you actually need the list.
Errors
Every input produces exactly one row — a failure never disappears from the dataset, so a join
against your input list stays aligned. Failures carry _error:
_error | Meaning |
|---|---|
invalid_input | Not a Discord invite code or a discord.gg / discord.com invite URL |
invite_not_found | Discord returned 404 — the invite is invalid, expired, or was revoked |
blocked | Every TLS profile was refused; _errorDetail carries the last status |
unexpected_shape | 200 JSON, but no guild object — the API contract changed |
If every input fails, the run itself fails rather than reporting success over an empty dataset.
How it works
Two documented public endpoints, curl_cffi with a Chrome TLS fingerprint and a
chrome131/safari180 fallback ladder:
GET /api/v10/invites/{code}?with_counts=true&with_expiration=true— the guild record.GET /api/v10/guilds/{guild_id}/widget.json— channels and presence, when enabled.
Rate limiting is honoured, not guessed: a 429 carries retry_after in seconds and the actor
sleeps exactly that long. Transport errors and unexpected statuses back off exponentially across
the profile ladder.