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);
@antlionguard
Copy link
Author

@Rp2patilrahul
Copy link

image

@Rp2patilrahul
Copy link

It's working but slow !
take pause & start again.

Thank you.

@ElKillThisLove
Copy link

Screenshot_5
Any way to fix it?

@martgil
Copy link

martgil commented Aug 4, 2024

The above code should be simplified to the following. I'm using this to remove unwanted retweets but not retweets my own tweets.

setInterval(
    function() {
        document.querySelector('[data-testid="unretweet"]').click()
        document.querySelector('[data-testid="unretweetConfirm"]').click()
    },
    500
)

Reference: https://gist.github.com/martgil/ddd7da50712105777029bbacb5123265

@JordanWinslow
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();

@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