⚡ Free X/Twitter Automation Features
🧹 Unfollow Tools
Unfollow Everyone
100% FreeMass unfollow all accounts with one script. Perfect for a fresh start.
📋 View Full Code
// Unfollow Everyone - by nichxbt
// Go to: x.com/YOUR_USERNAME/following
(() => {
const $followButtons = '[data-testid$="-unfollow"]';
const $confirmButton = '[data-testid="confirmationSheetConfirm"]';
const retry = { count: 0, limit: 3 };
const scrollToTheBottom = () => window.scrollTo(0, document.body.scrollHeight);
const retryLimitReached = () => retry.count === retry.limit;
const addNewRetry = () => retry.count++;
const sleep = ({ seconds }) =>
new Promise((proceed) => {
console.log(`WAITING FOR ${seconds} SECONDS...`);
setTimeout(proceed, seconds * 1000);
});
const unfollowAll = async (followButtons) => {
console.log(`UNFOLLOWING ${followButtons.length} USERS...`);
await Promise.all(
followButtons.map(async (followButton) => {
followButton && followButton.click();
await sleep({ seconds: 1 });
const confirmButton = document.querySelector($confirmButton);
confirmButton && confirmButton.click();
})
);
};
const nextBatch = async () => {
scrollToTheBottom();
await sleep({ seconds: 1 });
const followButtons = Array.from(document.querySelectorAll($followButtons));
if (followButtons.length > 0) {
await unfollowAll(followButtons);
await sleep({ seconds: 2 });
return nextBatch();
} else {
addNewRetry();
}
if (retryLimitReached()) {
console.log(`✅ DONE! Reload page and re-run if any were missed.`);
} else {
await sleep({ seconds: 2 });
return nextBatch();
}
};
console.log('🚀 Starting unfollow everyone...');
nextBatch();
})();
Unfollow Non-Followers
100% FreeRemove people who don't follow you back. Clean up your following list.
📋 View Full Code
// Unfollow Non-Followers - by nichxbt
// Go to: x.com/YOUR_USERNAME/following
(() => {
const $followButtons = '[data-testid$="-unfollow"]';
const $confirmButton = '[data-testid="confirmationSheetConfirm"]';
const retry = { count: 0, limit: 3 };
const sleep = ({ seconds }) => new Promise(r => setTimeout(r, seconds * 1000));
const unfollowAll = async (followButtons) => {
console.log(`UNFOLLOWING ${followButtons.length} USERS...`);
for (const btn of followButtons) {
btn.click();
await sleep({ seconds: 1 });
document.querySelector($confirmButton)?.click();
await sleep({ seconds: 1 });
}
};
const nextBatch = async () => {
window.scrollTo(0, document.body.scrollHeight);
await sleep({ seconds: 1 });
let followButtons = Array.from(document.querySelectorAll($followButtons));
// Only unfollow those who DON'T follow back (no "Follows you" indicator)
followButtons = followButtons.filter(b =>
b.parentElement?.parentElement?.querySelector('[data-testid="userFollowIndicator"]') === null
);
if (followButtons.length > 0) {
await unfollowAll(followButtons);
await sleep({ seconds: 2 });
return nextBatch();
} else if (retry.count < retry.limit) {
retry.count++;
await sleep({ seconds: 2 });
return nextBatch();
} else {
console.log(`✅ DONE! Reload and re-run if any were missed.`);
}
};
console.log('🚀 Starting unfollow non-followers...');
nextBatch();
})();
Smart Unfollow with Logging
100% FreeUnfollow non-followers and download a list of who you unfollowed.
📋 View Full Code
// Smart Unfollow with Logging - by nichxbt
// Downloads a list of unfollowed users
(() => {
const $followButtons = '[data-testid$="-unfollow"]';
const $confirmButton = '[data-testid="confirmationSheetConfirm"]';
const unfollowedUsers = [];
const retry = { count: 0, limit: 5 };
const sleep = (seconds) => new Promise(r => setTimeout(r, seconds * 1000));
const unfollowAll = async (followButtons) => {
for (const button of followButtons) {
const usernameEl = button.closest('[data-testid="UserCell"]')?.querySelector('[dir="ltr"]');
const username = usernameEl ? usernameEl.textContent : "Unknown";
unfollowedUsers.push(username);
button.click();
await sleep(2);
document.querySelector($confirmButton)?.click();
await sleep(1);
}
};
const createDownload = () => {
const blob = new Blob([unfollowedUsers.join('\n')], { type: 'text/plain' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'unfollowed-users.txt';
a.click();
};
const nextBatch = async () => {
window.scrollTo(0, document.body.scrollHeight);
await sleep(3);
let followButtons = Array.from(document.querySelectorAll($followButtons));
followButtons = followButtons.filter(btn =>
!btn.closest('[data-testid="UserCell"]')?.querySelector('[data-testid="userFollowIndicator"]')
);
if (followButtons.length > 0) {
await unfollowAll(followButtons);
retry.count = 0;
await sleep(3);
nextBatch();
} else if (retry.count < retry.limit) {
retry.count++;
await sleep(3);
nextBatch();
} else {
console.log(`✅ DONE! Unfollowed ${unfollowedUsers.length} users.`);
if (unfollowedUsers.length > 0) createDownload();
}
};
console.log('🚀 Starting smart unfollow with logging...');
nextBatch();
})();
Detect Unfollowers
100% FreeFind out who stopped following you. Run twice to compare.
📋 View Full Code
// Detect Unfollowers - by nichxbt
// Run once to save, run again later to detect changes
(() => {
const STORAGE_KEY = 'xactions_my_followers';
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
if (!window.location.pathname.includes('/followers')) {
console.error('❌ Go to: x.com/YOUR_USERNAME/followers');
return;
}
const username = window.location.pathname.match(/^\/([^/]+)\/followers/)?.[1] || 'unknown';
const scrapeFollowers = async () => {
const followers = new Set();
let prevSize = 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(el => {
const u = el.getAttribute('href').replace('/', '').toLowerCase();
if (u && !u.includes('/')) followers.add(u);
});
console.log(` Found ${followers.size}...`);
if (followers.size === prevSize) retries++;
else { retries = 0; prevSize = followers.size; }
}
return Array.from(followers);
};
const run = async () => {
console.log(`\n🐦 Tracking @${username}\n`);
const current = await scrapeFollowers();
const prev = JSON.parse(localStorage.getItem(STORAGE_KEY) || 'null');
if (prev && prev.username === username) {
const prevSet = new Set(prev.followers);
const unfollowed = prev.followers.filter(f => !current.includes(f));
const newFollows = current.filter(f => !prevSet.has(f));
console.log(`📊 Previous: ${prev.count} | Current: ${current.length}`);
if (unfollowed.length) {
console.log(`\n🚨 UNFOLLOWED (${unfollowed.length}):`);
unfollowed.forEach(u => console.log(` @${u}`));
} else console.log('✨ No one unfollowed you!');
if (newFollows.length) {
console.log(`\n🎉 NEW (${newFollows.length}):`);
newFollows.forEach(u => console.log(` @${u}`));
}
} else {
console.log('📸 First scan! Run again later to detect changes.');
}
localStorage.setItem(STORAGE_KEY, JSON.stringify({
username, followers: current, count: current.length, timestamp: new Date().toISOString()
}));
console.log(`\n💾 Saved! Run again to check for changes.\n`);
};
run();
})();
🤖 Automation Tools
Auto Liker
100% FreeAutomatically like posts based on keywords.
📋 View Full Code
// Auto Liker - by nichxbt
// Configure KEYWORDS array below
(() => {
const OPTIONS = {
KEYWORDS: ['web3', 'crypto', 'AI'], // Edit these!
MAX_LIKES: 20,
MIN_DELAY: 2000,
MAX_DELAY: 5000,
};
const sleep = ms => new Promise(r => setTimeout(r, ms));
const randomDelay = () => sleep(OPTIONS.MIN_DELAY + Math.random() * (OPTIONS.MAX_DELAY - OPTIONS.MIN_DELAY));
let likeCount = 0;
const liked = new Set();
const matchesKeywords = (text) => {
if (!OPTIONS.KEYWORDS.length) return true;
return OPTIONS.KEYWORDS.some(kw => text.toLowerCase().includes(kw.toLowerCase()));
};
const processTweets = async () => {
for (const tweet of document.querySelectorAll('[data-testid="tweet"]')) {
if (likeCount >= OPTIONS.MAX_LIKES) {
console.log(`✅ Done! Liked ${likeCount} tweets.`);
return;
}
if (liked.has(tweet) || tweet.querySelector('[data-testid="unlike"]')) continue;
const text = tweet.querySelector('[data-testid="tweetText"]')?.textContent || '';
if (!matchesKeywords(text)) continue;
const likeBtn = tweet.querySelector('[data-testid="like"]');
if (likeBtn) {
likeBtn.click();
likeCount++;
liked.add(tweet);
console.log(`❤️ Liked #${likeCount}: "${text.substring(0, 50)}..."`);
await randomDelay();
}
}
window.scrollBy(0, 800);
await sleep(2000);
processTweets();
};
console.log(`🚀 Auto Liker | Keywords: ${OPTIONS.KEYWORDS.join(', ')}`);
processTweets();
})();
Follow Engagers
100% FreeFollow users who liked/retweeted a specific post.
📋 View Full Code
// Follow Engagers - by nichxbt
// Follow users from likes/retweets list
(() => {
const CONFIG = { MAX_FOLLOWS: 20, DELAY: 3000 };
const sleep = ms => new Promise(r => setTimeout(r, ms));
let count = 0;
const followUsers = async () => {
for (const cell of document.querySelectorAll('[data-testid="UserCell"]')) {
if (count >= CONFIG.MAX_FOLLOWS) {
console.log(`✅ Done! Followed ${count} users.`);
return;
}
const btn = cell.querySelector('[data-testid$="-follow"]');
if (!btn) continue;
const username = cell.querySelector('a[href^="/"]')?.getAttribute('href')?.replace('/', '');
btn.click();
count++;
console.log(`✅ Followed @${username} (${count}/${CONFIG.MAX_FOLLOWS})`);
await sleep(CONFIG.DELAY);
}
window.scrollBy(0, 500);
await sleep(2000);
followUsers();
};
console.log('🚀 Starting Follow Engagers...');
followUsers();
})();
Keyword Follow
100% FreeSearch for keywords and follow relevant users.
📋 View Full Code
// Keyword Follow - by nichxbt
// Follow users from search results
(() => {
const CONFIG = { MAX_FOLLOWS: 30, DELAY: 3000, MUST_HAVE_BIO: true };
const sleep = ms => new Promise(r => setTimeout(r, ms));
let count = 0;
const followUsers = async () => {
for (const cell of document.querySelectorAll('[data-testid="UserCell"]')) {
if (count >= CONFIG.MAX_FOLLOWS) {
console.log(`✅ Done! Followed ${count} users.`);
return;
}
const btn = cell.querySelector('[data-testid$="-follow"]');
if (!btn) continue;
if (CONFIG.MUST_HAVE_BIO) {
const bio = cell.querySelector('[data-testid="UserDescription"]');
if (!bio || !bio.textContent.trim()) continue;
}
const username = cell.querySelector('a[href^="/"]')?.getAttribute('href')?.replace('/', '');
btn.click();
count++;
console.log(`✅ Followed @${username} (${count}/${CONFIG.MAX_FOLLOWS})`);
await sleep(CONFIG.DELAY);
}
window.scrollBy(0, 500);
await sleep(2000);
followUsers();
};
console.log('🚀 Keyword Follow | Search "People" tab first!');
followUsers();
})();
👀 Monitoring Tools
Monitor Any Account
100% FreeTrack follows/unfollows on any public account.
📋 View Full Code
// Monitor Any Account - by nichxbt
// Track changes on any public account
(() => {
const sleep = ms => new Promise(r => setTimeout(r, ms));
const path = window.location.pathname;
const isFollowers = path.includes('/followers');
const isFollowing = path.includes('/following');
if (!isFollowers && !isFollowing) {
console.error('❌ Go to: x.com/username/followers or /following');
return;
}
const type = isFollowers ? 'followers' : 'following';
const target = path.split('/')[1].toLowerCase();
const key = `xactions_${target}_${type}`;
const scrape = async () => {
const users = new Set();
let prev = 0, retries = 0;
console.log(`🔍 Scanning @${target}'s ${type}...`);
while (retries < 5) {
window.scrollTo(0, document.body.scrollHeight);
await sleep(1500);
document.querySelectorAll('[data-testid="UserCell"] a[href^="/"]').forEach(el => {
const u = el.getAttribute('href').replace('/', '').split('/')[0].toLowerCase();
if (u && u !== target && !u.includes('?')) users.add(u);
});
if (users.size === prev) retries++;
else { retries = 0; prev = users.size; }
}
return Array.from(users);
};
const run = async () => {
const current = await scrape();
const prev = JSON.parse(localStorage.getItem(key) || 'null');
if (prev) {
const removed = prev.users.filter(u => !current.includes(u));
const added = current.filter(u => !prev.users.includes(u));
console.log(`📊 Previous: ${prev.users.length} | Current: ${current.length}`);
if (removed.length) console.log(`🚨 REMOVED: ${removed.map(u => '@' + u).join(', ')}`);
if (added.length) console.log(`🎉 ADDED: ${added.map(u => '@' + u).join(', ')}`);
if (!removed.length && !added.length) console.log('✨ No changes!');
} else {
console.log('📸 First scan! Run again to detect changes.');
}
localStorage.setItem(key, JSON.stringify({ users: current, timestamp: new Date().toISOString() }));
console.log('💾 Saved!');
};
run();
})();
New Follower Alerts
100% FreeTrack your new followers over time.
📋 View Full Code
// New Follower Alerts - by nichxbt
(() => {
const STORAGE_KEY = 'xactions_new_followers';
const sleep = ms => new Promise(r => setTimeout(r, ms));
if (!window.location.pathname.includes('/followers')) {
console.error('❌ Go to your /followers page!');
return;
}
const username = window.location.pathname.split('/')[1];
const scrape = async () => {
const followers = new Map();
let prev = 0, retries = 0;
while (retries < 5) {
window.scrollTo(0, document.body.scrollHeight);
await sleep(1500);
document.querySelectorAll('[data-testid="UserCell"]').forEach(cell => {
const link = cell.querySelector('a[href^="/"]');
const name = cell.querySelector('[dir="ltr"] > span')?.textContent;
if (link) {
const u = link.getAttribute('href').replace('/', '').split('/')[0].toLowerCase();
if (u && u !== username.toLowerCase()) followers.set(u, name || u);
}
});
if (followers.size === prev) retries++;
else { retries = 0; prev = followers.size; }
}
return followers;
};
const run = async () => {
console.log(`🎉 New Followers Tracker for @${username}`);
const current = await scrape();
const prev = JSON.parse(localStorage.getItem(STORAGE_KEY) || 'null');
if (prev && prev.username.toLowerCase() === username.toLowerCase()) {
const prevUsers = new Set(Object.keys(prev.followers));
const newFollowers = [];
current.forEach((name, user) => {
if (!prevUsers.has(user)) newFollowers.push({ user, name });
});
const change = current.size - prev.count;
console.log(`📊 Previous: ${prev.count} | Current: ${current.size} (${change >= 0 ? '+' : ''}${change})`);
if (newFollowers.length) {
console.log(`🎉 NEW FOLLOWERS (${newFollowers.length}):`);
newFollowers.forEach(f => console.log(` ${f.name} (@${f.user})`));
}
} else {
console.log('📸 First scan! Run again to see new followers.');
}
localStorage.setItem(STORAGE_KEY, JSON.stringify({
username, followers: Object.fromEntries(current), count: current.size, timestamp: new Date().toISOString()
}));
console.log('💾 Saved!');
};
run();
})();
🏠 Community Tools
Leave All Communities
100% FreeAutomatically leave all X Communities you've joined.
📋 View Full Code
// Leave All Communities - by nichxbt
// Go to: x.com/YOUR_USERNAME/communities
(() => {
const $communityLinks = 'a[href^="/i/communities/"]';
const $joinedButton = 'button[aria-label^="Joined"]';
const $confirmButton = '[data-testid="confirmationSheetConfirm"]';
const $communitiesNav = 'a[aria-label="Communities"]';
const getLeft = () => JSON.parse(sessionStorage.getItem('xactions_left') || '[]');
const markLeft = (id) => {
const left = getLeft();
if (!left.includes(id)) {
left.push(id);
sessionStorage.setItem('xactions_left', JSON.stringify(left));
}
};
const sleep = ms => new Promise(r => setTimeout(r, ms));
const run = async () => {
console.log(`🚀 Left ${getLeft().length} communities so far...`);
await sleep(1500);
const joinedBtn = document.querySelector($joinedButton);
if (joinedBtn) {
const id = window.location.href.match(/\/i\/communities\/(\d+)/)?.[1];
console.log(`📍 Leaving community ${id}...`);
joinedBtn.click();
await sleep(1000);
document.querySelector($confirmButton)?.click();
if (id) markLeft(id);
await sleep(1500);
document.querySelector($communitiesNav)?.click();
await sleep(2500);
return run();
}
const left = getLeft();
for (const link of document.querySelectorAll($communityLinks)) {
const id = link.href.match(/\/i\/communities\/(\d+)/)?.[1];
if (id && !left.includes(id)) {
console.log(`🏠 Entering community ${id}...`);
link.click();
await sleep(2500);
return run();
}
}
console.log(`🎉 DONE! Left ${getLeft().length} communities.`);
sessionStorage.removeItem('xactions_left');
};
run();
})();
📥 Scraping Tools
Video Downloader
100% FreeDownload any video from X/Twitter posts.
📋 View Full Code
// X Video Downloader - by nichxbt
(() => {
const findVideos = () => {
const videos = [];
const html = document.documentElement.innerHTML;
const patterns = [
/https:\/\/video\.twimg\.com\/[^"'\s]+\.mp4[^"'\s]*/g,
/https:\/\/[^"'\s]*\/amplify_video[^"'\s]*\.mp4[^"'\s]*/g,
/https:\/\/[^"'\s]*\/ext_tw_video[^"'\s]*\.mp4[^"'\s]*/g,
];
patterns.forEach(pattern => {
(html.match(pattern) || []).forEach(url => {
let clean = url.replace(/\\u002F/g, '/').replace(/\\/g, '').split('"')[0].split("'")[0];
if (clean.includes('.mp4')) {
const quality = clean.match(/\/(\d+x\d+)\//)?.[1] || 'unknown';
videos.push({ url: clean, quality });
}
});
});
// Deduplicate
const seen = new Set();
return videos.filter(v => {
const key = v.url.split('?')[0];
if (seen.has(key)) return false;
seen.add(key);
return true;
});
};
const videos = findVideos();
if (!videos.length) {
console.log('❌ No videos found. Make sure you are on a tweet with video.');
return;
}
videos.sort((a, b) => {
const res = q => parseInt(q.match(/(\d+)x(\d+)/)?.[2] || 0);
return res(b.quality) - res(a.quality);
});
console.log(`🎬 Found ${videos.length} video(s):`);
videos.forEach((v, i) => console.log(`${i + 1}. [${v.quality}] ${v.url.substring(0, 80)}...`));
const best = videos[0];
console.log(`\n📥 Downloading best quality (${best.quality})...`);
const a = document.createElement('a');
a.href = best.url;
a.download = `twitter-video-${Date.now()}.mp4`;
a.target = '_blank';
a.click();
})();
🤖 AI & MCP Integration
MCP Server for AI Agents
100% FreeConnect Claude Desktop or any MCP client to control X/Twitter.
📋 View Setup Instructions
# Install XActions globally
npm install -g xactions
# Or run directly with npx
npx xactions mcp
# Add to Claude Desktop config (~/.claude/config.json):
{
"mcpServers": {
"xactions": {
"command": "npx",
"args": ["xactions", "mcp"],
"env": {
"X_AUTH_TOKEN": "your_auth_token_here"
}
}
}
}
# Available MCP Tools:
# - scrape_profile: Get profile info
# - scrape_followers: Get followers list
# - scrape_following: Get following list
# - scrape_tweets: Get recent tweets
# - unfollow_everyone: Mass unfollow
# - unfollow_non_followers: Smart unfollow
# - detect_unfollowers: Track unfollows
# - auto_like: Like posts by keyword
# - follow_users: Follow user list
# - download_video: Download tweet videos
❓ FAQ
Is this safe to use?
Yes! Browser scripts run entirely in your browser and just automate clicking. Nothing leaves your computer.
Will I get banned?
Scripts include rate limiting, but aggressive automation can trigger spam detection. Use responsibly!
Why is this free?
XActions is 100% open source. Support us by starring on GitHub!