Scraping Central is reader-supported. When you buy through links on our site, we may earn an affiliate commission.

Tutorial

How to Scrape Discord Server Data

Learn how to collect Discord server data including messages, members, and channels using Python bots and the Discord API.

Discord servers contain valuable data for community analysis, market research, and trend monitoring. The most reliable approach uses the official Discord API through a bot account.

Setting Up a Discord Bot

First, create a bot at https://discord.com/developers/applications:

  1. Create a new application
  2. Go to the Bot section and create a bot
  3. Enable the "Message Content Intent" under Privileged Gateway Intents
  4. Generate an invite link with appropriate permissions
  5. Invite the bot to your target server
pip install discord.py

Scraping Messages with discord.py

import discord
import json
import asyncio
from datetime import datetime, timedelta

intents = discord.Intents.default()
intents.message_content = True
intents.members = True

client = discord.Client(intents=intents)

@client.event
async def on_ready():
    print(f"Bot connected as {client.user}")

    guild = client.guilds[0]  # First server the bot is in
    messages_data = []

    for channel in guild.text_channels:
        try:
            async for message in channel.history(limit=1000):
                messages_data.append({
                    "channel": channel.name,
                    "author": str(message.author),
                    "content": message.content,
                    "timestamp": str(message.created_at),
                    "reactions": [str(r.emoji) for r in message.reactions]
                })
        except discord.Forbidden:
            print(f"No access to #{channel.name}")

    with open("discord_messages.json", "w") as f:
        json.dump(messages_data, f, indent=2)

    print(f"Scraped {len(messages_data)} messages")
    await client.close()

client.run("YOUR_BOT_TOKEN")

Scraping Server Members

@client.event
async def on_ready():
    guild = client.guilds[0]
    members = []

    async for member in guild.fetch_members(limit=None):
        members.append({
            "id": member.id,
            "name": str(member),
            "joined": str(member.joined_at),
            "roles": [role.name for role in member.roles],
            "bot": member.bot
        })

    print(f"Found {len(members)} members")
    await client.close()

Scraping Specific Channels by Date Range

from datetime import datetime, timezone

async def scrape_channel_range(channel, start_date, end_date):
    messages = []

    async for message in channel.history(
        after=start_date,
        before=end_date,
        oldest_first=True
    ):
        messages.append({
            "content": message.content,
            "author": str(message.author),
            "timestamp": str(message.created_at),
            "attachments": [a.url for a in message.attachments],
            "embeds": [e.to_dict() for e in message.embeds]
        })

    return messages

# Usage in on_ready:
# start = datetime(2026, 1, 1, tzinfo=timezone.utc)
# end = datetime(2026, 4, 1, tzinfo=timezone.utc)
# data = await scrape_channel_range(channel, start, end)

Rate Limits and Best Practices

Discord enforces strict rate limits:

  • 50 requests per second per bot globally
  • 5 messages per 5 seconds per channel for sending
  • History fetches are limited to 100 messages per API call

Best practices:

  • Add delays between channel scrapes (await asyncio.sleep(1))
  • Use after and before parameters for incremental scraping
  • Store progress to resume if interrupted
  • Only collect data from servers where you have proper authorization

Important Legal Note

Only scrape Discord servers where you have permission or where you operate the server. Scraping private servers without consent violates Discord's Terms of Service and may violate privacy laws.