Created
December 4, 2025 22:39
-
-
Save eaorak/160e5794d09bb0638ce49b80b25a84d9 to your computer and use it in GitHub Desktop.
LinkedIn Unfollow Script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Go to this page: | |
| // | |
| // https://www.linkedin.com/mynetwork/network-manager/people-follow/following/ | |
| // | |
| // Paste this entire file into the DevTools console on your LinkedIn "Following" tab. | |
| // It will iterate through visible "Following" buttons, click each one, confirm the | |
| // unfollow dialog, and keep scrolling until it runs out of people or hits the limit. | |
| // Adjust the CONFIG values to suit your pace/limits before running. | |
| (() => { | |
| const CONFIG = { | |
| maxUnfollows: 300, // Hard stop to avoid endless runs. | |
| betweenClicksMs: 900, // Wait after each confirm click. | |
| confirmWaitMs: 2000, // How long to wait for the confirm dialog. | |
| scrollPauseMs: 1000 // Wait after each scroll for content to load. | |
| }; | |
| const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); | |
| const findFollowingButtons = () => | |
| Array.from(document.querySelectorAll('button')).filter((btn) => { | |
| const label = btn.textContent?.trim().toLowerCase(); | |
| return label === 'following'; | |
| }); | |
| const waitForConfirmButton = async (timeoutMs) => { | |
| const start = performance.now(); | |
| while (performance.now() - start < timeoutMs) { | |
| const btn = Array.from(document.querySelectorAll('button')).find((b) => { | |
| const text = b.textContent?.trim().toLowerCase(); | |
| return text === 'unfollow'; | |
| }); | |
| if (btn) return btn; | |
| await sleep(100); | |
| } | |
| return null; | |
| }; | |
| const scrollMore = async () => { | |
| const before = document.body.scrollHeight; | |
| window.scrollBy({ top: window.innerHeight * 0.9, behavior: 'smooth' }); | |
| await sleep(CONFIG.scrollPauseMs); | |
| return document.body.scrollHeight > before; | |
| }; | |
| const processed = new WeakSet(); | |
| let unfollowed = 0; | |
| let failures = 0; | |
| const log = (...args) => console.log('[unfollow]', ...args); | |
| const run = async () => { | |
| log('Starting…'); | |
| while (unfollowed < CONFIG.maxUnfollows) { | |
| const buttons = findFollowingButtons().filter((b) => !processed.has(b)); | |
| if (buttons.length === 0) { | |
| const grew = await scrollMore(); | |
| if (!grew) { | |
| log('No more people found to unfollow.'); | |
| break; | |
| } | |
| continue; | |
| } | |
| for (const btn of buttons) { | |
| if (unfollowed >= CONFIG.maxUnfollows) break; | |
| processed.add(btn); | |
| btn.scrollIntoView({ behavior: 'smooth', block: 'center' }); | |
| btn.click(); | |
| const confirm = await waitForConfirmButton(CONFIG.confirmWaitMs); | |
| if (confirm) { | |
| confirm.click(); | |
| unfollowed += 1; | |
| failures = 0; | |
| log(`Unfollowed ${unfollowed}`); | |
| await sleep(CONFIG.betweenClicksMs); | |
| } else { | |
| failures += 1; | |
| log('Confirm dialog not found; skipping this entry.'); | |
| await sleep(300); | |
| } | |
| if (failures >= 5) { | |
| log('Too many failures locating the confirm dialog. Stopping.'); | |
| return; | |
| } | |
| } | |
| } | |
| log(`Finished. Total unfollowed: ${unfollowed}`); | |
| }; | |
| run(); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment