REST API v2

API documentation built for one clean request.

Base URLhttps://api.cord.cat

Introduction

The CordCat API lets you programmatically query Discord user profiles, breach data, EU DSA sanctions, and FiveM records. The API is JSON-only and requires an API key for external access.

Note

The site itself uses the API internally without a key (IP rate-limited). External applications must include an API key header.

Authentication

Pass your API key in one of two ways.

# Header (recommended)
X-API-Key: cc_your_api_key_here

# Or via Authorization
Authorization: Bearer cc_your_api_key_here

Get your API key by creating an account and visiting the Dashboard.

Rate limits

No key (site)

10 req/min

Free plan

60 req/hour

Unlimited plan

No limit

Rate limit headers are included in every response: X-RateLimit-Remaining, X-RateLimit-Reset.

Plans & access

Every plan is account-level — all of your API keys follow your plan. Anonymous callers can still use the site (Turnstile + daily quota). Contributor (our partner tier) is earned, not bought: contribute data, tokens, code or research to get it.

CapabilityAnonymous$0Free$0Premium$2.5/moContributorEarned
Full lookup /api/v2/query/:id25/day + captcha1000/dayNo captchaNo captcha
API rate limit✕1 req/s2 req/sUnlimited
Search by username / display name /api/v2/lookup/:name✕1/day✓ Unlimited✓ Unlimited
User's server list /api/v2/guilds/:idCount only1 reveal/day✓✓
Guild member list /api/v2/lookup/guild/:idProfile onlyProfile onlyProfile onlyFull list
Server deep stats & history /api/v2/server/:id✕✕Full historyFull history
Batch lookup (100 IDs) /api/user/batch✕5 runs/10 min5 runs/10 min5 runs/10 min
Tools API /api/tools/* (no captcha)Captcha required✓✓✓
Captcha bypass on the site✕✕✓✓
Saved batch maps (25 max)✕✓✓✓
Profile badges✕CordCat UserPremiumContributor + Premium
Early access to exclusive endpoints✕✕✕✓

Endpoints

GET/api/v2/query/:discord_idAPI key

Full lookup: Discord profile, dataset exposure (with GeoIP/ASN), FiveM records, EU DSA sanctions, and a transparent risk/bot score.

Path parameters

ParameterTypeDescription
discord_idstring17 to 20 digit Discord snowflake ID. Required.

Query parameters

ParameterTypeDescription
refreshbooleanOptional. Set to 1 to bypass the result cache, re-fetch, and return meta.changes (the diff since the last snapshot).

Caching & extras

Results are cached for ~10 minutes. Each response also carries a score (risk + bot likelihood) and a meta block with the cache state and any changes since the previous lookup.

Response

responseobject{6}
userInfoobject{6} →
statementsarray[0]
breachobject{3} →
fivemobject{2} →
scoreobject{4} →
metaobject{4} →
userInfoobject{6}
id"123456789012345678"
username"example"
global_name"Example User"
avatar"a_8f4c..."
public_flags64
bannernull
breachobject{3}
successtrue
resultsCount2
dataobject{2} →
dataobject{2}
resultsarray[1] →
ipGeoobject{1} →
resultsarray[1]
0object{3} →
0object{3}
source"Emoji.gg"
categoriesarray[2] →
fieldsobject{2} →
categoriesarray[2]
0"email"
1"ip"
fieldsobject{2}
ip"203.0.113.5"
ipGeoobject{1}
203.0.113.5object{3} →
203.0.113.5object{3}
asn"AS7545"
organization"TPG Telecom"
country"AU"
fivemobject{2}
successtrue
dataobject{3} →
dataobject{3}
took12
total3
resultsarray[0]
scoreobject{4}
risk23
level"low"
signalsarray[1] →
botobject{4} →
signalsarray[1]
0object{4} →
0object{4}
key"breach"
label"Exposed in 2 datasets"
points6
kind"risk"
botobject{4}
score10
level"unlikely"
isBotfalse
reasonsarray[0]
metaobject{4}
cachedfalse
fetchedAt"2026-06-05T00:00:00.000Z"
lastCheckednull
changesarray[0]
POST/api/user/batchAccount session

Resolve up to 100 Discord IDs in one call. Requires a logged-in account session (cookie + CSRF), not an API key. Throttled to ~10 IDs/sec, capped at 5 runs per 10 minutes.

Body (JSON)

FieldTypeDescription
idsstring[]Up to 100 Discord IDs. A newline- or comma-separated string is also accepted.

Response

responseobject{3}
count2
invalidarray[0]
resultsarray[2] →
resultsarray[2]
0object{9} →
1object{3} →
0object{9}
oktrue
id"123456789012345678"
username"example"
risk23
riskLevel"low"
botLevel"unlikely"
breachCount2
fivemTotal3
sanctions0
1object{3}
okfalse
id"999999999999999999"
error"not_found"

Saved batch maps

Account session

Persist a batch result set to your account and reload it later (max 25 per account).

GET/api/user/batch-maps

List all saved maps for the authenticated user. Returns map metadata (IDs omitted for brevity).

Response

{
  "maps": [
    {
      "id": 1,
      "name": "My investigation",
      "count": 42,
      "created_at": "2026-06-01T12:00:00.000Z",
      "updated_at": "2026-06-01T12:00:00.000Z"
    }
  ]
}
POST/api/user/batch-maps

Save a batch result set under a name. Body must be JSON.

Body (JSON)

FieldTypeDescription
namestringDisplay name for the map (max 80 chars). Required.
idsstring[]Array of Discord snowflake IDs (max 100). Required.
resultsBatchSummary[] | nullOptional cached result summaries from the batch endpoint.

Response 201 Created

{ "id": 7 }
GET/api/user/batch-maps/:id

Fetch a single saved map including the full ID list and cached results.

Response

{
  "id": 7,
  "name": "My investigation",
  "ids": ["123456789012345678", "..."],
  "results": [ { "ok": true, "id": "123456789012345678", "username": "example", "risk": 23, "riskLevel": "low", "botLevel": "unlikely", "breachCount": 1, "fivemTotal": 0, "sanctions": 0 } ],
  "created_at": "2026-06-01T12:00:00.000Z",
  "updated_at": "2026-06-01T12:00:00.000Z"
}
DELETE/api/user/batch-maps/:id

Permanently delete a saved map. Only the owner can delete their own maps.

Response

{ "ok": true }

Member index (premium)

API key or session

Endpoints powered by the CordCat member index. Premium, contributor, and admin accounts get unlimited access. Free accounts get 1 search per day, shared across all three endpoints — the quota is only consumed when a result is returned.

GET/api/v2/lookup/:name

Search indexed members by username or display name. Minimum 2 characters, max 64. Paginated for premium callers (limit 1-50, offset; total holds the full match count). Free accounts always get the full first page (up to 50).

ParameterTypeDescription
namestringUsername or display name fragment. Required.
limitnumberOptional (query). Results per page, 1-50, default 20. Premium only.
offsetnumberOptional (query). Page offset. Premium only.

Response

{
  "query": "dyno",
  "count": 1,
  "total": 1,
  "results": [
    {
      "discord_id": "155149108183695360",
      "username": "Dyno",
      "global_name": null,
      "avatar": "a_8f4c...",
      "first_seen_at": "2025-11-02T10:12:00.000Z",
      "last_seen_at": "2026-09-06T13:02:09.000Z",
      "guild_count": 14
    }
  ],
  "quota": { "used": 1, "limit": 1, "remaining": 0 }
}

quota is null for unlimited (premium) callers.

GET/api/v2/lookup/guild/:id

Guild profile is public to any signed-in caller; the member list is contributor/admin-only — other plans (premium included) get locked: true and no member rows. Ordered by last seen, paginated with limit/offset (max 100).

ParameterTypeDescription
idstring17-20 digit guild snowflake. Required.
limitnumberOptional (query). Members per page, 1-100, default 100. Contributor/admin only.
offsetnumberOptional (query). Page offset for the member list. Contributor/admin only.

Response locked (default for free/no auth)

{
  "locked": true,
  "guild": { "id": "1224243448685658213", "name": "Zeke Hub", "icon": "97e3a539..." },
  "indexed_members": 10282,
  "total_members": 10282
}

Response unlocked (premium, or reveal=1)

{
  "locked": false,
  "guild": {
    "id": "1224243448685658213",
    "name": "Zeke Hub",
    "icon": "97e3a539...",
    "member_count": 68014,
    "presence_count": 6990
  },
  "indexed_members": 10282,
  "members": [
    {
      "discord_id": "310824728715591681",
      "username": "kitemogiya",
      "global_name": "7ashapp",
      "avatar": null,
      "first_seen_at": "2026-01-12T09:00:00.000Z",
      "last_seen_at": "2026-09-06T12:44:00.000Z",
      "guild_count": 3
    }
  ],
  "page": { "limit": 100, "offset": 0 }
}
GET/api/v2/server/:idPremium

Deep server profile, periodically scraped from our index: boosts (with tier progress and next-tier threshold), live invite resolved from the vanity tag, owner, emojis, stickers, channels with permissions, roles (color, position, permissions bitfield, hoist/mentionable/managed flags), features, plus a tracked change history — every modification we observed since we started monitoring the server. Premium, Contributor and admin only; works with a session cookie or a Premium API key. Returns 404 if the server has not been scraped yet — try again later.

ParameterTypeDescription
idstring17-20 digit guild snowflake. Required.
historynumberOptional (query). Max change-log entries to return, 0-500, default 100. Use 0 for the current snapshot only.

Response premium/contributor/admin

{
  "guild_id": "1224243448685658213",
  "name": "Zeke Hub",
  "tag": "zekehub",
  "invite": {
    "code": "zekehub",
    "channel": { "id": "9013", "name": "welcome", "type": 0 },
    "inviter": { "id": "310824728715591681", "username": "kitemogiya" },
    "approximate_member_count": 68014,
    "approximate_presence_count": 6990,
    "expires_at": null
  },
  "description": "The official Zeke Hub community server",
  "created_at": "2024-03-30T18:22:17.000Z",
  "rank": 37,
  "boosts": { "count": 14, "tier": 1, "progress_bar": true, "next_tier_at": 14 },
  "verification_level": 2,
  "owner": { "id": "310824728715591681", "username": "kitemogiya", "global_name": "7ashapp", "avatar_url": "https://cdn.discordapp.com/avatars/…" },
  "images": { "icon_url": "https://cdn.discordapp.com/icons/…", "banner_url": null, "splash_url": null },
  "emojis": { "count": 42, "items": [{ "id": "1234", "name": "zeke", "animated": false, "url": "https://cdn.discordapp.com/emojis/1234.png" }] },
  "stickers": { "count": 3, "items": [{ "id": "5678", "name": "wave", "format_type": 1, "url": "https://cdn.discordapp.com/stickers/5678.png" }] },
  "channels": {
    "count": 28,
    "categories": [{ "id": "9012", "name": "general", "permission_overwrites": [], "channels": [{ "id": "9013", "name": "chat", "type": 0, "position": 0, "parent_id": "9012", "permission_overwrites": [{ "id": "910", "type": 0, "allow": "2048", "deny": "0" }] }] }],
    "uncategorized": []
  },
  "features": ["GUILD_ONBOARDING_EVER_ENABLED", "INVITE_SPLASH", "COMMUNITY"],
  "roles": [
    {
      "id": "910", "name": "Moderator", "color": 3447003, "position": 12,
      "permissions": "1099511627799", "managed": false, "mentionable": false,
      "hoist": true, "member_count": null
    }
  ],
  "members": { "total": 68014, "online": 6990 },
  "monitoring": { "first_seen": "2025-11-02 10:12:00", "last_seen": "2026-09-06 13:02:09", "monitored_seconds": 25085409, "scrape_count": 132 },
  "history": [
    { "field": "name", "old_value": "Zeke Community", "new_value": "Zeke Hub", "changed_at": "2026-08-14 09:15:22" },
    { "field": "emoji_added:1234", "old_value": null, "new_value": "{\"id\":\"1234\",\"name\":\"zeke\"}", "changed_at": "2026-08-20 11:02:41" },
    { "field": "channel_updated:9013", "old_value": "{…}", "new_value": "{…}", "changed_at": "2026-09-01 20:44:03" }
  ]
}

invite is resolved live from the vanity tag (null when the server has none or the invite is dead). roles[].member_count is Discord’s online-member estimate per role (null when 0/absent). next_tier_at is the boost count needed for the next tier (null at tier 3). A 403 with action: "upgrade" means the account plan is free — the endpoint is a straight Premium entitlement with no daily-credit option.

GET/api/v2/guilds/:id

The servers an indexed user belongs to, ordered by member count. Without entitlement, returns a locked teaser with the real count only — guild names are never sent. Free accounts can pass reveal=1 to spend their daily search and unlock the list.

ParameterTypeDescription
idstring17-20 digit guild snowflake. Required.
revealbooleanOptional (query). Set to 1 to spend the daily free search and unlock the list. Ignored for premium callers (always unlocked).

Response locked (default for free/no auth)

{
  "locked": true,
  "total": 14,
  "quota": { "used": 0, "limit": 1, "remaining": 1 }
}

Response unlocked (premium, or reveal=1)

{
  "locked": false,
  "total": 14,
  "guilds": [
    {
      "id": "1224243448685658213",
      "name": "Zeke Hub",
      "icon": "97e3a539...",
      "member_count": 68014,
      "last_seen_at": "2026-09-06T13:02:09.000Z"
    }
  ],
  "quota": null
}

If the member index is temporarily unreachable, the endpoint returns { "unavailable": true, "locked": true, "total": 0 } instead of failing.

Access errors

CodeFieldDescription
401action: "register"Anonymous caller tried a search or reveal. Create an account.
429action: "upgrade"Daily free search already used. Upgrade to Premium for unlimited access.
GET/api/status

Returns the current health status of all services.

Tools API

Free to use on the website with a captcha. Direct API access (bypassing the captcha) requires an API key. Base URL: https://api.cord.cat

GET/api/tools/user/:id

Fetch basic Discord user info (avatar, banner) by snowflake ID. Lighter than /v2/query — no breach or FiveM data.

FieldTypeDescription
idstringDiscord snowflake ID (17-20 digits)
usernamestringDiscord username
global_namestring | nullDisplay name
avatarstring | nullAvatar hash. Prefix a_ = animated GIF available.
bannerstring | nullBanner hash
accent_colornumber | nullProfile accent color as integer

Avatar CDN URL

https://cdn.discordapp.com/avatars/{id}/{hash}.png?size=1024
GET/api/tools/invite/:code

Validate a Discord invite and return full guild and channel metadata.

{
  "code": "intelxfr",
  "guild": { "id": "...", "name": "IntelX", "icon": "...", "features": [...] },
  "channel": { "id": "...", "name": "events", "type": 0 },
  "inviter": { "id": "...", "username": "user" },
  "approximate_member_count": 1430,
  "approximate_presence_count": 248,
  "expires_at": null
}
GET/api/tools/guild-widget/:id

Proxies Discord's public widget JSON for a server. The server must have its widget enabled (Server Settings → Widget). Returns 403 if widget is disabled.

{
  "id": "...",
  "name": "Server Name",
  "instant_invite": "https://discord.gg/...",
  "presence_count": 248,
  "channels": [ { "id": "...", "name": "General", "position": 0 } ],
  "members": [
    {
      "id": "...",
      "username": "Wojak",
      "status": "online",
      "avatar_url": "https://cdn.discordapp.com/widget-avatars/...",
      "activity": { "name": "League of Legends" }
    }
  ]
}

Browser-side tools

These tools run entirely in your browser — no API call required. They are accessible at cord.cat/tools.

Snowflake Decoder — /tools/snowflake

Decodes any Discord (or Twitter) snowflake ID client-side. Returns creation timestamp (UTC), internal worker ID, process ID, and increment. No network request.

Time Converter — /tools/time

Converts any date or Unix timestamp to every Discord timestamp markdown format (<t:unix:R>, <t:unix:F>, etc.) and displays the equivalent in every major timezone.

Webhook Sender — /tools/webhook

GUI for building and sending Discord messages directly to a webhook URL. Supports plain content, embeds (title, description, fields, footer, author, color), username override, and avatar override. Calls the Discord webhook URL directly from the browser — no server-side proxy.

Embed Builder → Code — /tools/embed-builder

Visual Discord embed designer with a live preview. Export the embed as discord.js, discord.py, or raw JSON payload. Runs fully client-side.

Gateway Intent Calculator — /tools/intents

Select Discord gateway intents from a checklist and compute the combined bitfield integer. Also decodes an existing integer back to its constituent intents. Use the value directly in your bot's intents config.

Response schema

Every field returned by the query endpoint, with its type.

FieldTypeDescription
userInfoobject | nullDiscord profile, or null if the user was not found.
userInfo.usernamestringDiscord username.
userInfo.global_namestring | nullDisplay name, if set.
userInfo.public_flagsintegerBadge bitmask, decode for public flags.
breach.resultsCountintegerNumber of dataset matches.
breach.data.resultsarrayDataset records, each with its source and raw fields.
breach.data.ipGeoobjectGeoIP/ASN enrichment keyed by IP: { asn, organization, country }.
fivem.data.totalintegerTotal FiveM records found.
statementsarrayEU DSA statements, empty if none.
score.riskintegerRisk score 0-100, summed from explainable signals.
score.levelstringlow | elevated | high.
score.signalsarrayEach contributing signal: { key, label, detail, points }.
score.bot.levelstringBot likelihood: unlikely | possible | likely | definite.
meta.cachedbooleanWhether this response was served from cache.
meta.changesarrayFields that changed since the previous snapshot (with ?refresh=1).

Errors

CodeMeaning
400Invalid Discord ID format
401Missing or invalid API key
404Discord user not found
429Rate limit exceeded
500Internal server error
502Upstream Discord API error

Examples

The same request, in your language of choice.

curl -H "X-API-Key: cc_your_key" \
  https://api.cord.cat/api/v2/query/123456789012345678