Skip to content

Instantly share code, notes, and snippets.

@jatinkrmalik
Created July 13, 2025 20:30
Show Gist options
  • Save jatinkrmalik/1f3b6bcd685d00350f41c75a879b4d66 to your computer and use it in GitHub Desktop.
Save jatinkrmalik/1f3b6bcd685d00350f41c75a879b4d66 to your computer and use it in GitHub Desktop.
Client-side browser script that celetes tweets from your profile posted after a specific date and time while respecting rate limiter
/**
* @description Deletes tweets from your profile posted after a specific date and time.
* @instructions Paste this entire script into your browser's developer console
* on your Twitter/X profile page (e.g., https://x.com/your-username)
* and press Enter.
* DISCLAIMER: USE AT YOUR OWN RISK. YOUR ACCOUNT MIGHT GET FLAGGED/SUSPENDED. I BEAR NO RESPONSIBILITY
*/
async function deleteSpamTweets() {
// --- CONFIGURATION ---
// Set the cutoff date and time. Tweets posted AFTER this time will be deleted.
// Format: YYYY-MM-DDTHH:MM:SS
const CUTOFF_DATE = new Date('2025-06-27T05:00:00');
// Set a random delay between actions to avoid rate limits.
// Values are in milliseconds (e.g., 5000 = 5 seconds).
const MIN_DELAY_MS = 5000; // 5 seconds
const MAX_DELAY_MS = 10000; // 10 seconds
// --- SCRIPT LOGIC (No need to edit below this line) ---
console.log(`Starting tweet deletion process.`);
console.log(`Will delete tweets posted after: ${CUTOFF_DATE.toLocaleString()}`);
// Helper function for creating a randomized delay
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const randomDelay = () => Math.floor(Math.random() * (MAX_DELAY_MS - MIN_DELAY_MS + 1)) + MIN_DELAY_MS;
let tweetsDeleted = 0;
// Main loop to continuously find and delete tweets
while (true) {
// Find all tweet articles currently visible on the page
const articles = Array.from(document.querySelectorAll('article[data-testid="tweet"]'));
if (articles.length === 0) {
console.log("No more tweets found on the page. Scrolling down to load more...");
window.scrollTo(0, document.body.scrollHeight);
await sleep(3000); // Wait for new tweets to load
// Check again after scroll; if still no tweets, we might be done.
if (document.querySelectorAll('article[data-testid="tweet"]').length === 0) {
console.log("Finished: No more tweets could be found.");
break;
}
continue; // Restart the loop to process newly loaded tweets
}
let tweetsFoundInBatch = 0;
for (const article of articles) {
// Find the timestamp of the tweet
const timeElement = article.querySelector('time');
if (!timeElement || !timeElement.dateTime) {
continue; // Skip if tweet has no timestamp
}
const tweetDate = new Date(timeElement.dateTime);
// Check if the tweet is new enough to be deleted
if (tweetDate > CUTOFF_DATE) {
tweetsFoundInBatch++;
console.log(`[TARGET FOUND] Tweet from ${tweetDate.toLocaleString()}. Preparing to delete.`);
// 1. Click the "More" button (...)
const moreButton = article.querySelector('[data-testid="caret"]');
if (!moreButton) {
console.error("Could not find the 'More' button for a target tweet. Skipping.");
continue;
}
moreButton.click();
await sleep(1000); // Wait for the dropdown menu to appear
// 2. Click the "Delete" option from the menu
const menuItems = document.querySelectorAll('div[role="menuitem"]');
const deleteOption = Array.from(menuItems).find(item => item.textContent.includes('Delete'));
if (!deleteOption) {
console.error("Could not find the 'Delete' option in the menu. Skipping.");
// Try to close the menu by clicking the body
document.body.click();
continue;
}
deleteOption.click();
await sleep(1000); // Wait for the confirmation dialog
// 3. Click the final "Delete" confirmation button
const confirmButton = document.querySelector('[data-testid="confirmationSheetConfirm"]');
if (!confirmButton) {
console.error("Could not find the final confirmation button. Skipping.");
document.body.click();
continue;
}
confirmButton.click();
tweetsDeleted++;
console.log(`[SUCCESS] Tweet deleted. Total deleted so far: ${tweetsDeleted}`);
// Wait for a random period before processing the next tweet
const delay = randomDelay();
console.log(`Waiting for ${delay / 1000} seconds to avoid rate limits...`);
await sleep(delay);
} else {
// This tweet is older than the cutoff, so we assume all subsequent tweets are also old.
console.log(`Found a tweet from ${tweetDate.toLocaleString()}, which is before the cutoff. Assuming all older tweets are safe.`);
console.log(`Process finished. Total tweets deleted: ${tweetsDeleted}.`);
return; // Exit the entire function
}
}
// If we processed a batch but didn't find any tweets to delete, it means we've reached older content.
if (tweetsFoundInBatch === 0) {
console.log("No more tweets found after the cutoff date. Process complete.");
break;
}
}
}
// Run the function
deleteSpamTweets();
@zessu
Copy link

zessu commented Jul 21, 2025

<3 thanks man

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