Delete all your messages in Discord channel

  • Open Discord in a browser like Chrome or Firefox;
  • Open DevTools pressing F12 or ⌘ command+option+J;
  • Copy the deleteDiscordMessages.js script and paste it in the Console, then press ENTER;
  • Edit the following text, then paste it in the console:
// fill with your info
var authToken = "MTX5MzQ1MjAyMjU0NjA2MzM2.ROFLMAO.UvqZqBMXLpDuOY3Z456J3JRIfbk";
var authorId = "112233445566778899";
var channelId = "112233445566778899";
var firstMessageId = "";

deleteMessages(authToken, authorId, channelId, firstMessageId); //start
  • It will start to delete messages. You will be able to follow the progress and the remaining time in a popup window.

Abort / Stop

Inside the console, type (uppercase) STOP=1 and press ENTER.

Variables

authToken

  1. Open the dev tools (F12), open the Network tab. (You should clear all requests for better readability if you see some.)
  2. Delete one message manually. In the request log, you will see a request with a DELETE method.
  3. Click on the request to open the details, and on the Headers tab, copy the ‘authorization’ token. It’s a long text > with dots like MTX5MzQ1MjAyMjU0NjA2MzM2.ROFLMAO…

authorId

Right click your avatar in a message you sent in the chat, Copy ID

channelId

  • For public channels: Right click a channel, Copy ID
  • For a DM/Direct messages: copy the number after /@me/ in the URL)

firstMessageId

  • Delete messages after one message - Right click a message, Copy ID
  • Delete since the begining of a channel - Leave this variable empty “”.

deleteDiscordMessages.js

//Paste this function in DevTools console inside Discord

/**
 * Delete all messages in a Discord channel or DM
 * @param {string} authToken Your authorization token
 * @param {string} authorId Author of the messages you want to delete
 * @param {string} channelId Channel were the messages are located
 * @param {string} afterMessageId Only delete messages after this, leave blank do delete all
 * @author Victornpb <https://www.github.com/victornpb>
 * @see https://gist.github.com/victornpb/135f5b346dea4decfc8f63ad7d9cc182
 */
function deleteMessages(authToken, authorId, channelId, afterMessageId) {
    const start = new Date();
    let delayDelete = 500;
    let delaySearch = 1000;
    let delCount = 0;
    let failCount = 0;
    let estimatedPing = 220;
    let grandTotal;
    let throttledCount = 0;
    let throttledTotalTime = 0;
    const history = [];

    const wait = async (ms) => new Promise(done => setTimeout(done, ms));
    const msToHMS = (s) => `${s / 3.6e6 | 0}h ${(s % 3.6e6) / 6e4 | 0}m ${(s % 6e4) / 1000 | 0}s`;
    function logger(type, args, style = '') {
        console[type].apply(console, args);
        history.push(args);
        pp.insertAdjacentHTML('beforeend', `<div style="${style}">${Array.from(args).map(o => typeof o === 'object' ? JSON.stringify(o) : o).join('\t')}</div>`);
        popup.scrollBy(0, 1e10);
    }
    function log() { logger('log', arguments, 'black'); }
    function log_info() { logger('info', arguments, 'color:darkturquoise;'); }
    function log_verb() { logger('debug', arguments, 'color:gray;'); }
    function log_warn() { logger('warn', arguments, 'color:orange;'); }
    function log_error() { logger('error', arguments, 'color:red;'); }
    function log_success() { logger('log', arguments, 'color:green;'); }

    var popup = window.open('', '', 'width=800,height=1000,top=0,left=0');
    if (!popup) return console.error('Popup blocked! Please allow popups and try again.');
    popup.document.write('<span>...</span>');
    popup.document.body.innerHTML = '<pre></pre>';
    const pp = popup.document.getElementsByTagName('pre')[0];
    

    log_info(`Started at ${start.toLocaleString()}`);
    log(`channelId=${channelId} authorId=${authorId} firstMessageId=${afterMessageId}`);
    log_info(`---- You can abort by setting STOP=1 on the console ----`);
    recurse();

    async function recurse() {
        const headers = {
            "Authorization": authToken
        };
        const deleteAfter = `search?author_id=${authorId}` + (afterMessageId ? `&min_id=${afterMessageId}` : '');
        const baseURL = `https://discordapp.com/api/v6/channels/${channelId}/messages/`;

        let resp;
        try {
            resp = await fetch(baseURL + deleteAfter, {
                headers
            });
        } catch (err) {
            log_error('Something went wrong!', err);
            return;
        }

        // not indexed yet
        if (resp.status === 202) {
            const w = (await resp.json()).retry_after;
            throttledCount++;
            throttledTotalTime += w;
            log_warn(`This channel wasn't indexed, waiting ${w} ms for discord to index it...`);
            await wait(w);
            return recurse();
        }

        if (!resp.ok) {
            if (resp.status === 429) {
                const r = await resp.json();
                const x = r.retry_after;
                throttledCount++;
                throttledTotalTime += x;
                log_warn(`! Rate limited by the API! Waiting ${x} ms ...`);
                await wait(x);
                return recurse();
            } else {
                log_error('API respondend with non OK status!', await resp.json());
                return;
            }
        }

        const result = await resp.json();

        const total = result.total_results;
        if (!grandTotal) grandTotal = total;
        log_info(`Messages to delete: ${result.total_results}`, `Time remaining: ${msToHMS((delaySearch * Math.round(total / 25)) + ((delayDelete + estimatedPing) * total))} (ping: ${estimatedPing << 0}ms)`);

        if (result.total_results > 0) {
            for (let i = 0; i < result.messages.length; i++) {
                const element = result.messages[i];
                for (let j = 0; j < element.length; j++) {
                    const message = element[j];

                    if (window.STOP) return log_error('STOPPED! (If you want to continue set STOP=0 and run again!');

                    if (message.type === 3) {
                        log_verb('Found a System message!? skipping it...', message);
                    } else if (message.author.id == authorId && message.hit == true) {

                        log(`${((delCount + 1) / grandTotal * 100).toFixed(2)}% (${delCount + 1}/${grandTotal}) Deleting ID:${message.id}`,
                            `[${new Date(message.timestamp).toLocaleString()}] ${message.author.username}#${message.author.discriminator}: ${message.content}`,
                            message.attachments.length ? message.attachments : '');
                        const s = Date.now();

                        let resp;
                        try {
                            resp = await fetch(baseURL + message.id, {
                                headers,
                                method: "DELETE"
                            });
                            delCount++;
                        } catch (err) {
                            log_error('Failed to delete message:', message, 'Error:', err);
                            failCount++;
                        }

                        if (!resp.ok) {
                            if (resp.status === 429) {
                                const r = await resp.json();
                                const x = r.retry_after;
                                throttledCount++;
                                throttledTotalTime += x;
                                log_warn(`! Rate limited by the API! Waiting ${x} ms ...`);
                                await wait(x);
                                i--;
                            } else {
                                log_error('API respondend with non OK status!', resp);
                            }
                        }
                        estimatedPing = (estimatedPing + (Date.now() - s)) / 2;
                        await wait(delayDelete);
                    }
                }
            }
            log_verb('Getting next messages...');
            await wait(delaySearch);
            return recurse();
        } else {
            log_success('---- DONE! ----');
            log_info(`Ended at ${new Date().toLocaleString()}! Total time: ${msToHMS(Date.now() - start.getTime())}`);
            log(`Rate Limited: ${throttledCount} times. Total time throttled: ${msToHMS(throttledTotalTime)}`);
            log(`Deleted ${delCount} messages , ${failCount} failed.`);
            return result;
        }
    }
}

//END.