# Discord Channel Message Scraper (`recordsdata/discord-scraper`) Actor

Export Discord channel messages: content, author, attachments, embeds, reactions, timestamps. Export CSV, Excel, JSON.

- **URL**: https://apify.com/recordsdata/discord-scraper.md
- **Developed by:** [RecordsData](https://apify.com/recordsdata) (community)
- **Categories:** Social media, Automation
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

<p align="center">
  <img src="https://api.apify.com/v2/key-value-stores/AAm3a1h3Z9nYfrvh9/records/banner?v=3" alt="RecordsData" width="100%" />
</p>

## 💬 Discord Message Scraper: Export Channel History

> 🚀 **Discord Message Scraper** exports a channel's message history in seconds: content, author, attachments, embeds, reactions, mentions, and timestamps, in the order they were posted. Point it at a channel URL and a token, get a structured dataset back.

> 🕒 **Last updated:** 2026-08-29 · **📊 21 fields** per message · pagination up to full channel history · CSV, Excel, JSON export

Discord doesn't expose channel history through a public search index, so pulling a full conversation thread out for analysis, moderation review, or archiving normally means scrolling and copy-pasting by hand. This Actor calls Discord's own message API directly and turns a channel into a clean, exportable dataset: one row per message, ready for a spreadsheet or a downstream pipeline.

| 🎯 Target audience | 💡 Primary use cases |
|---|---|
| Community managers, researchers, moderators, data teams | Archiving a channel before it's deleted, sentiment/trend analysis on a community, exporting evidence for moderation, building a searchable message log |

### 📋 What the Discord Message Scraper does

Given a channel URL, it walks the channel's message history page by page (newest-first by default, or oldest-first for a full archive) and returns each message as a structured record: text content, author profile, attachments, embeds, reaction counts, mentions, pin status, and both posted and edited timestamps. Runs on the Apify platform, so every run is schedulable, monitorable from the Console, and reachable through the Apify API or any of Apify's integrations (Zapier, Make, n8n).

### ⚙️ Input

| Field | Type | Required | Description |
|---|---|---|---|
| `token` | string | ✅ | Your personal Discord token. See "How to use" below. |
| `channelUrl` | string | ✅ | `https://discord.com/channels/{serverId}/{channelId}`, from a channel's right-click "Copy Link" menu. |
| `maxItems` | integer | Optional | Stop after this many messages. Leave empty for the full channel history. |
| `oldestFirst` | boolean | Optional | Off starts from the newest message. On starts from the first message ever posted. |
| `minDelaySecs` / `maxDelaySecs` | integer | Optional | Random wait between pages, in seconds. Defaults: 1 and 3. |
| `proxyConfiguration` | object | Optional | Route requests through an Apify Proxy IP. |

Minimal input:

```json
{
  "token": "your-discord-token",
  "channelUrl": "https://discord.com/channels/123456789012345678/123456789012345679",
  "maxItems": 100
}
```

Full channel archive, oldest message first:

```json
{
  "token": "your-discord-token",
  "channelUrl": "https://discord.com/channels/123456789012345678/123456789012345679",
  "oldestFirst": true,
  "minDelaySecs": 2,
  "maxDelaySecs": 5
}
```

> ⚠️ **Good to know:** this Actor authenticates as your personal Discord account, not an official bot. Automating a personal account this way is against Discord's Terms of Service and carries a real risk of that account being banned. Use a secondary or otherwise expendable account, never your main one, and never a token for an account you can't afford to lose. You are responsible for how you use it.

### 📊 Output

| Field | Description |
|---|---|
| 🖼 `authorAvatarUrl` | Author's avatar image URL |
| 💬 `content` | Message text |
| 👤 `authorUsername` / `authorGlobalName` / `authorId` | Author identity |
| 🤖 `authorIsBot` | Whether the author is a bot account |
| # `channelId` / `messageId` | Discord IDs |
| 📎 `attachmentCount` / `attachments` | File attachment count and details |
| 🔗 `embedCount` / `embeds` | Link preview/embed count and details |
| 😀 `reactionCount` | Total reactions on the message |
| @ `mentionCount` / `mentions` | Users mentioned |
| 📌 `pinned` | Pin status |
| 🕒 `postedAt` / `editedAt` | Timestamps |
| 🔗 `messageUrl` | Direct link back to the message |

Real sample record (from a live run against a public server):

```json
{
  "authorAvatarUrl": "https://cdn.discordapp.com/avatars/712447082652237904/0bbc2086679de3b310846db9e7021b0c.png",
  "content": "anyone free to review the PR I opened this morning?",
  "authorUsername": "riverjay",
  "authorGlobalName": "River",
  "authorId": "712447082652237904",
  "authorIsBot": false,
  "channelId": "1480052419512635462",
  "messageId": "1518669370136723536",
  "attachmentCount": 0,
  "attachments": [],
  "embedCount": 0,
  "embeds": [],
  "reactionCount": 2,
  "mentionCount": 0,
  "mentions": [],
  "pinned": false,
  "postedAt": "2026-06-22T17:29:53.353Z",
  "editedAt": null,
  "messageUrl": "https://discord.com/channels/1371199180072292513/1480052419512635462/1518669370136723536",
  "scrapedAt": "2026-08-29T23:28:13.093Z",
  "error": null
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel from the Storage tab.

### ✨ Why choose this Actor

- ✅ Direct calls to Discord's own message API, no browser automation, so runs finish fast
- 🔓 Works on any channel your account can already see, no server admin approval or bot invite needed
- 📄 Full pagination: pull the last 20 messages or the entire channel history in one run
- ⚠️ Honest about the trade-off: the input schema and this README both disclose the ToS risk up front, most tools like this don't

### 📈 How it compares to alternatives

An official Discord bot (OAuth2 + Bot API) is the ToS-safe way to read a server's messages, but it only works on servers where someone with Manage Server permission has invited the bot first, so it can't reach a channel you don't already administrate. This Actor trades that safety for reach: it works on any channel you're already a member of, with no invite step, at the cost of using a personal account token instead of a bot identity.

### 🚀 How to use

1. Open [console.apify.com](https://console.apify.com) and find Discord Message Scraper in your Actors.
2. Get your Discord token: open discord.com in a browser you're logged into, open DevTools (F12) → Console, and run a token-extraction snippet (search "get discord token console" for a current one, Discord's internal structure changes periodically so snippets do too).
3. Right-click the target channel in Discord → Copy Link, paste it into `channelUrl`.
4. Set `maxItems` (or leave empty for the full history) and click Start.
5. Download results as JSON, CSV, or Excel from the Storage tab once the run finishes.

### 💼 Business use cases

**Community management.** Archive a channel's full history before pruning it or before a server migration.

**Research.** Pull message-level data from a public community for sentiment or trend analysis.

**Moderation.** Export a conversation thread as evidence for a report or an appeal.

**Compliance.** Keep a searchable record of a workspace's Discord communications where policy requires it.

### ❓ Frequently Asked Questions

**Is this against Discord's Terms of Service?**
Yes. Automating a personal Discord account outside the official Bot API violates Discord's ToS and can get that account banned. This Actor discloses that plainly instead of hiding it. Use an account you're prepared to lose.

**Do I need to be an admin of the server?**
No. You only need to already be a member with access to view the target channel.

**How do I get a Discord token?**
Log into discord.com in a browser, open DevTools (F12) → Console, and run a token-extraction snippet. Search "get discord token console" for a current one.

**Will my token be stored or shared?**
No. It's used only for the run you provide it in and isn't logged or persisted by this Actor.

**Can I scrape a channel I'm not a member of?**
No. Your account needs to already have view access to that channel, same as opening it in the Discord app.

**Does this scrape server member lists?**
Not in this version. Discord serves member lists over a real-time connection rather than a simple API call, which is a meaningfully bigger automation footprint; it's intentionally out of scope for now.

**How much does it cost to run?**
Apify's free tier covers small runs. Cost scales with message count, roughly proportional to how many pages of history you pull. Check current Apify plan pricing at [apify.com/pricing](https://apify.com/pricing).

**Can I resume a large export if it stops partway?**
Set `oldestFirst: true` and re-run with `maxItems` adjusted; the Actor works from the message ID range so a re-run naturally continues from where you left off if you track the last `messageId` seen.

**Can I schedule this to run automatically?**
Yes, Apify Actors support scheduling directly from the Console, so you can pull new messages daily or hourly.

**What happens if my token expires mid-run?**
Discord returns a 401, the run logs the error and stops rather than silently failing.

### 🔌 Integrate with any app

Every Apify Actor exposes a REST API, webhooks, and native integrations with Zapier, Make, and n8n. Trigger a run, get notified when it finishes, and pull results straight into your own tools.

> **⚠️ Disclaimer:** independent tool, not affiliated with or endorsed by Discord Inc. Only data visible to the account whose token you provide is collected. Contact: contact.punkrecordsdata@gmail.com

# Actor input Schema

## `token` (type: `string`):

Your personal Discord token, from a browser you're already logged into (F12 → Console → paste the token-grab snippet linked in the Actor's README). ⚠️ This authenticates as YOUR account, not an official bot. Automating a personal Discord account this way is against Discord's Terms of Service and can get that account banned. Use an account you're comfortable putting at risk, never your only/primary account.

## `channelUrl` (type: `string`):

Right-click a channel in Discord → Copy Link. Looks like https://discord.com/channels/{serverId}/{channelId}. You must already be a member of that server for your token to see it.

## `maxItems` (type: `integer`):

Stop after this many messages. Leave empty to pull the entire channel history.

## `oldestFirst` (type: `boolean`):

Off (default) starts from the newest message and works backward. On starts from the very first message in the channel and works forward — slower, but useful for a full archive.

## `minDelaySecs` (type: `integer`):

Wait at least this long before fetching the next page of messages. Higher values look less automated and lower ban risk, at the cost of speed.

## `maxDelaySecs` (type: `integer`):

Upper bound of the random wait between pages.

## `proxyConfiguration` (type: `object`):

Optional. Routes requests through an Apify Proxy IP instead of the platform's own, for extra traffic-pattern variety.

## Actor input object example

```json
{
  "channelUrl": "https://discord.com/channels/613425648685547541/613425648685547546",
  "maxItems": 100,
  "oldestFirst": false,
  "minDelaySecs": 1,
  "maxDelaySecs": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "channelUrl": "https://discord.com/channels/613425648685547541/613425648685547546",
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("recordsdata/discord-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "channelUrl": "https://discord.com/channels/613425648685547541/613425648685547546",
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("recordsdata/discord-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "channelUrl": "https://discord.com/channels/613425648685547541/613425648685547546",
  "maxItems": 100
}' |
apify call recordsdata/discord-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,recordsdata/discord-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/iQQpJrZK7YZRGxMHP/builds/eWjqcBoMgG0oVG4sF/openapi.json
