๐ญ Monitor Any Account
Track follows and unfollows on any public X account over time. Great for competitor analysis or tracking influential accounts.
Step 1: Go to any account's followers or following page
Navigate to x.com/USERNAME/followers or x.com/USERNAME/following
Step 2: Paste the Monitor Account script
// Monitor Any Account - by nichxbt
// https://github.com/nirholas/XActions
// Track follows/unfollows on ANY public X account
// Go to x.com/USERNAME/followers or /following
(() => {
const STORAGE_PREFIX = 'xactions_monitor_';
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('โ Please go to a followers or following page!');
console.log('Example: x.com/elonmusk/followers');
return;
}
const pageType = isFollowers ? 'followers' : 'following';
const targetUser = path.split('/')[1].toLowerCase();
const storageKey = `${STORAGE_PREFIX}${targetUser}_${pageType}`;
console.log(`๐ญ Monitoring @${targetUser}'s ${pageType}...\n`);
const scrapeUsers = async () => {
const users = new Set();
let prevSize = 0;
let retries = 0;
while (retries < 5) {
window.scrollTo(0, document.body.scrollHeight);
await sleep(1500);
document.querySelectorAll('[data-testid="UserCell"]').forEach(cell => {
const links = cell.querySelectorAll('a[href^="/"]');
links.forEach(link => {
const href = link.getAttribute('href');
if (href?.startsWith('/') && !href.includes('/status/')) {
const username = href.replace('/', '').split('/')[0].toLowerCase();
if (username && username !== targetUser && !username.includes('?')) {
users.add(username);
}
}
});
});
console.log(`Found ${users.size} accounts...`);
if (users.size === prevSize) retries++;
else { retries = 0; prevSize = users.size; }
}
return Array.from(users);
};
const loadPrevious = () => {
try {
const data = localStorage.getItem(storageKey);
return data ? JSON.parse(data) : null;
} catch { return null; }
};
const saveData = (users) => {
const data = {
target: targetUser,
type: pageType,
users,
timestamp: new Date().toISOString(),
count: users.length
};
localStorage.setItem(storageKey, JSON.stringify(data));
return data;
};
const compare = (previous, current) => {
const prevSet = new Set(previous);
const currSet = new Set(current);
return {
removed: previous.filter(u => !currSet.has(u)),
added: current.filter(u => !prevSet.has(u))
};
};
const downloadList = (list, filename) => {
if (list.length === 0) return;
const blob = new Blob([list.map(u => `@${u}`).join('\n')], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
scrapeUsers().then(currentUsers => {
console.log(`\nโ
Found ${currentUsers.length} accounts\n`);
const previous = loadPrevious();
if (previous) {
const prevDate = new Date(previous.timestamp).toLocaleString();
console.log(`๐ Comparing with snapshot from ${prevDate}`);
console.log(`Previous: ${previous.count} | Current: ${currentUsers.length}\n`);
const { removed, added } = compare(previous.users, currentUsers);
if (pageType === 'followers') {
if (removed.length > 0) {
console.log(`๐จ ${removed.length} UNFOLLOWED @${targetUser}:`);
removed.forEach(u => console.log(` @${u}`));
downloadList(removed, `${targetUser}-lost-followers.txt`);
}
if (added.length > 0) {
console.log(`\n๐ ${added.length} NEW FOLLOWERS:`);
added.forEach(u => console.log(` @${u}`));
}
} else {
if (removed.length > 0) {
console.log(`๐ @${targetUser} UNFOLLOWED ${removed.length}:`);
removed.forEach(u => console.log(` @${u}`));
}
if (added.length > 0) {
console.log(`\nโ @${targetUser} NOW FOLLOWS ${added.length} NEW:`);
added.forEach(u => console.log(` @${u}`));
}
}
if (removed.length === 0 && added.length === 0) {
console.log('โจ No changes since last check!');
}
} else {
console.log('๐ธ First scan! Saving snapshot...');
console.log('Run again later to see changes.');
}
saveData(currentUsers);
console.log(`\n๐พ Snapshot saved. Run again anytime!\n`);
});
})();
๐ก How It Works
The script saves a snapshot of the account's followers/following list in your browser's localStorage. When you run it again, it compares with the previous snapshot to show who was added or removed.
๐ New Follower Alerts
Track your new followers with display names and get ready-to-use welcome message templates.
Step 1: Go to your followers page
Navigate to x.com/YOUR_USERNAME/followers
Step 2: Paste the New Followers Alert script
// New Followers Alert - by nichxbt
// https://github.com/nirholas/XActions
// Track new followers + get welcome templates
// Go to x.com/YOUR_USERNAME/followers
(() => {
const STORAGE_KEY = 'xactions_new_followers';
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
if (!window.location.pathname.includes('/followers')) {
console.error('โ Please go to your FOLLOWERS page!');
return;
}
const username = window.location.pathname.split('/')[1];
console.log(`๐ Tracking new followers for @${username}...\n`);
const scrapeFollowers = async () => {
const followers = new Map();
let prevSize = 0;
let 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 nameEl = cell.querySelector('[dir="ltr"] > span');
if (link) {
const user = link.getAttribute('href').replace('/', '').split('/')[0].toLowerCase();
const displayName = nameEl?.textContent || user;
if (user && user !== username.toLowerCase()) {
followers.set(user, displayName);
}
}
});
if (followers.size === prevSize) retries++;
else { retries = 0; prevSize = followers.size; }
console.log(`Found ${followers.size} followers...`);
}
return followers;
};
const loadPrevious = () => {
try {
const data = localStorage.getItem(STORAGE_KEY);
return data ? JSON.parse(data) : null;
} catch { return null; }
};
const saveFollowers = (followersMap) => {
const data = {
username,
followers: Object.fromEntries(followersMap),
timestamp: new Date().toISOString(),
count: followersMap.size
};
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
return data;
};
scrapeFollowers().then(currentFollowers => {
console.log(`\nโ
Total followers: ${currentFollowers.size}\n`);
const previous = loadPrevious();
if (previous && previous.username.toLowerCase() === username.toLowerCase()) {
const prevUsers = new Set(Object.keys(previous.followers));
const newFollowers = [];
currentFollowers.forEach((displayName, user) => {
if (!prevUsers.has(user)) {
newFollowers.push({ user, displayName });
}
});
const prevDate = new Date(previous.timestamp).toLocaleString();
console.log(`๐ Comparing with ${prevDate}`);
console.log(`Previous: ${previous.count} | Current: ${currentFollowers.size}`);
console.log(`Net change: ${currentFollowers.size - previous.count > 0 ? '+' : ''}${currentFollowers.size - previous.count}\n`);
if (newFollowers.length > 0) {
console.log(`๐ ${newFollowers.length} NEW FOLLOWERS:\n`);
newFollowers.forEach((f, i) => {
console.log(`${i + 1}. ${f.displayName} (@${f.user})`);
console.log(` https://x.com/${f.user}`);
});
console.log('\n๐ Welcome templates (copy & customize):');
console.log('โ'.repeat(50));
newFollowers.slice(0, 5).forEach(f => {
console.log(`Hey @${f.user}, thanks for the follow! ๐`);
});
console.log('โ'.repeat(50));
} else {
console.log('๐ญ No new followers since last check.');
}
// Check for unfollowers
const currentUsers = new Set(currentFollowers.keys());
const lost = Object.keys(previous.followers).filter(u => !currentUsers.has(u));
if (lost.length > 0) {
console.log(`\n๐ ${lost.length} unfollowed you:`);
lost.forEach(u => console.log(` @${u}`));
}
} else {
console.log('๐ธ First scan! Saving your followers...');
console.log('Run again later to see new followers!');
}
saveFollowers(currentFollowers);
console.log('\n๐พ Snapshot saved!\n');
});
})();
๐จ Detect Unfollowers
Find out exactly who unfollowed you since your last check. Downloads a list of unfollowers.
Step 1: Go to your followers page
Navigate to x.com/YOUR_USERNAME/followers
Step 2: Paste the Detect Unfollowers script
// Detect Unfollowers - by nichxbt
// https://github.com/nirholas/XActions
// Find who unfollowed you
// Go to x.com/YOUR_USERNAME/followers
(() => {
const STORAGE_KEY = 'xactions_my_followers';
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
if (!window.location.pathname.includes('/followers')) {
console.error('โ Please go to your FOLLOWERS page!');
console.log('๐ Go to: x.com/YOUR_USERNAME/followers');
return;
}
const username = window.location.pathname.match(/^\/([^/]+)\/followers/)?.[1] || 'unknown';
console.log(`๐ Detecting unfollowers for @${username}...\n`);
const scrapeFollowers = async () => {
const followers = new Set();
let prevSize = 0;
let 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^="/"]');
if (link) {
const href = link.getAttribute('href');
const user = href.replace('/', '').toLowerCase();
if (user && !user.includes('/')) {
followers.add(user);
}
}
});
console.log(`Found ${followers.size} followers...`);
if (followers.size === prevSize) retries++;
else { retries = 0; prevSize = followers.size; }
}
return Array.from(followers);
};
const loadPrevious = () => {
try {
const data = localStorage.getItem(STORAGE_KEY);
return data ? JSON.parse(data) : null;
} catch { return null; }
};
const saveFollowers = (followers) => {
const data = {
username,
followers,
timestamp: new Date().toISOString(),
count: followers.length
};
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
return data;
};
scrapeFollowers().then(currentFollowers => {
console.log(`\nโ
Found ${currentFollowers.length} followers\n`);
const previous = loadPrevious();
if (previous && previous.username === username) {
const prevDate = new Date(previous.timestamp).toLocaleString();
console.log(`๐ Comparing with snapshot from ${prevDate}`);
console.log(`Previous: ${previous.count} | Current: ${currentFollowers.length}\n`);
const currSet = new Set(currentFollowers);
const unfollowed = previous.followers.filter(f => !currSet.has(f.toLowerCase()));
const newFollowers = currentFollowers.filter(f => !previous.followers.includes(f));
if (unfollowed.length > 0) {
console.log(`๐จ ${unfollowed.length} PEOPLE UNFOLLOWED YOU:\n`);
unfollowed.forEach((u, i) => {
console.log(`${i + 1}. @${u} โ https://x.com/${u}`);
});
// Download list
const blob = new Blob([unfollowed.join('\n')], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `unfollowers-${new Date().toISOString().split('T')[0]}.txt`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
console.log('\n๐ฅ Downloaded unfollowers list!');
} else {
console.log('โจ No one unfollowed you since last check!');
}
if (newFollowers.length > 0) {
console.log(`\n๐ ${newFollowers.length} NEW FOLLOWERS:`);
newFollowers.forEach((u, i) => console.log(`${i + 1}. @${u}`));
}
} else {
console.log('๐ธ First scan! Saving snapshot...');
console.log('Run again later to detect unfollowers.');
}
saveFollowers(currentFollowers);
console.log(`\n๐พ Snapshot saved!\n`);
});
})();
๐ก Pro Tip
Run this script regularly (daily or weekly) to catch unfollowers quickly. The more frequently you run it, the more accurate your tracking will be.