Skip to content

Instantly share code, notes, and snippets.

@d-oit
Created October 25, 2025 14:39
Show Gist options
  • Select an option

  • Save d-oit/13407345641a6518e42f5ea75793a0b6 to your computer and use it in GitHub Desktop.

Select an option

Save d-oit/13407345641a6518e42f5ea75793a0b6 to your computer and use it in GitHub Desktop.
LinkedIn Mass Unfollow Script (Stealth Mode) - browser console workaround script

LinkedIn Mass Unfollow Script (Stealth Mode)

A browser console script to automatically unfollow people on LinkedIn with human-like behavior patterns to minimize detection risk.

⚠️ Disclaimer

This script is provided for educational purposes only. Automated actions may violate LinkedIn's Terms of Service. Use at your own risk. The authors are not responsible for any consequences including but not limited to account restrictions or bans.

Features

  • Unpredictable random delays between actions (mimics human behavior)
  • Batch processing with longer breaks to avoid rate limiting
  • Human-like mouse movements with randomized click positions
  • Automatic rate limit detection - stops if warnings are detected
  • Configurable safety limits to control maximum unfollows per session
  • Detailed logging with timestamps for monitoring
  • Smooth scrolling with random offsets
  • Session management to prevent excessive automation

How It Works

The script:

  1. Finds all "unfollow" buttons on the current page
  2. Clicks each button with randomized delays (800-2500ms)
  3. Confirms the unfollow action after a random wait (500-1500ms)
  4. Takes longer breaks after processing batches (5-10 seconds)
  5. Scrolls to load more people with human-like timing
  6. Repeats until no more people are found or limits are reached

Usage

Step 1: Navigate to LinkedIn Following Page

Open your browser and go to:

https://www.linkedin.com/mynetwork/network-manager/people-follow/following/

Step 2: Open Browser Console

  • Chrome/Edge: Press F12 or Ctrl+Shift+J (Windows) / Cmd+Option+J (Mac)
  • Firefox: Press F12 or Ctrl+Shift+K (Windows) / Cmd+Option+K (Mac)
  • Safari: Enable Developer Menu in Preferences, then press Cmd+Option+C

Step 3: Enable Pasting in Chrome/Edge (First Time Only)

⚠️ Important for Chrome/Edge users: The first time you try to paste into the console, Chrome will block it for security reasons.

  1. Click into the console area
  2. Type allow pasting (without quotes)
  3. Press Enter
  4. Now you can paste scripts

Note: You only need to do this once per browser session. Firefox and Safari don't require this step.

Step 4: Copy and Paste the Script

Copy the entire script from mass-unfollow-on-linkedin.js and paste it into the console, then press Enter.

Step 5: Monitor the Progress

Watch the console output for progress updates. The script will log:

  • Number of people found
  • Each unfollow action with delays
  • Batch completion messages
  • Warnings or completion status

Step 6: Stop Manually (Optional)

To stop the script at any time, simply refresh the page or close the browser tab.

Configuration

You can customize the script behavior by editing these values at the top:

const config = {
    // Random delay ranges (in milliseconds)
    clickDelay: { min: 800, max: 2500 },        // Between clicking unfollow
    confirmDelay: { min: 500, max: 1500 },      // Before clicking confirm
    afterConfirmDelay: { min: 800, max: 2000 }, // After confirming
    scrollDelay: { min: 1500, max: 3000 },      // After scrolling
    pauseAfterBatch: { min: 5000, max: 10000 }, // Longer pause every N unfollows
    batchSize: { min: 8, max: 15 },             // Process this many before long pause
    
    // Safety limits
    maxUnfollows: 100,  // Maximum total unfollows per session (0 = unlimited)
    stopIfTooFast: true // Stop if LinkedIn shows rate limit warning
};

Recommended Settings

Conservative (Safest):

maxUnfollows: 50
clickDelay: { min: 1500, max: 3500 }
pauseAfterBatch: { min: 10000, max: 20000 }

Moderate (Balanced):

maxUnfollows: 100
clickDelay: { min: 800, max: 2500 }
pauseAfterBatch: { min: 5000, max: 10000 }

Aggressive (Higher Risk):

maxUnfollows: 200
clickDelay: { min: 500, max: 1500 }
pauseAfterBatch: { min: 3000, max: 6000 }

Language Support

The script looks for unfollow buttons using the aria-label attribute. By default, it searches for German labels:

button[aria-label*="nicht mehr zu folgen"]

For other languages, modify this line in the getAllButtons() function:

  • English: button[aria-label*="Unfollow"]
  • Spanish: button[aria-label*="Dejar de seguir"]
  • French: button[aria-label*="Ne plus suivre"]
  • Portuguese: button[aria-label*="Deixar de seguir"]

Safety Tips

  1. Start Small: Begin with maxUnfollows: 20-50 to test
  2. Use During Active Hours: Run during times when you'd normally use LinkedIn
  3. Don't Run Daily: Wait several days between sessions
  4. Monitor for Warnings: If you see rate limit messages, stop immediately
  5. Stay on the Page: Don't switch tabs while running (appears more human)
  6. Increase Delays: If concerned, increase all delay ranges by 50-100%

Troubleshooting

Script Doesn't Start

  • Ensure you're on the correct LinkedIn page
  • Check browser console for error messages
  • Try refreshing the page and running again

No Buttons Found

  • Verify you're on the "Following" page, not "Followers"
  • Check if the aria-label matches your LinkedIn language
  • Scroll manually to load some people first

Rate Limiting

  • The script should detect this automatically
  • Wait 24-48 hours before trying again
  • Reduce maxUnfollows and increase delays next time

Confirmation Button Not Found

  • LinkedIn may have updated their UI
  • Check the browser console for the actual button selector
  • Update the selector in the script if needed

Technical Details

Anti-Detection Measures

  1. Randomized Timing: All delays use random ranges to prevent pattern detection
  2. Variable Batch Sizes: Each session processes a different number per batch
  3. Human-like Clicks: Mouse events include randomized coordinates
  4. Smooth Scrolling: Natural scroll behavior with random offsets
  5. Warning Detection: Monitors for LinkedIn error/limit messages
  6. Session Limits: Prevents excessive automation in one session

Browser Compatibility

  • ✅ Chrome/Chromium (Recommended)
  • ✅ Firefox
  • ✅ Edge
  • ✅ Safari
  • ✅ Brave
  • ✅ Opera

FAQ

Q: Is this safe to use?
A: There's always risk with automation. The script includes many anti-detection features, but LinkedIn could still detect and penalize automated behavior.

Q: How many people can I unfollow per day?
A: LinkedIn's limits aren't public. Conservative recommendation: 50-100 per day maximum, split into multiple sessions.

Q: Will this get my account banned?
A: Possibly. Use conservatively and at your own risk. Many users report no issues with moderate use.

Q: Can I run this multiple times?
A: Yes, but wait several hours between runs. Running it continuously increases detection risk.

Q: What if LinkedIn updates their interface?
A: The script may need updates. Check the selectors and aria-labels if it stops working.

Updates & Contributing

This script may need updates if LinkedIn changes their interface. Feel free to:

  • Report issues with LinkedIn UI changes
  • Suggest improvements to anti-detection measures
  • Share your safe configuration settings

License

This project is provided as-is for educational purposes. Use responsibly.


Last Updated: October 2025
LinkedIn UI Version: Tested on current LinkedIn interface

Remember: The safest approach is to manually unfollow people. This tool is for those managing large networks who understand and accept the risks.

// Open: https://www.linkedin.com/mynetwork/network-manager/people-follow/following/
// Open Browser console and execute this helper:
(() => {
// Configuration
const config = {
// Random delay ranges (in milliseconds) - mimics human behavior
clickDelay: { min: 800, max: 2500 }, // Delay between initial button click
confirmDelay: { min: 500, max: 1500 }, // Delay before clicking confirm
afterConfirmDelay: { min: 800, max: 2000 }, // Delay after confirming
scrollDelay: { min: 1500, max: 3000 }, // Delay after scrolling
pauseAfterBatch: { min: 5000, max: 10000 }, // Longer pause every N unfollows
batchSize: { min: 8, max: 15 }, // Process this many before long pause
// Safety limits
maxUnfollows: 100, // Maximum total unfollows per session (set to 0 for unlimited)
stopIfTooFast: true // Stop if LinkedIn shows rate limit warning
};
let unfollowCount = 0;
let batchCount = 0;
const currentBatchSize = randomInt(config.batchSize.min, config.batchSize.max);
// Generate random delay between min and max
function randomDelay(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Generate random integer
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Wait for specified milliseconds
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// Log with timestamp
function log(message) {
const timestamp = new Date().toLocaleTimeString();
console.log(`[${timestamp}] ${message}`);
}
// Simulate human-like mouse movement (add slight randomness to click position)
function humanClick(element) {
const event = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window,
// Add slight randomness to make it less robotic
clientX: element.getBoundingClientRect().left + randomInt(5, element.offsetWidth - 5),
clientY: element.getBoundingClientRect().top + randomInt(5, element.offsetHeight - 5)
});
element.dispatchEvent(event);
}
// ⚠️ Maybe you need to adjust the aria label if your LinkedIn displays labels in a different language:
function getAllButtons() {
return document.querySelectorAll('button[aria-label*="nicht mehr zu folgen"]');
}
// Check for rate limiting or error messages
function checkForWarnings() {
const errorMessages = document.querySelectorAll('[role="alert"], .artdeco-toast-item');
for (let msg of errorMessages) {
if (msg.textContent.toLowerCase().includes('limit') ||
msg.textContent.toLowerCase().includes('error') ||
msg.textContent.toLowerCase().includes('try again')) {
return true;
}
}
return false;
}
async function unfollowAll() {
const buttons = getAllButtons();
if (buttons.length === 0) {
log('No more unfollow buttons found on this page.');
return;
}
log(`Found ${buttons.length} people to unfollow on current page.`);
for (let button of buttons) {
// Check safety limits
if (config.maxUnfollows > 0 && unfollowCount >= config.maxUnfollows) {
log(`⚠️ Reached maximum unfollow limit (${config.maxUnfollows}). Stopping for safety.`);
return;
}
if (config.stopIfTooFast && checkForWarnings()) {
log('⚠️ Warning detected! Stopping to avoid rate limiting.');
return;
}
// Scroll button into view with random offset
button.scrollIntoView({ behavior: 'smooth', block: 'center' });
await sleep(randomDelay(200, 500));
// Click unfollow button with human-like behavior
const clickDelay = randomDelay(config.clickDelay.min, config.clickDelay.max);
log(`Unfollowing... (waiting ${clickDelay}ms)`);
await sleep(clickDelay);
humanClick(button);
// Wait for confirmation dialog with random delay
const confirmWait = randomDelay(config.confirmDelay.min, config.confirmDelay.max);
await sleep(confirmWait);
// Click confirm button
const confirmBtn = document.querySelector('[role="alertdialog"] button[data-test-dialog-primary-btn]');
if (confirmBtn) {
humanClick(confirmBtn);
unfollowCount++;
batchCount++;
log(`✓ Unfollowed (Total: ${unfollowCount})`);
} else {
log('⚠️ Confirmation button not found, skipping...');
}
// Wait after confirming
const afterDelay = randomDelay(config.afterConfirmDelay.min, config.afterConfirmDelay.max);
await sleep(afterDelay);
// Take longer break after batch
if (batchCount >= currentBatchSize) {
const pauseTime = randomDelay(config.pauseAfterBatch.min, config.pauseAfterBatch.max);
log(`📊 Batch complete (${batchCount} unfollows). Taking a ${(pauseTime/1000).toFixed(1)}s break...`);
await sleep(pauseTime);
batchCount = 0;
}
}
}
async function run() {
log('🚀 Starting LinkedIn unfollow script...');
log(`Configuration: Max ${config.maxUnfollows || 'unlimited'} unfollows, batch size: ${currentBatchSize}`);
await unfollowAll();
// Check if we should continue
if (config.maxUnfollows > 0 && unfollowCount >= config.maxUnfollows) {
log('✅ Session complete - reached maximum limit.');
return;
}
if (config.stopIfTooFast && checkForWarnings()) {
log('✅ Stopped due to warning detection.');
return;
}
// Scroll to load more with human-like behavior
const scrollDelay = randomDelay(config.scrollDelay.min, config.scrollDelay.max);
log(`Scrolling to load more... (waiting ${scrollDelay}ms)`);
// Scroll with slight randomness (not always to exact bottom)
const scrollTarget = document.body.scrollHeight - randomInt(0, 200);
window.scrollTo({ top: scrollTarget, behavior: 'smooth' });
await sleep(scrollDelay);
// Check if there are more buttons after scroll
const buttons = getAllButtons();
if (buttons.length > 0) {
log(`Found ${buttons.length} more people after scrolling. Continuing...`);
run(); // Continue recursively
} else {
log('✅ No more people to unfollow. Done!');
}
}
run();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment