⚠️ Educational Use Only: XActions demonstrates browser automation for educational purposes.
Not affiliated with X Corp.
Learn more
⚡
Clean Up Your X Following List
Free, open-source browser scripts. No apps, no sign-ins, no data collection.
✨ What can it do?
Automatically unfollow everyone who doesn't follow you back.
Start fresh with a completely clean following list.
Find out who stopped following you recently.
Watch any public account's followers for changes.
Like posts based on keywords or from specific users.
All-in-one automation: follow, like, and smart unfollow.
🚀 How to use
Go to your Following page
Open X (Twitter) and navigate to your Following list
twitter.com/YOUR_USERNAME/following
Open Developer Console
Windows/Linux: Ctrl + Shift + J
Mac: Cmd + Option + J
Copy the script below
Click the "Copy" button to copy the script to your clipboard
Paste and press Enter
Paste the script into the console and press Enter. Watch it work!
📋 Scripts
(() => {
const $followButtons = '[data-testid$="-unfollow"]';
const $confirmButton = '[data-testid="confirmationSheetConfirm"]';
const retry = { count: 0, limit: 3 };
const sleep = (s) => new Promise(r => setTimeout(r, s * 1000));
const scroll = () => window.scrollTo(0, document.body.scrollHeight);
const unfollowAll = async (buttons) => {
for (const btn of buttons) {
btn.click();
await sleep(1);
document.querySelector($confirmButton)?.click();
await sleep(0.5);
}
};
const run = async () => {
scroll();
await sleep(1);
let buttons = [...document.querySelectorAll($followButtons)]
.filter(b => !b.closest('[data-testid="UserCell"]')
?.querySelector('[data-testid="userFollowIndicator"]'));
if (buttons.length) {
console.log(`Unfollowing ${buttons.length} users...`);
await unfollowAll(buttons);
retry.count = 0;
await sleep(2);
return run();
}
if (++retry.count < retry.limit) {
await sleep(2);
return run();
}
console.log('✅ Done! Reload and run again if any were missed.');
};
run();
})();
📍 Use on: twitter.com/YOUR_USERNAME/following
(() => {
const KEY = 'xactions_followers';
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
const scrape = async () => {
const users = new Set();
let prev = 0, retries = 0;
console.log('🔍 Scanning followers...');
while (retries < 5) {
window.scrollTo(0, document.body.scrollHeight);
await sleep(1500);
document.querySelectorAll('[data-testid="UserCell"] a[href^="/"]')
.forEach(a => {
const u = a.href.split('/')[3]?.toLowerCase();
if (u && !u.includes('?')) users.add(u);
});
console.log(` Found ${users.size}...`);
if (users.size === prev) retries++;
else { retries = 0; prev = users.size; }
}
return [...users];
};
const run = async () => {
const current = await scrape();
const saved = localStorage.getItem(KEY);
if (saved) {
const { followers: old, time } = JSON.parse(saved);
const oldSet = new Set(old);
const gone = old.filter(u => !current.includes(u));
const newF = current.filter(u => !oldSet.has(u));
console.log(`\n📊 Since ${new Date(time).toLocaleString()}:`);
if (gone.length) {
console.log(`\n🚨 UNFOLLOWED YOU (${gone.length}):`);
gone.forEach(u => console.log(` @${u}`));
}
if (newF.length) {
console.log(`\n🎉 NEW FOLLOWERS (${newF.length}):`);
newF.forEach(u => console.log(` @${u}`));
}
if (!gone.length && !newF.length) console.log('✨ No changes!');
} else {
console.log('📸 First scan — saving snapshot...');
}
localStorage.setItem(KEY, JSON.stringify({
followers: current, time: Date.now()
}));
console.log(`\n💾 Saved ${current.length} followers. Run again later!`);
};
run();
})();
📍 Use on: twitter.com/YOUR_USERNAME/followers
(() => {
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
const path = location.pathname;
const type = path.includes('/followers') ? 'followers' : 'following';
const user = path.split('/')[1].toLowerCase();
const KEY = `xactions_${user}_${type}`;
const scrape = async () => {
const users = new Set();
let prev = 0, retries = 0;
console.log(`🔍 Scanning @${user}'s ${type}...`);
while (retries < 5) {
window.scrollTo(0, document.body.scrollHeight);
await sleep(1500);
document.querySelectorAll('[data-testid="UserCell"] a[href^="/"]')
.forEach(a => {
const u = a.href.split('/')[3]?.toLowerCase();
if (u && u !== user && !u.includes('?')) users.add(u);
});
if (users.size === prev) retries++;
else { retries = 0; prev = users.size; }
}
return [...users];
};
const run = async () => {
const current = await scrape();
console.log(`✅ Found ${current.length} accounts`);
const saved = localStorage.getItem(KEY);
if (saved) {
const { users: old, time } = JSON.parse(saved);
const oldSet = new Set(old);
const removed = old.filter(u => !current.includes(u));
const added = current.filter(u => !oldSet.has(u));
console.log(`\n📊 Changes since ${new Date(time).toLocaleString()}:`);
if (removed.length) console.log(`👋 Gone: ${removed.map(u=>'@'+u).join(', ')}`);
if (added.length) console.log(`➕ New: ${added.map(u=>'@'+u).join(', ')}`);
if (!removed.length && !added.length) console.log('✨ No changes!');
} else {
console.log('📸 First scan — run again later to see changes.');
}
localStorage.setItem(KEY, JSON.stringify({ users: current, time: Date.now() }));
};
run();
})();
📍 Use on: twitter.com/ANYONE/followers or /following
🔒 Safe & Private
✅
100% Local
Runs entirely in your browser. Nothing sent anywhere.
✅
Open Source
All code visible on GitHub. No hidden functionality.
✅
No Sign-in
Never asks for your password or credentials.
✅
Just Clicks
Only automates the same clicks you'd do manually.