๐ŸŽ‰ 100% Free & Open Source โ€” No API fees, no subscriptions!

๐Ÿ‘‹ Unfollow Tutorials

Complete guides for mass unfollowing on X/Twitter

๐Ÿš€ 1. Unfollow Everyone

๐Ÿ“‹ What This Does

Mass unfollows ALL accounts you're currently following. This is the nuclear option - use it when you want to start fresh with a clean following list.

๐ŸŽฏ Quick Start

  1. Go to x.com/YOUR_USERNAME/following
  2. Open DevTools with F12 (Windows/Linux) or Cmd+Option+J (Mac)
  3. Click the "Console" tab
  4. Paste the code below and press Enter
unfollow-everyone.js
// Unfollow everyone on X
// by nichxbt - https://github.com/nirholas/XActions
(() => {
  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));
    const followButtonsWereFound = followButtons.length > 0;

    if (followButtonsWereFound) {
      await unfollowAll(followButtons);
      await sleep({ seconds: 2 });
      return nextBatch();
    } else {
      addNewRetry();
    }

    if (retryLimitReached()) {
      console.log(`NO ACCOUNTS FOUND, SO I THINK WE'RE DONE`);
      console.log(`RELOAD PAGE AND RE-RUN SCRIPT IF ANY WERE MISSED`);
    } else {
      await sleep({ seconds: 2 });
      return nextBatch();
    }
  };

  nextBatch();
})();
โš ๏ธ Warning

This will unfollow EVERYONE. There's no undo button. Make sure you really want to do this!

โš™๏ธ How It Works

  • Scrolls down your following list to load more accounts
  • Finds all "Following" buttons and clicks them
  • Automatically confirms each unfollow
  • Repeats until no more accounts are found
  • Retries 3 times to catch any stragglers

๐Ÿ‘ฅ 2. Unfollow Non-Followers Only

๐Ÿ“‹ What This Does

Unfollows only people who don't follow you back. Keeps mutual follows intact. Perfect for cleaning up your following list without losing your real connections.

๐ŸŽฏ Quick Start

  1. Go to x.com/YOUR_USERNAME/following
  2. Open DevTools (F12 or Cmd+Option+J)
  3. Paste the code below and press Enter
unfollow-non-followers.js
// Unfollow people who don't follow you back
// by nichxbt - https://github.com/nirholas/XActions
(() => {
  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 });

    let followButtons = Array.from(document.querySelectorAll($followButtons));
    // Filter out users who follow you back (they have the "Follows you" indicator)
    followButtons = followButtons.filter(b => 
      b.parentElement?.parentElement?.querySelector('[data-testid="userFollowIndicator"]') === null
    );
    const followButtonsWereFound = followButtons.length > 0;

    if (followButtonsWereFound) {
      await unfollowAll(followButtons);
      await sleep({ seconds: 2 });
      return nextBatch();
    } else {
      addNewRetry();
    }

    if (retryLimitReached()) {
      console.log(`NO ACCOUNTS FOUND, SO I THINK WE'RE DONE`);
      console.log(`RELOAD PAGE AND RE-RUN SCRIPT IF ANY WERE MISSED`);
    } else {
      await sleep({ seconds: 2 });
      return nextBatch();
    }
  };

  nextBatch();
})();
๐Ÿ’ก How It Detects Mutuals

X shows a "Follows you" badge on users who follow you back. The script looks for [data-testid="userFollowIndicator"] and skips those users.

๐Ÿง  3. Smart Unfollow with Whitelist

๐Ÿ“‹ What This Does

Unfollows non-followers BUT lets you keep specific accounts you want to keep following (like celebrities, brands, or news accounts that never follow back).

๐ŸŽฏ Quick Start

  1. Edit the WHITELIST array with usernames you want to keep
  2. Go to x.com/YOUR_USERNAME/following
  3. Open DevTools and paste the code
smart-unfollow.js
// Smart Unfollow - Non-followers with whitelist
// by nichxbt - https://github.com/nirholas/XActions
(() => {
  // โฌ‡๏ธ ADD USERNAMES TO KEEP (without @)
  const WHITELIST = [
    'elonmusk',
    'naval',
    'paulg',
    // Add more usernames here...
  ];
  
  const $followButtons = '[data-testid$="-unfollow"]';
  const $confirmButton = '[data-testid="confirmationSheetConfirm"]';
  const $userCell = '[data-testid="UserCell"]';

  let unfollowedCount = 0;
  let skippedCount = 0;
  let retry = { count: 0, limit: 3 };

  const sleep = (ms) => new Promise(r => setTimeout(r, ms));
  const scrollToBottom = () => window.scrollTo(0, document.body.scrollHeight);

  const getUsernameFromCell = (cell) => {
    const link = cell.querySelector('a[href^="/"]');
    if (link) {
      const href = link.getAttribute('href');
      return href.replace('/', '').toLowerCase();
    }
    return null;
  };

  const isWhitelisted = (username) => {
    return WHITELIST.map(u => u.toLowerCase()).includes(username?.toLowerCase());
  };

  const followsBack = (cell) => {
    return cell.querySelector('[data-testid="userFollowIndicator"]') !== null;
  };

  const unfollowUser = async (unfollowBtn) => {
    unfollowBtn.click();
    await sleep(800);
    const confirmBtn = document.querySelector($confirmButton);
    if (confirmBtn) {
      confirmBtn.click();
      await sleep(500);
    }
  };

  const processVisible = async () => {
    const cells = document.querySelectorAll($userCell);
    let processed = 0;

    for (const cell of cells) {
      const username = getUsernameFromCell(cell);
      const unfollowBtn = cell.querySelector($followButtons);
      
      if (!unfollowBtn || !username) continue;

      // Skip if follows back
      if (followsBack(cell)) {
        continue;
      }

      // Skip if whitelisted
      if (isWhitelisted(username)) {
        console.log(`โญ๏ธ Skipping @${username} (whitelisted)`);
        skippedCount++;
        continue;
      }

      console.log(`๐Ÿ‘‹ Unfollowing @${username}...`);
      await unfollowUser(unfollowBtn);
      unfollowedCount++;
      processed++;
      await sleep(1500);
    }

    return processed > 0;
  };

  const run = async () => {
    console.log('๐Ÿง  Smart Unfollow Started');
    console.log(`๐Ÿ“ Whitelist: ${WHITELIST.length} accounts protected`);

    while (retry.count < retry.limit) {
      scrollToBottom();
      await sleep(2000);

      const didProcess = await processVisible();
      
      if (!didProcess) {
        retry.count++;
        console.log(`โณ No users found, retry ${retry.count}/${retry.limit}...`);
      } else {
        retry.count = 0;
      }
    }

    console.log('');
    console.log('โœ… DONE!');
    console.log(`๐Ÿ‘‹ Unfollowed: ${unfollowedCount}`);
    console.log(`โญ๏ธ Skipped (whitelisted): ${skippedCount}`);
  };

  run();
})();
โœ… Tip

Keep a list of your favorite accounts that never follow back (news, brands, etc.) and add them to your whitelist!

๐Ÿ” 4. Detect Who Unfollowed You

๐Ÿ“‹ What This Does

Scans your followers and saves a snapshot. Run it again later to see who unfollowed you! Also shows new followers. Data is saved locally in your browser.

๐ŸŽฏ Quick Start

  1. Go to x.com/YOUR_USERNAME/followers
  2. Open DevTools and paste the code
  3. Wait for scan to complete (saves snapshot)
  4. Run again later to see changes!
detect-unfollowers.js
// Detect who unfollowed you on X
// by nichxbt - https://github.com/nirholas/XActions
(() => {
  const STORAGE_KEY = 'xactions_my_followers';
  const sleep = (ms) => new Promise(r => setTimeout(r, ms));

  // Check we're on the right page
  const isFollowersPage = window.location.pathname.includes('/followers');
  if (!isFollowersPage) {
    console.error('โŒ Please navigate to your FOLLOWERS page first!');
    console.log('๐Ÿ‘‰ Go to: https://x.com/YOUR_USERNAME/followers');
    return;
  }

  const getCurrentUsername = () => {
    const match = window.location.pathname.match(/^\/([^/]+)\/followers/);
    return match ? match[1] : 'unknown';
  };

  const scrapeFollowers = async () => {
    const followers = new Set();
    let previousSize = 0;
    let retries = 0;
    const maxRetries = 5;

    console.log('๐Ÿ” Scanning your followers...');

    while (retries < maxRetries) {
      // Scroll to load more
      window.scrollTo(0, document.body.scrollHeight);
      await sleep(1500);

      // Find all user cells and extract usernames
      const userCells = document.querySelectorAll('[data-testid="UserCell"]');
      userCells.forEach(cell => {
        const usernameEl = cell.querySelector('a[href^="/"]');
        if (usernameEl) {
          const href = usernameEl.getAttribute('href');
          const username = href.replace('/', '').toLowerCase();
          if (username && !username.includes('/')) {
            followers.add(username);
          }
        }
      });

      console.log(`   Found ${followers.size} followers so far...`);

      if (followers.size === previousSize) {
        retries++;
      } else {
        retries = 0;
        previousSize = followers.size;
      }
    }

    return Array.from(followers);
  };

  const loadPreviousFollowers = () => {
    try {
      const data = localStorage.getItem(STORAGE_KEY);
      if (data) {
        return JSON.parse(data);
      }
    } catch (e) {
      console.warn('Could not load previous data:', e);
    }
    return null;
  };

  const saveFollowers = (followers, username) => {
    const data = {
      username,
      followers,
      timestamp: new Date().toISOString(),
      count: followers.length
    };
    localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
    return data;
  };

  const compareFollowers = (previous, current) => {
    const prevSet = new Set(previous.map(f => f.toLowerCase()));
    const currSet = new Set(current.map(f => f.toLowerCase()));

    const unfollowed = previous.filter(f => !currSet.has(f.toLowerCase()));
    const newFollowers = current.filter(f => !prevSet.has(f.toLowerCase()));

    return { unfollowed, newFollowers };
  };

  const formatDate = (isoString) => {
    return new Date(isoString).toLocaleString();
  };

  const run = async () => {
    const username = getCurrentUsername();
    console.log(`\n๐Ÿฆ XActions Detector โ€” Monitoring @${username}\n`);

    // Scrape current followers
    const currentFollowers = await scrapeFollowers();
    console.log(`\nโœ… Found ${currentFollowers.length} total followers\n`);

    // Check for previous data
    const previousData = loadPreviousFollowers();

    if (previousData && previousData.username === username) {
      console.log(`๐Ÿ“Š Comparing with snapshot from ${formatDate(previousData.timestamp)}`);
      console.log(`   Previous count: ${previousData.count}`);
      console.log(`   Current count: ${currentFollowers.length}`);
      console.log('');

      const { unfollowed, newFollowers } = compareFollowers(previousData.followers, currentFollowers);

      if (unfollowed.length > 0) {
        console.log(`\n๐Ÿšจ ${unfollowed.length} PEOPLE UNFOLLOWED YOU:\n`);
        unfollowed.forEach((u, i) => {
          console.log(`   ${i + 1}. @${u} โ€” https://x.com/${u}`);
        });
      } else {
        console.log('โœจ No one unfollowed you since last check!');
      }

      if (newFollowers.length > 0) {
        console.log(`\n๐ŸŽ‰ ${newFollowers.length} NEW FOLLOWERS:\n`);
        newFollowers.forEach((u, i) => {
          console.log(`   ${i + 1}. @${u} โ€” https://x.com/${u}`);
        });
      }

      // Offer download of unfollowers
      if (unfollowed.length > 0) {
        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 list of unfollowers!');
      }
    } else {
      console.log('๐Ÿ“ธ First scan! Saving snapshot of your followers...');
      console.log('   Run this script again later to detect changes.');
    }

    // Save current state
    const saved = saveFollowers(currentFollowers, username);
    console.log(`\n๐Ÿ’พ Snapshot saved at ${formatDate(saved.timestamp)}`);
    console.log('   Run this script again anytime to check for changes!\n');
  };

  run();
})();
๐Ÿ’พ Data Storage

Your follower data is saved in your browser's localStorage under the key xactions_my_followers. It stays on your computer and is never sent anywhere.

๐Ÿ“ฆ Node.js / CLI Method

You can also use XActions from the command line:

Terminal
# Install XActions globally
npm install -g xactions

# Unfollow everyone (requires auth cookie)
npx xactions unfollow --all

# Unfollow non-followers only
npx xactions unfollow --non-followers

# Get list of non-followers
npx xactions analyze non-followers @yourusername

โš ๏ธ Important Notes

  • Rate Limits: X may temporarily limit your account if you unfollow too fast. The scripts include delays to minimize this risk.
  • No Undo: Unfollows cannot be undone automatically. You'd need to re-follow accounts manually.
  • Page Navigation: Don't navigate away while scripts are running - they stop when you leave the page.
  • Large Lists: For accounts following 10,000+ people, run the script multiple times with refreshes.
  • Best Practice: Start during off-peak hours and don't run multiple automation scripts simultaneously.