Skip to content

Instantly share code, notes, and snippets.

@antlionguard
Last active November 30, 2025 15:53
Show Gist options
  • Select an option

  • Save antlionguard/000e24bb039e8824fa5c58d6e324c78e to your computer and use it in GitHub Desktop.

Select an option

Save antlionguard/000e24bb039e8824fa5c58d6e324c78e to your computer and use it in GitHub Desktop.
With this script, you can remove all retweets you are retweeted on Twitter.
const timer = ms => new Promise(res => setTimeout(res, ms));
// Unretweet normally
const unretweetTweet = async (tweet) => {
await tweet.querySelector('[data-testid="unretweet"]').click();
await timer(250);
await document.querySelector('[data-testid="unretweetConfirm"]').click();
console.log('****// Unretweeted Successfully //****')
}
// Sometimes twitter shows your retweet but green retweet button is invisible and therefore you need to retweet again for make unreweet. This function is for that.
const unretweetUnretweetedTweet = async (tweet) => {
await tweet.querySelector('[data-testid="retweet"]').click();
await timer(250);
await document.querySelector('[data-testid="retweetConfirm"]').click();
console.log('****// Retweeted Successfully //****')
await timer(250);
unretweetTweet(tweet);
}
setInterval(async () =>
{
// Get all tweets
const retweetedTweetList = document.querySelectorAll('[data-testid="socialContext"]');
console.log('****// Retweeted Tweet List Collected //****')
for (const retweet of retweetedTweetList) {
const tweetWrapper = retweet.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement;
tweetWrapper.scrollIntoView();
const isRetweeted = tweetWrapper.querySelector('[data-testid="unretweet"]');
if (isRetweeted) {
console.log('****// Green Retweet Button Found - Starting "unretweetTweet" process //****')
await unretweetTweet(tweetWrapper);
} else {
console.log('****// Green Retweet Button Not Found - Starting "unretweetUnretweetedTweet" process //****')
await unretweetUnretweetedTweet(tweetWrapper);
}
await timer(2000);
}
console.log('****// List Completed //****')
console.log('****// Scrolling //****')
console.log(' ')
console.log(' ')
console.log(' ')
console.log(' ')
console.log(' ')
console.log(' ')
console.log(' ')
console.log(' ')
await window.scrollTo(0, document.body.scrollHeight);
}, 60000);
@AsifOnWeb3
Copy link

2025 may 16th, it still works. the updated command of my above, it works perfectly

@Extra107
Copy link

as of 28th July I can confirm it is still working

@niii50xi-cell
Copy link

Bo thanig

@JonRoosevelt
Copy link

as of 2025 this script does not work.

I have updated it to use button instead of div for unretweet test id as following and confirmed it works:

const timer = ms => new Promise(res => setTimeout(res, ms));

const unretweetTweet = async (tweet) => { try { await tweet.querySelector('button[data-testid="unretweet"]').click(); await timer(250); await document.querySelector('div[data-testid="unretweetConfirm"]').click(); console.log('// Unretweeted Successfully //'); } catch (error) { console.error('Error during unretweet:', error); } };

const unretweetUnretweetedTweet = async (tweet) => { try { await tweet.querySelector('div[data-testid="retweet"]').click(); await timer(250); await document.querySelector('div[data-testid="retweetConfirm"]').click(); console.log('// Retweeted Successfully //'); await timer(250); unretweetTweet(tweet); } catch (error) { console.error('Error during unretweetUnretweetedTweet:', error); } };

const processTweets = async () => { const retweetedTweetList = document.querySelectorAll('span[data-testid="socialContext"]'); console.log('// Retweeted Tweet List Collected //');

for (const retweet of retweetedTweetList) { const tweetWrapper = retweet.closest('[data-testid="tweet"]'); tweetWrapper.scrollIntoView();

const isRetweeted = tweetWrapper.querySelector('button[data-testid="unretweet"]');
if (isRetweeted) {
  console.log('****// Green Retweet Button Found - Starting "unretweetTweet" process //****');
  await unretweetTweet(tweetWrapper);
} else {
  console.log('****// Green Retweet Button Not Found - Starting "unretweetUnretweetedTweet" process //****');
  await unretweetUnretweetedTweet(tweetWrapper);
}
await timer(2000);

} console.log('// List Completed //'); console.log('// Scrolling //'); console.log(' '); console.log(' '); console.log(' '); console.log(' '); console.log(' '); console.log(' '); console.log(' '); console.log(' '); window.scrollTo(0, document.body.scrollHeight);

// Call processTweets again using requestAnimationFrame to keep the loop going requestAnimationFrame(processTweets); };

// Start the process initially processTweets();

This worked for me!

@kernelvoid17
Copy link

re-pasting @JordanWinslow 's script in a code block to fix formatting. works as of 09/2025 :)

const timer = (ms) => new Promise((res) => setTimeout(res, ms));

const unretweetTweet = async (tweet) => {
  try {
    await tweet.querySelector('button[data-testid="unretweet"]').click();
    await timer(250);
    await document.querySelector('div[data-testid="unretweetConfirm"]').click();
    console.log("// Unretweeted Successfully //");
  } catch (error) {
    console.error("Error during unretweet:", error);
  }
};

const unretweetUnretweetedTweet = async (tweet) => {
  try {
    await tweet.querySelector('div[data-testid="retweet"]').click();
    await timer(250);
    await document.querySelector('div[data-testid="retweetConfirm"]').click();
    console.log("// Retweeted Successfully //");
    await timer(250);
    unretweetTweet(tweet);
  } catch (error) {
    console.error("Error during unretweetUnretweetedTweet:", error);
  }
};

const processTweets = async () => {
  const retweetedTweetList = document.querySelectorAll(
    'span[data-testid="socialContext"]',
  );
  console.log("// Retweeted Tweet List Collected //");

  for (const retweet of retweetedTweetList) {
    const tweetWrapper = retweet.closest('[data-testid="tweet"]');
    tweetWrapper.scrollIntoView();

    const isRetweeted = tweetWrapper.querySelector(
      'button[data-testid="unretweet"]',
    );
    if (isRetweeted) {
      console.log(
        '****// Green Retweet Button Found - Starting "unretweetTweet" process //****',
      );
      await unretweetTweet(tweetWrapper);
    } else {
      console.log(
        '****// Green Retweet Button Not Found - Starting "unretweetUnretweetedTweet" process //****',
      );
      await unretweetUnretweetedTweet(tweetWrapper);
    }
    await timer(2000);
  }
  console.log("// List Completed //");
  console.log("// Scrolling //");
  console.log(" ");
  console.log(" ");
  console.log(" ");
  console.log(" ");
  console.log(" ");
  console.log(" ");
  console.log(" ");
  console.log(" ");
  window.scrollTo(0, document.body.scrollHeight);

  // Call processTweets again using requestAnimationFrame to keep the loop going
  requestAnimationFrame(processTweets);
};

// Start the process initially
processTweets();

@annsvc
Copy link

annsvc commented Nov 14, 2025

const timer = (ms) => new Promise((res) => setTimeout(res, ms));

const unretweetTweet = async (tweet) => {
  try {
    await tweet.querySelector('button[data-testid="unretweet"]').click();
    await timer(250);
    await document.querySelector('div[data-testid="unretweetConfirm"]').click();
    console.log("// Unretweeted Successfully //");
  } catch (error) {
    console.error("Error during unretweet:", error);
  }
};

const unretweetUnretweetedTweet = async (tweet) => {
  try {
    await tweet.querySelector('div[data-testid="retweet"]').click();
    await timer(250);
    await document.querySelector('div[data-testid="retweetConfirm"]').click();
    console.log("// Retweeted Successfully //");
    await timer(250);
    unretweetTweet(tweet);
  } catch (error) {
    console.error("Error during unretweetUnretweetedTweet:", error);
  }
};

const processTweets = async () => {
  const retweetedTweetList = document.querySelectorAll(
    'span[data-testid="socialContext"]',
  );
  console.log("// Retweeted Tweet List Collected //");

  for (const retweet of retweetedTweetList) {
    const tweetWrapper = retweet.closest('[data-testid="tweet"]');
    tweetWrapper.scrollIntoView();

    const isRetweeted = tweetWrapper.querySelector(
      'button[data-testid="unretweet"]',
    );
    if (isRetweeted) {
      console.log(
        '****// Green Retweet Button Found - Starting "unretweetTweet" process //****',
      );
      await unretweetTweet(tweetWrapper);
    } else {
      console.log(
        '****// Green Retweet Button Not Found - Starting "unretweetUnretweetedTweet" process //****',
      );
      await unretweetUnretweetedTweet(tweetWrapper);
    }
    await timer(2000);
  }
  console.log("// List Completed //");
  console.log("// Scrolling //");
  console.log(" ");
  console.log(" ");
  console.log(" ");
  console.log(" ");
  console.log(" ");
  console.log(" ");
  console.log(" ");
  console.log(" ");
  window.scrollTo(0, document.body.scrollHeight);

  // Call processTweets again using requestAnimationFrame to keep the loop going
  requestAnimationFrame(processTweets);
};

// Start the process initially
processTweets();

still works. thanks

@mofejo1
Copy link

mofejo1 commented Nov 30, 2025

Autonomous version

const timer = ms => new Promise(res => setTimeout(res, ms));

let totalUnretweeted = 0;
let isRunning = true;

// Stop the script by running: isRunning = false; in console
window.stopUnretweet = () => {
isRunning = false;
console.log('// Stopping script... //');
};

const unretweetBatch = async () => {
const retweetedTweetList = document.querySelectorAll('span[data-testid="socialContext"]');

if (retweetedTweetList.length === 0) {
console.log('// No retweets found, scrolling... //');
return 0;
}

let batchCount = 0;

for (const retweet of retweetedTweetList) {
if (!isRunning) break;

const tweetWrapper = retweet.closest('[data-testid="tweet"]');
if (!tweetWrapper) continue;

tweetWrapper.scrollIntoView({ behavior: 'smooth', block: 'center' });
await timer(800);

const unretweetButton = tweetWrapper.querySelector('button[data-testid="unretweet"]');

if (unretweetButton) {
  try {
    unretweetButton.click();
    await timer(500);
    const confirmButton = document.querySelector('div[data-testid="unretweetConfirm"]');
    if (confirmButton) {
      confirmButton.click();
      batchCount++;
      totalUnretweeted++;
      console.log(`✓ Unretweeted #${totalUnretweeted}`);
    }
  } catch (error) {
    console.error('Error:', error);
  }
}

await timer(3000); // 3 second delay between unretweets

}

return batchCount;
};

const autoUnretweet = async () => {
console.log('🚀 Starting autonomous unretweet script...');
console.log('⚠️ To stop at any time, type: stopUnretweet()');
console.log(' ');

while (isRunning) {
const processed = await unretweetBatch();

if (!isRunning) break;

// Scroll down to load more
console.log('📜 Scrolling to load more tweets...');
window.scrollTo(0, document.body.scrollHeight);

// Wait for new tweets to load
await timer(4000);

// If no tweets were processed, wait longer before trying again
if (processed === 0) {
  console.log('⏸️  No retweets found. Waiting 10 seconds before checking again...');
  await timer(10000);
}

}

console.log(' ');
console.log(✅ Script stopped. Total unretweeted: ${totalUnretweeted});
};

autoUnretweet();

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