How to Bulk Delete Your Tweets on X Using the Browser Console
If you want to clean up your X / Twitter account, deleting tweets one by one can take forever.
There are paid tools that can do this, but you can also automate the process directly from your browser using JavaScript and the browser console.
Before You Start
- This method works directly in your browser using JavaScript.
- You must be logged into your X account.
- Deleted tweets cannot be recovered.
- X may temporarily rate limit your account if you delete too many tweets too quickly.
- Always double check scripts before running them in your browser console.
Script Settings
You can customize the behavior of the script by changing the values in the CONFIG section:
const CONFIG = {
dryRun: false,
maxActions: 9999,
delayMs: 5000,
skipPinned: true,
removeReposts: true,
};
- dryRun , If set to
true, the script will simulate actions without actually deleting anything. - maxActions , Maximum number of tweets or reposts the script will process before stopping automatically.
- delayMs , Delay in milliseconds between actions. Higher values reduce the chance of rate limiting.
- skipPinned , If set to
true, pinned tweets will not be deleted. - removeReposts , If set to
true, reposts will also be removed automatically.
Step 1: Open Your X Profile
Go to your profile page on X:
Make sure you are viewing your own posts timeline.
Step 2: Open Developer Tools
- Press F12 on your keyboard
- Or right click anywhere on the page and click Inspect
- Open the Console tab
Step 3: Paste and Run the Script
Copy and paste the following code into the browser console, then press Enter:
(() => {
// =========================
// CONFIG
// =========================
const CONFIG = {
dryRun: false,
maxActions: 9999,
delayMs: 5000,
skipPinned: true,
removeReposts: true,
};
let actions = 0;
let stopped = false;
// =========================
// STOP FUNCTION
// =========================
window.stopTweetCleanup = () => {
stopped = true;
console.log("Tweet cleanup stopped.");
};
// =========================
// HELPERS
// =========================
const wait = (ms) =>
new Promise(resolve => setTimeout(resolve, ms));
async function clickElement(el, label) {
if (!el) return false;
if (CONFIG.dryRun) {
console.log("[DRY RUN]", label);
return true;
}
el.click();
console.log("[CLICKED]", label);
return true;
}
function getTopArticle() {
return document.querySelector("section article");
}
function isPinned(article) {
if (!article) return false;
return article.innerText
.toLowerCase()
.includes("pinned");
}
// =========================
// MAIN POST PROCESSOR
// =========================
async function processPost() {
if (stopped) return false;
const article = getTopArticle();
if (!article) {
console.log("No posts found.");
return false;
}
// Skip pinned
if (CONFIG.skipPinned && isPinned(article)) {
console.log("Skipping pinned post.");
window.scrollBy(0, 800);
return true;
}
// =========================
// REMOVE REPOSTS
// =========================
if (CONFIG.removeReposts) {
const repostButton = article.querySelector(
"button[data-testid='unretweet']"
);
if (repostButton) {
console.log("Repost detected.");
await clickElement(
repostButton,
"Open repost dialog"
);
await wait(1500);
const confirmUndo = [
...document.querySelectorAll(
"div[role='menuitem']"
)
].find(el =>
el.innerText
.toLowerCase()
.includes("undo")
);
if (confirmUndo) {
await clickElement(
confirmUndo,
"Confirm undo repost"
);
actions++;
await wait(2000);
window.scrollBy(0, 800);
return true;
}
console.log(
"Undo repost option not found."
);
}
}
// =========================
// DELETE TWEETS
// =========================
const menuButton = article.querySelector(
"button[data-testid='caret']"
);
if (!menuButton) {
console.log("Menu button not found.");
window.scrollBy(0, 800);
return true;
}
await clickElement(menuButton, "Open menu");
await wait(1500);
const deleteItem = [
...document.querySelectorAll(
"div[role='menuitem']"
)
].find(el =>
el.innerText.trim() === "Delete"
);
if (deleteItem) {
console.log("Delete option found.");
await clickElement(
deleteItem,
"Delete tweet"
);
await wait(1500);
const confirmBtn = document.querySelector(
"button[data-testid='confirmationSheetConfirm']"
);
if (confirmBtn) {
await clickElement(
confirmBtn,
"Confirm delete"
);
actions++;
await wait(2500);
window.scrollBy(0, 800);
return true;
}
}
else {
console.log(
"No delete option available."
);
}
// =========================
// SCROLL
// =========================
window.scrollBy(0, 800);
return true;
}
// =========================
// RUN LOOP
// =========================
async function run() {
console.log("Starting cleanup...");
console.log("Dry run:", CONFIG.dryRun);
while (
!stopped &&
actions < CONFIG.maxActions
) {
try {
await processPost();
}
catch (err) {
console.error("Error:", err);
}
await wait(CONFIG.delayMs);
}
console.log("Finished.");
console.log("Total actions:", actions);
}
run();
})();
The script will:
- Delete tweets automatically
- Remove reposts automatically
- Skip pinned tweets
- Scroll down your profile continuously
- Pause between actions to reduce rate limiting
How to Stop the Script
If you want to stop the cleanup process at any time, paste this into the console and press Enter:
window.stopTweetCleanup()
Possible Rate Limiting
X may temporarily limit actions if too many tweets are deleted too quickly.
If this happens:
- Wait a few minutes
- Refresh the page
- Run the script again
Important Notes
- This is a manual browser automation method.
- X may change its interface at any time which could break the script.
- Always test on a few tweets first before running large deletions.
- Consider exporting your X archive before deleting content permanently.
You can request your X archive here: