Discord Message Scraper
Pricing
from $0.50 / 1,000 message scrapeds
Discord Message Scraper
Scrape Discord channel & DM messages via the official API with your own bot or user token — content, author, timestamps, attachments, reactions, replies. HTTP-only, MCP-ready.
Pricing
from $0.50 / 1,000 message scrapeds
Rating
0.0
(0)
Developer
Khadin Akbar
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Scrape Discord channel and DM messages through the official Discord REST API using your own bot token (recommended) or user token. Returns clean, flat, MCP-ready records — message content, author, timestamps, attachments, reactions, replies, and a direct jump link — with no browser, no proxy, and official-API-grade reliability.
Built for community managers, moderators, researchers, and AI agents that need structured Discord message history out of channels they have access to.
What it does
You supply a Discord token and one or more channel IDs (or channel URLs). The actor pages through each channel's message history newest-first via GET /channels/{id}/messages, applies your filters, and writes one record per message to the dataset. It handles Discord rate limits (429 back-off), resumable pagination, and date/message-ID ranges.
When to use it
- Export a channel's full message history for analysis, backup, or compliance.
- Pull messages from a date range or since a known message ID (incremental scrapes).
- Collect messages from a specific user, containing a keyword, or with attachments.
- Feed structured Discord conversation data to an LLM/agent via Apify MCP.
When NOT to use it: for server size, member counts, channel lists, or emoji metadata (no auth needed), use the companion Discord All-in-One Scraper. This actor reads message content, which Discord always gates behind a token.
Output
One record per message. Example (detailed format):
{"messageId": "1180000000000000000","channelId": "112233445566778899","channelName": "general","guildId": "998877665544332211","authorId": "223344556677889900","authorUsername": "jdoe","authorGlobalName": "John","authorIsBot": false,"content": "gm everyone, the giveaway starts now!","timestamp": "2024-03-01T12:00:00.000Z","editedTimestamp": null,"messageType": "default","isPinned": false,"mentionsEveryone": true,"attachmentCount": 1,"embedCount": 0,"reactionCount": 12,"replyToMessageId": null,"jumpUrl": "https://discord.com/channels/998877665544332211/112233445566778899/1180000000000000000","mentionedUserIds": ["223344556677889900"],"attachments": [{ "url": "https://cdn.discordapp.com/...", "filename": "banner.png", "size": 84211, "contentType": "image/png", "width": 1200, "height": 630, "isImage": true }],"reactions": [{ "emoji": "🔥", "emojiId": null, "count": 12 }],"stickerNames": []}
| Field | Type | Description |
|---|---|---|
messageId | string | Discord message snowflake ID |
channelId / channelName | string | Source channel ID and name |
guildId | string | null | Server ID (null for DMs) |
authorId / authorUsername / authorGlobalName | string | Author identity |
authorIsBot | boolean | Whether the author is a bot |
content | string | Raw message text |
timestamp / editedTimestamp | ISO 8601 | Sent / last-edited time |
messageType | string | default, reply, thread_starter, … |
isPinned / mentionsEveryone | boolean | Message flags |
attachmentCount / embedCount / reactionCount | integer | Counts |
replyToMessageId | string | null | Parent message for replies |
jumpUrl | string | Direct link to the message |
mentionedUserIds, attachments[], reactions[], stickerNames[] | array | Present in detailed format only |
Choose concise response format to drop the arrays and keep only counts — a smaller, token-efficient payload for LLM/agent use.
Pricing
Pay-per-event (plus optional pay-per-usage):
| Event | Price |
|---|---|
| Actor start | $0.00005 |
| Message scraped | $0.0005 / message |
Cost is roughly channels × maxMessagesPerChannel × $0.0005. Scraping 1,000 messages costs about $0.50. The actor logs the upper-bound cost before it starts charging.
How to get a Discord bot token (recommended)
- Go to discord.com/developers/applications → New Application.
- Open the Bot tab → Reset Token → copy the token. Paste it into the
Discord tokeninput (it is stored as a secret). - Under Bot → Privileged Gateway Intents, enable Message Content Intent.
- Open OAuth2 → URL Generator, tick bot scope and the View Channels + Read Message History permissions, open the generated URL, and add the bot to your server.
- Enable Developer Mode in Discord (Settings → Advanced), right-click a channel → Copy Channel ID, and paste it into
channels.
Keep Token type = Bot (the default).
User tokens
Setting Token type = User lets the actor read any channel/DM the account can already see, without adding a bot. This is self-botting and violates Discord's Terms of Service — it can get the account banned. Use only on accounts you accept that risk for.
Input example
{"discordToken": "YOUR_BOT_TOKEN","tokenType": "bot","channels": ["112233445566778899"],"maxMessagesPerChannel": 500,"afterDate": "2024-01-01","filterContains": "giveaway","responseFormat": "detailed"}
Run via API
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~discord-message-scraper/runs?token=APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{ "discordToken": "YOUR_BOT_TOKEN", "channels": ["112233445566778899"], "maxMessagesPerChannel": 200 }'
Use with AI agents (MCP)
This actor is MCP-ready. Connect via https://mcp.apify.com?tools=khadinakbar/discord-message-scraper and an agent can call it with a channel ID and token, receiving structured JSON it can reason over directly. Use responseFormat: "concise" to minimize token usage.
Tips & behavior
- Threads: pass a thread's own channel ID in
channelsto scrape its messages. - Resuming: save the oldest
messageIdyou received and pass it asbeforeMessageIdnext run; or useafterMessageIdto fetch only newer messages. - Inaccessible channels (bot not in server, missing Read Message History, or deleted) are skipped with a warning. If every channel is inaccessible, the run fails with a clear message rather than returning an empty success.
- Filters (
filterContains,filterFromUserId,onlyWithAttachments) are applied after fetching, so the per-channel cap counts post-filter results.
FAQ
Do I need a bot token? Yes — Discord requires authentication to read messages. A bot token is the legitimate path. User tokens work but violate Discord TOS.
Does it need a proxy? No. Discord rate-limits per token, not per IP, so the actor talks directly to the API with no proxy cost.
How fast is it? Up to ~100 messages per API request, throttled to respect Discord's rate limits. Expect a few thousand messages per minute per token.
Can it read DMs? With a user token, yes — pass the DM channel ID. Bot tokens cannot read user DMs.
Will it get blocked? No anti-bot is involved; it's the official API. The only failure modes are an invalid token (401) or a channel the token can't access (403/404).
Legal & compliance
This actor accesses Discord only with credentials you provide, for channels you have permission to read. You are responsible for complying with Discord's Terms of Service, Developer Terms, applicable privacy laws (e.g. GDPR), and any server rules. Scrape only data you are authorized to access. User-token (self-bot) usage violates Discord's Terms of Service; the bot-token path is recommended. This tool is provided for legitimate moderation, backup, research, and analytics use.
Related actors
- Discord All-in-One Scraper — server size, channels, emojis, and discovery (no token needed).