Skip to content

Instantly share code, notes, and snippets.

@benjaminjackson
Created November 13, 2025 17:40
Show Gist options
  • Select an option

  • Save benjaminjackson/21fc2c1a135dca617ef1282285418c0e to your computer and use it in GitHub Desktop.

Select an option

Save benjaminjackson/21fc2c1a135dca617ef1282285418c0e to your computer and use it in GitHub Desktop.
Unfollow Everyone on LinkedIn (No Confirmation, Nukes Everyone)
// LinkedIn Auto-Unfollow Script
// Automatically unfollows everyone without confirmation
// WARNING: This will unfollow people automatically without asking for confirmation
(() => {
let count = 0;
const processedPeople = new Set(); // Track who we've already unfollowed
function getAllFollowingButtons() {
return Array.from(document.querySelectorAll('button.artdeco-button--muted.artdeco-button--secondary'))
.filter(btn => {
const buttonText = btn.querySelector('.artdeco-button__text')?.innerText;
const ariaLabel = btn.getAttribute('aria-label');
// Only include buttons we haven't processed yet
return buttonText === "Following" && !processedPeople.has(ariaLabel);
});
}
function waitForModal() {
return new Promise((resolve) => {
const checkInterval = setInterval(() => {
const modal = document.querySelector('.artdeco-modal');
if (modal) {
clearInterval(checkInterval);
resolve(modal);
}
}, 100);
});
}
function waitForModalToClose() {
return new Promise((resolve) => {
const checkInterval = setInterval(() => {
const modal = document.querySelector('.artdeco-modal');
if (!modal) {
clearInterval(checkInterval);
resolve();
}
}, 500);
});
}
async function unfollowNext() {
const buttons = getAllFollowingButtons();
console.log(`Found ${buttons.length} unprocessed "Following" buttons`);
if (buttons.length === 0) {
// Try multiple times to load more content
let loadAttempts = 0;
const maxAttempts = 3;
while (loadAttempts < maxAttempts) {
loadAttempts++;
console.log(`Load attempt ${loadAttempts}/${maxAttempts}...`);
// Click "Show more results" button if it exists
const showMoreButton = document.querySelector('.scaffold-finite-scroll__load-button');
if (showMoreButton && !showMoreButton.disabled) {
console.log("Clicking 'Show more results' button...");
showMoreButton.click();
await new Promise((resolve) => setTimeout(resolve, 5000));
} else {
// Otherwise try scrolling
console.log("Scrolling to bottom...");
window.scrollTo(0, document.body.scrollHeight);
await new Promise((resolve) => setTimeout(resolve, 5000));
}
// Check for new buttons
const newButtons = getAllFollowingButtons();
console.log(`After attempt ${loadAttempts}: found ${newButtons.length} new buttons`);
if (newButtons.length > 0) {
console.log("Found new buttons, continuing...");
return unfollowNext();
}
if (loadAttempts < maxAttempts) {
console.log("No new buttons yet, waiting before next attempt...");
await new Promise((resolve) => setTimeout(resolve, 2000));
}
}
// After all attempts, we're done
console.log("Could not find more content after multiple attempts - reached the end");
console.log(`All done! Unfollowed ${count} people total.`);
console.log(`Successfully unfollowed: ${processedPeople.size}`);
return;
}
// Get the first unprocessed button
const button = buttons[0];
const ariaLabel = button.getAttribute("aria-label");
// Extract person's name from aria-label (format: "Click to stop following [Name]")
const personName = ariaLabel.replace('Click to stop following ', '');
count++;
console.log(`${count}. Unfollowing: ${personName}`);
// Scroll button into view
button.scrollIntoView({ behavior: 'smooth', block: 'center' });
await new Promise((resolve) => setTimeout(resolve, 300));
// Click to open modal
button.click();
// Wait for modal to appear
await waitForModal();
await new Promise((resolve) => setTimeout(resolve, 300));
// Find and click the "Unfollow" button in the modal
// It's the primary button with text "Unfollow"
const unfollowButton = Array.from(document.querySelectorAll('.artdeco-modal button'))
.find(btn => btn.innerText.trim() === 'Unfollow');
if (unfollowButton) {
unfollowButton.click();
} else {
console.log(`⚠️ Could not find Unfollow button in modal for ${personName}`);
}
// Wait for modal to close
await waitForModalToClose();
// Delay to let the button update (LinkedIn needs time to re-render)
await new Promise((resolve) => setTimeout(resolve, 1000));
// Re-query for buttons with this person's name to verify unfollow
const updatedButton = Array.from(document.querySelectorAll('button.artdeco-button--secondary'))
.find(btn => {
const label = btn.getAttribute('aria-label');
return label && (
label === ariaLabel || // Still has old label (failed?)
label === `Click to follow ${personName}` // Changed to new label (success)
);
});
if (!updatedButton || updatedButton.querySelector('.artdeco-button__text')?.innerText === "Follow") {
// Successfully unfollowed
processedPeople.add(ariaLabel);
console.log(`✓ Unfollowed ${personName}`);
} else {
// Something went wrong, mark as processed to avoid infinite loop
processedPeople.add(ariaLabel);
console.log(`⚠️ Could not verify unfollow for ${personName}`);
}
// Small delay before next person
await new Promise((resolve) => setTimeout(resolve, 500));
// Continue to next
unfollowNext();
}
console.log("⚠️ Starting AUTOMATIC unfollow - will unfollow everyone without confirmation!");
unfollowNext();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment