Discord Server Stats Scraper avatar

Discord Server Stats Scraper

Pricing

from $1.67 / 1,000 results

Go to Apify Store
Discord Server Stats Scraper

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

Farhan Febrian Nauval

Maintained by Community

Actor 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

FieldTypeDefaultDescription
invitesarrayrequiredhttps://discord.gg/python, discord.gg/python or bare python — all three parse
fetchWidgetbooleantrueAlso call the widget endpoint for the channel list and live presence
includeOnlineMembersbooleanfalseAdd usernames of up to 100 online members (widget servers only)
maxItemsintegerallStop 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:

_errorMeaning
invalid_inputNot a Discord invite code or a discord.gg / discord.com invite URL
invite_not_foundDiscord returned 404 — the invite is invalid, expired, or was revoked
blockedEvery TLS profile was refused; _errorDetail carries the last status
unexpected_shape200 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:

  1. GET /api/v10/invites/{code}?with_counts=true&with_expiration=true — the guild record.
  2. 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.