REST API reference, MCP server integration, and the technical writeup on how we reverse-engineered KolScan.
KolQuest provides a unified API for crypto wallet intelligence — KOL tracking, smart money analysis, and token data.
https://kol.quest/apiAll endpoints are relative to this base URL.
Content-Type: application/json
# Get trending tokens
curl "https://kol.quest/api/trending?chain=sol&limit=10"
# Search wallets
curl "https://kol.quest/api/wallets?search=cented&limit=5"
# Get wallet details
curl "https://kol.quest/api/wallets/CyaE1Vxv..."Full OpenAPI 3.0 spec available at /api/openapi.json — import into Postman, Insomnia, or generate client SDKs.
Most read endpoints are public. Write operations and user-specific features require authentication.
Wallet listings, trending tokens, search, and token data are publicly accessible without authentication.
Watchlist, submissions, vouching, and admin features require a valid session cookie from signing in.
KolQuest uses session cookies for authentication. Sign in via the web UI using Solana wallet, Ethereum (SIWE), or email/password.
# The session cookie is automatically sent by browsers
# For programmatic access, include credentials:
curl -X GET "https://kol.quest/api/watchlist" \
-b "session=your-session-cookie"API key authentication for external integrations and bots is on the roadmap. Keys will be managed from your profile dashboard.
Requests are rate-limited to ensure fair usage and service stability.
| Tier | Limit | Notes |
|---|---|---|
| Anonymous | 60 req/min | Per IP address |
| Authenticated | 120 req/min | Per user account |
| Search | 30 req/min | Search endpoints only |
Check response headers to monitor your rate limit status.
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1712678400If you exceed the rate limit, you'll receive a 429 response. Wait for the reset time before retrying.
Try the API live. Pick an endpoint, customize parameters, and send requests directly from your browser.
Complete endpoint reference. Click an endpoint to expand details, parameters, and code examples.
KOL and smart money wallet data from KolScan and GMGN.
Token data — trending, security analysis, smart money activity.
Real-time trade feed from tracked smart money wallets.
X/Twitter integration for KOL tracking.
Authenticated user features — requires session cookie.
Community wallet submissions and vouching.
Health and status endpoints.
Standard HTTP status codes with consistent error response format.
| Code | Name | Description |
|---|---|---|
| 400 | Bad Request | Invalid request parameters or malformed JSON |
| 401 | Unauthorized | Authentication required or invalid credentials |
| 403 | Forbidden | Insufficient permissions for this resource |
| 404 | Not Found | Resource not found |
| 429 | Too Many Requests | Rate limit exceeded — slow down |
| 500 | Internal Error | Server error — try again later |
| 502 | Bad Gateway | Upstream API error |
| 503 | Service Unavailable | Service temporarily unavailable |
{
"error": "RATE_LIMITED",
"message": "Too many requests. Please slow down.",
"retryAfter": 30
}Expose wallet intelligence via the Model Context Protocol for use in AI assistants (Claude, Copilot, Cursor, etc.). Communicates over JSON-RPC via stdio.
# Run the MCP server
bun mcp/index.ts
# Claude Desktop config (~/.config/claude/claude_desktop_config.json)
{
"mcpServers": {
"kolquest": {
"command": "bun",
"args": ["mcp/index.ts"],
"cwd": "/path/to/kol-quest"
}
}
}Each tool is callable by the AI assistant through the MCP protocol.
kolscan_leaderboardGet KolScan KOL leaderboard. Returns wallets ranked by profit, win rate, or other metrics.
| Param | Type | Description | Required |
|---|---|---|---|
| timeframe | number | 1 (daily), 7 (weekly), 30 (monthly) | — |
| sort | string | profit, wins, losses, winrate, name | — |
| order | string | asc or desc | — |
| limit | number | Max results (1-100) | — |
| search | string | Search by name or wallet address | — |
kolscan_walletGet detailed KolScan data for a specific wallet — stats, rankings, and PnL across all timeframes.
| Param | Type | Description | Required |
|---|---|---|---|
| address | string | Wallet address to look up | ✓ |
gmgn_walletsGet GMGN smart money wallets. Supports Solana and BSC with category filtering.
| Param | Type | Description | Required |
|---|---|---|---|
| chain | string | sol or bsc | — |
| category | string | smart_degen, kol, snipe_bot, launchpad_smart, fresh_wallet, etc. | — |
| sort | string | Sort field | — |
| order | string | asc or desc | — |
| limit | number | Max results (1-100) | — |
| search | string | Search by name, address, or twitter | — |
gmgn_wallet_detailGet detailed GMGN data for a specific wallet — profit, trades, win rates, tags, and category.
| Param | Type | Description | Required |
|---|---|---|---|
| address | string | Wallet address to look up | ✓ |
wallet_statsAggregate statistics across all data sources — total wallets, top performers, category breakdowns.
search_walletsSearch across all data sources (KolScan + GMGN Solana + GMGN BSC) by name, address, or twitter.
| Param | Type | Description | Required |
|---|---|---|---|
| query | string | Search query | ✓ |
| limit | number | Max results | — |
How we scraped 472 Solana KOL wallets from kolscan.io by reverse-engineering their Next.js app, discovering a hidden POST API, and using Playwright to bypass session protection.
Each entry in the scraped dataset contains these fields.
| Field | Type |
|---|---|
| wallet_address | string |
| name | string |
| string|null | |
| telegram | string|null |
| profit | number |
| wins | number |
| losses | number |
| timeframe | number |
All 472 wallets are pre-formatted for GMGN bulk import. Paste the JSON from output/gmgn-import.json.
[
{ "address": "CyaE1Vxv...", "name": "Cented", "emoji": "🐋" },
{ "address": "Bi4rd5FH...", "name": "theo", "emoji": "💰" },
...
]Step-by-step reverse engineering, from initial recon to full data extraction.
First step: fetch the raw HTML and identify the tech stack.
curl -s 'https://kolscan.io/leaderboard' -o page.html
head -100 page.htmlFound /_next/static/chunks/ script tags — confirming it's a Next.js application with App Router.
Tried common REST patterns with GET requests:
curl -s -o /dev/null -w "%{http_code}" 'https://kolscan.io/api/leaderboard' → 400
curl -s -o /dev/null -w "%{http_code}" 'https://kolscan.io/api/kols' → 400
curl -s -o /dev/null -w "%{http_code}" 'https://api.kolscan.io/' → 401400 means the endpoints exist but reject GET requests. 401 on the API subdomain means auth required.
Extracted all script chunk URLs from the page source:
curl -s 'https://kolscan.io/leaderboard' \
| grep -oE '"[^"]*/_next/static/chunks/[^"]*"'Found key chunks including:
app/leaderboard/page-939ad755c42d8b9d.js — the leaderboard page184-3d6ce3be6906820b.js — shared API helper chunkSearched each JS chunk for /api/ paths:
for chunk in 341-*.js 184-*.js 255-*.js; do
curl -s "https://kolscan.io/_next/static/chunks/${chunk}" \
| grep -oP '"/api/[^"]*"'
doneChunk 184 contained the gold: /api/trades, /api/tokens, /api/leaderboard, /api/data
Pulled the surrounding code context to see the full fetch call:
curl -s '.../184-*.js' | grep -oP '.{0,200}/api/leaderboard.{0,200}'Revealed the exact implementation:
fetch("/api/leaderboard", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ timeframe: e, page: t, pageSize: n })
})Key discovery: POST not GET. Parameters: timeframe (1/7/30), page (0-indexed), pageSize (50).
curl -s -X POST 'https://kolscan.io/api/leaderboard' \
-H 'Content-Type: application/json' \
-d '{"timeframe":1,"page":0,"pageSize":50}'
→ ForbiddenForbidden — The API requires a valid browser session. Cookie/session-based protection prevents direct curl access.
Discovered the page server-renders initial data via the initLeaderboard React prop:
curl -s 'https://kolscan.io/leaderboard' \
| grep -oP '\{[^}]*wallet_address[^}]*\}' | head -5Extracted 616 entries from the HTML — but only the first page per timeframe, and many had missing fields due to regex limits.
By reading the full page chunk (~14KB), we found:
react-infinite-scroll-componentscrollableTarget: "mainScroll" (not window!)[1, 7, 30] → Daily / Weekly / MonthlyInstalled Playwright to get a real browser session. First attempt scrolled window — captured 0 results.
// ❌ Wrong — infinite scroll listens on #mainScroll, not window
window.scrollTo(0, document.body.scrollHeight);The infinite scroll component only triggers when #mainScroll is scrolled.
// ✅ Correct — scroll the actual container
const el = document.getElementById('mainScroll');
if (el) el.scrollTop = el.scrollHeight;Combined with intercepting POST responses and clicking between Daily/Weekly/Monthly tabs, this captured all 1,304 entries across 472 unique wallets.
Daily: 434 entries (9 pages × 50 + 34)
Weekly: 435 entries (8 pages × 50 + 35)
Monthly: 435 entries (8 pages × 50 + 35)
─────────────────────────────────────────
Total: 1,304 entries
Unique: 472 walletsFull data saved to JSON with GMGN-compatible import format generated automatically.
This API only accepts POST, not GET
Minified code still reveals exact API signatures
Headless browsers bypass cookie/session protection
Infinite scroll often binds to a specific element
Next.js embeds initial page data in HTML as React props
Look in numbered chunks (184-*.js) for fetch calls