Skip to content

Instantly share code, notes, and snippets.

@orion-v
Last active May 5, 2024 16:14
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save orion-v/95cb48fa73808cdc5c589fe415cc65f1 to your computer and use it in GitHub Desktop.
Save orion-v/95cb48fa73808cdc5c589fe415cc65f1 to your computer and use it in GitHub Desktop.
Delete all messages of an user in a Discord channel or server

Delete discord user message history

This script allow for user specific message deletion from an entire server or a single channel using the browser console. This script uses discord search API and it will only delete messages of a chosen user.

How to use

1. Enable developer mode in discord

Go to user settings > appearance in discord and enable Developer mode.

2. Copy and paste the script to a file so you can change the server and author ids.

3. Replace the server and author ids with your own.

Open discord and right click on the server icon and click copy id. Replace the server id in the script with your server id. Do the same process for the author id by right clicking the avatar image.

4. Run script in console

Press F12 in Chrome or Firefox to open the console. Paste the modified script in the console and press enter.

The more messages the longer it takes. You can check if the messages have been deleted by using the search.


Notes

I think there are some channels that this script won't work with. I think they may be NSFW channels but I haven't tested enough.

Use this script at your own risk

This script was based on the following scripts https://gist.github.com/niahoo/c99284a8908cd33d59b4aff802179e9b#gistcomment-2397287 https://gist.github.com/IMcPwn/0c838a6248772c6fea1339ddad503cce

async function clearMessages() {
const server = "000000000000000000"; // server id number
const author = "000000000000000000"; // user id number
const channel = window.location.href.split('/').pop(); // remove this line to delete all messages of an user from a server
const authToken = document.body.appendChild(document.createElement`iframe`).contentWindow.localStorage.token.replace(/"/g, "");
const headers = { 'Authorization': authToken, 'Content-Type': 'application/json' };
const baseURL = `https://discordapp.com/api/v6/channels`;
let searchURL = `https://discordapp.com/api/v6/guilds/${server}/messages/search?author_id=${author}`;
if (typeof channel !== 'undefined') searchURL = searchURL + `&channel_id=${channel}`;
let clock = 0;
let interval = 500;
function delay(duration) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), duration);
});
}
const response = await fetch(searchURL, {headers});
const json = await response.json();
console.log("There are " + json.total_results + " messages left to delete.");
await Array.from(json.messages).map(message => {
message.forEach(async function(item) {
if(item.hit == true) {
await delay(clock += interval);
await fetch(`${baseURL}/${item.channel_id}/messages/${item.id}`, { headers, method: 'DELETE' });
}
});
});
if (json.total_results > 0) {
delay(clock += interval).then(() => { clearMessages(); });
} else {
console.log("Finished deleting messages")
};
}
clearMessages();
Copy link

ghost commented Jul 13, 2018

How exactly can this work in a DM?

Open discord and right click on the server icon and click copy id. Replace the server id in the script with your server id. Do the same process for the author id by right clicking the avatar image.

@Nicckonator
Copy link

Nicckonator commented Jul 21, 2018

Sadly doesnt work for me for a DM (not a server/channel)

Uncaught (in promise) TypeError: Cannot convert undefined or null to object VM280:24
at Function.from (native)
at clearMessages (:24:14)

is what i get as error.

any fix?

@TrunerReisar
Copy link

I tried using this (and the IMcPwn one which worked like a charm up to this point, but that page is gone now) and all I'm getting is this error now:

Uncaught (in promise) TypeError: Cannot read property 'replace' of undefined
at clearMessages (:5:110)
at :37:1

Is this something easily fixable?

@etch286
Copy link

etch286 commented Aug 7, 2018

same as above

@Alvin388
Copy link

Not working anymore

@instinctualjealousy
Copy link

instinctualjealousy commented Sep 21, 2018

If it's anything like the other script, the AuthToken isn't being correctly grabbed and has to be manually inserted instead.

const authToken = "AuthTokenHere";

You can grab it from the dev tools "Application -> Local Storage -> https://discordapp.com", under "token" after a page refresh, I think.

Be sure to remove line #5 if you're trying to do what I'm doing, otherwise it'll say there's 0 messages to delete. It seems to be working for me so far.

@Knuckl3s
Copy link

Hello
Can someone give a complete code to delete private messages? It works very well on servers, but for private discussions I have no idea what to change.

Thank you

@PointMeAtTheDawn
Copy link

My guess is it is using https://discord.js.org/#/docs/main/stable/class/GuildMember, which doesn't exist in a DM. You'd have to repoint all references to GuildMembers to https://discord.js.org/#/docs/main/stable/class/User (and they don't have stuff like Nickname or DisplayName, just Username IIRC).

@GreenReaper
Copy link

You probably need &include_nsfw=true at the end of the channel string to get NSFW channels. That's what the search bar uses.

However right this moment it won't work because the search API as a whole appears to have been removed, breaking Discord's own search bar. This is presumably because it was causing the recent downtime (search is easy to abuse, causing a denial-of-service deliberately or not).

@orion-v
Copy link
Author

orion-v commented Dec 10, 2019

You probably need &include_nsfw=true at the end of the channel string to get NSFW channels. That's what the search bar uses.

Thanks for that info.

However right this moment it won't work because the search API as a whole appears to have been removed, breaking Discord's own search bar. This is presumably because it was causing the recent downtime (search is easy to abuse, causing a denial-of-service deliberately or not).

Yours was the first comment that githubgist alerted me. I didn't know there were so many comments here. I will see if I can answer some questions when I have some more time.

Discord search appears to be working again. I don't know if they changed anything or if the code will still work.

@GreenReaper
Copy link

It works, but the script gets rate limited at an interval of 500ms. Even 3000ms was too much after a while. The 429 response has this body:

{
  "global": false, 
  "message": "You are being rate limited.", 
  "retry_after": 26104
}

The value appears to be in ms. Typically further requests (at least of that type) are refused with a decreasing timeout from 30 seconds to 0.

@swordfite
Copy link

This script by a-SynKronus works well in DMs. But make sure you keep the dms of the person you want your dms deleted in open.


clearMessages= function() {
const author = "YOUR_ID_HERE";
const authToken = "YOUR_TOKEN_HERE";
const channel = window.location.href.split('/').pop();
const headers = { 'Authorization': authToken, 'Content-Type': 'application/json' };

let clock = 0;
let interval = 500;
function delay(duration) {
	return new Promise((resolve, reject) => {
		setTimeout(() => resolve(), duration);
	});
}

fetch(`https://discordapp.com/api/v6/channels/${channel}/messages/search?author_id=${author}`, {headers})
	.then(response => response.json())
	.then(json => {
		Array.from(json.messages).map(message => {
			message.forEach(function(item) {
				if(item.hit == true) {
					delay(clock += interval).then(() => { fetch(`https://discordapp.com/api/v6/channels/${item.channel_id}/messages/${item.id}`, { headers, method: 'PATCH', body: JSON.stringify({'content': 'This comment has been overwritten.'}) }) });
					delay(clock += interval).then(() => { fetch(`https://discordapp.com/api/v6/channels/${item.channel_id}/messages/${item.id}`, { headers, method: 'DELETE' }) });
				}
			});
		});

		if (json.total_results > 0) { delay(clock += interval).then(() => { clearMessages(); }); }
	});

}
clearMessages();

@marcosrocha85
Copy link

marcosrocha85 commented Nov 17, 2020

Uncaught (in promise) TypeError: document.body.appendChild(...).contentWindow.localStorage.token is undefined
When trying to use the script to delete all messages from myself in all channels.

I think Discord does not save token on localStorage anymore. Now we should use OAuth2 in order to get Authorization token.


Quick workaround: Follow this.

@scsmash3r
Copy link

Works well, but often catches up the rate limits. Thanks to @marcosrocha85 for the token tip.

@mikecann
Copy link

Okay just as a reference this works for me, deletes all of a users messages from the entire server:

async function clearMessages() {
	const server = "000000000000000000"; // server id number
	const author = "000000000000000000"; // user id number

	const authToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
	const headers = { 'Authorization': authToken, 'Content-Type': 'application/json' };
	const baseURL = `https://discordapp.com/api/v6/channels`;
	let searchURL = `https://discordapp.com/api/v6/guilds/${server}/messages/search?author_id=${author}`;

	let clock = 0;
	let interval = 2000;
	function delay(duration) {
		return new Promise((resolve, reject) => {
			setTimeout(() => resolve(), duration);
		});
	}

	const response = await fetch(searchURL, {headers});
	const json = await response.json();
	console.log("There are " + json.total_results + " messages left to delete.");
	await Array.from(json.messages).map(message => {
		message.forEach(async function(item) {
			if(item.hit == true) {
				await delay(clock += interval);
				await fetch(`${baseURL}/${item.channel_id}/messages/${item.id}`, { headers, method: 'DELETE' });
			}
		});
	});

	if (json.total_results > 0) { 
		delay(clock += interval).then(() => { clearMessages(); }); 
	} else {
		console.log("Finished deleting messages")
	};
}
clearMessages();

As @instinctualjealousy mentioned you need to manually get the auth token.

The "token" in Local Storage wasnt there so I refreshed the page by typing window.location.reload(). It then turned up. I grabbed it and smashed it into this script and it worked. I had to increase the timeout to 2000 otherise I would be rate limited.

@KLEPTOROTH
Copy link

Okay just as a reference this works for me, deletes all of a users messages from the entire server:

async function clearMessages() {
	const server = "000000000000000000"; // server id number
	const author = "000000000000000000"; // user id number

	const authToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
	const headers = { 'Authorization': authToken, 'Content-Type': 'application/json' };
	const baseURL = `https://discordapp.com/api/v6/channels`;
	let searchURL = `https://discordapp.com/api/v6/guilds/${server}/messages/search?author_id=${author}`;

	let clock = 0;
	let interval = 2000;
	function delay(duration) {
		return new Promise((resolve, reject) => {
			setTimeout(() => resolve(), duration);
		});
	}

	const response = await fetch(searchURL, {headers});
	const json = await response.json();
	console.log("There are " + json.total_results + " messages left to delete.");
	await Array.from(json.messages).map(message => {
		message.forEach(async function(item) {
			if(item.hit == true) {
				await delay(clock += interval);
				await fetch(`${baseURL}/${item.channel_id}/messages/${item.id}`, { headers, method: 'DELETE' });
			}
		});
	});

	if (json.total_results > 0) { 
		delay(clock += interval).then(() => { clearMessages(); }); 
	} else {
		console.log("Finished deleting messages")
	};
}
clearMessages();

As @instinctualjealousy mentioned you need to manually get the auth token.

The "token" in Local Storage wasnt there so I refreshed the page by typing window.location.reload(). It then turned up. I grabbed it and smashed it into this script and it worked. I had to increase the timeout to 2000 otherise I would be rate limited.

Thank you so much for this! One problem I'm having running this, is it didn't delete ALL messages from the user. I can still search and see many messages from the user I targeted. I did see some of them disappear, but it only got about 200 of 900+ messages. Any ideas why this would be?

@sbaysan21
Copy link

sbaysan21 commented Apr 2, 2022

Thank you so much for this! One problem I'm having running this, is it didn't delete ALL messages from the user. I can still search and see many messages from the user I targeted. I did see some of them disappear, but it only got about 200 of 900+ messages. Any ideas why this would be?

This same thing happened to me where it stopped deleting messages after about getting through 10% of what I wanted to get rid of. I figured out that it wasn't deleting messages that were archived in threads, so I had to unarchive them manually.

@0xAskar
Copy link

0xAskar commented Oct 13, 2022

I'm still getting rate limited even with using your exact script @mikecann. thoughts on why? Interval is 2000 ms right now

@PatrickKing
Copy link

PatrickKing commented Oct 26, 2022

I've created a modified version of the above script which pays attention to the server error that indicates we're being rate limited, and which pauses for a bit. It still has issues, in particular it doesn't handle the failure to delete a message due to it being archived.

It works for me. As before, this comes with zero warranty, use at your own risk!

Edited to add: when deleting many messages from the same channel it's common to see 'try again later' values higher than 7000 ms. But, often many messages can be deleted in a row without being rate limited

Edited again: modified to print an URL to archived messages, to more easily track them down.

function clearMessages () {
  const server = "000000000000000000"; // server id number
  const author = "000000000000000000"; // user id number

  const channel = window.location.href.split('/').pop(); // remove this line to delete all messages of an user from a server

  const authToken = document.body.appendChild(document.createElement`iframe`).contentWindow.localStorage.token.replace(/"/g, "");
  const headers = { 'Authorization': authToken, 'Content-Type': 'application/json' };
  const baseURL = `https://discordapp.com/api/v6/channels`;
  let searchURL = `https://discordapp.com/api/v6/guilds/${server}/messages/search?author_id=${author}`;
  if (typeof channel !== 'undefined') searchURL = searchURL + `&channel_id=${channel}`;


  let itemsForDeletion = []

  function checkForMessages () {
    fetch(searchURL, {headers})
    .then((response) => {
      return response.json()
    })
    .then((json) => {
      console.log("There are " + json.total_results + " messages left to delete.");
      if (json.total_results === 0) {
        console.log('Finished deleting messages!')
        return
      }

      for (const message of json.messages) {
        for (const item of message) {
          if (item.hit === true) {
            itemsForDeletion.push(item)
          }
        }
      }

      deleteNextMessage()
    })
  }

  function deleteNextMessage () {

    if (itemsForDeletion.length === 0) {
      checkForMessages()
      return
    }

    const item = itemsForDeletion[itemsForDeletion.length - 1]

    fetch(`${baseURL}/${item.channel_id}/messages/${item.id}`, { headers, method: 'DELETE' })
    .then((response) => {

      if (response.status === 200 || response.status === 204) {
        itemsForDeletion.pop()
        deleteNextMessage()
      }
      else if (response.status === 429) {
        // too many requests
        response.json().then((errorJson) => {
          console.log(`Waiting (${errorJson.retry_after}ms)`)
          setTimeout(deleteNextMessage, errorJson.retry_after)
        })
      }
      else if (response.status === 400) {
        console.log(`Check whether this message is in an archived/closed thread: https://discord.com/channels/${server}/${item.channel_id}/${item.id}`)
        itemsForDeletion.pop()
        deleteNextMessage()
      }
      else {
        itemsForDeletion.pop()
        deleteNextMessage()
      }

    })
    .catch((error) => {
      console.log(error)
    })

  }

  checkForMessages()

}

clearMessages()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment