Created
October 29, 2024 11:09
-
-
Save cyrillsemenov/e9b014a68e4a2c1c2a1c175b8314f3de to your computer and use it in GitHub Desktop.
Batch remove twitter followers
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
// Function to extract the username from the follower element | |
const get_username = (follower) => { | |
return new URL( | |
follower.children[1].querySelector("a").href | |
).pathname.substring(1); | |
}; | |
// Function to extract the user ID from the button within the follower element | |
const get_user_id = (follower) => { | |
return follower.querySelector("button").dataset.testid.split("-")[0]; | |
}; | |
// Main function to print out JSON-formatted list of followers | |
(function print_followers() { | |
let users = {}; | |
document | |
.querySelectorAll('button[data-testid="UserCell"] > div') | |
.forEach((follower) => { | |
const username = get_username(follower); | |
const userId = get_user_id(follower); | |
if (username && userId) { | |
users[username] = userId; | |
} | |
}); | |
console.table(users); | |
console.log(JSON.stringify(users, null, 4)); | |
})() |
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
const users = { | |
// Paste users here | |
}; | |
// Replace with your actual Bearer token, csrf token, and query ID | |
const BEARER_TOKEN = "YOUR_BEARER_TOKEN_HERE"; | |
const CSRF_TOKEN = "YOUR_CSRF_TOKEN_HERE"; | |
const QUERY_ID = "YOUR_QUERY_ID_HERE"; | |
async function unfollowUser(user_id) { | |
try { | |
const response = await fetch( | |
"https://x.com/i/api/graphql/" + QUERY_ID + "/RemoveFollower", | |
{ | |
headers: { | |
accept: "*/*", | |
"accept-language": "en-US,en;q=0.9", | |
authorization: `Bearer ${BEARER_TOKEN}`, | |
"content-type": "application/json", | |
"x-csrf-token": CSRF_TOKEN, | |
"x-twitter-active-user": "yes", | |
"x-twitter-auth-type": "OAuth2Session", | |
"x-twitter-client-language": "en", | |
}, | |
body: JSON.stringify({ | |
variables: { | |
target_user_id: user_id, | |
}, | |
}), | |
method: "POST", | |
mode: "cors", | |
credentials: "include", | |
} | |
); | |
if (response.ok) { | |
console.log(`Successfully removed follower: ${user_id}`); | |
} else { | |
console.error( | |
`Failed to remove follower: ${user_id}`, | |
response.statusText | |
); | |
} | |
} catch (error) { | |
console.error(`Error unfollowing user ${user_id}`, error); | |
} | |
} | |
(function remove_followers(users, y = false) { | |
for (const [username, user_id] of Object.entries(users)) { | |
if ( | |
y || | |
confirm( | |
`User ${username} will unfollow you\nCancel to leave them in followers` | |
) | |
) { | |
unfollowUser(value); | |
} | |
} | |
})( | |
users, | |
false // If `true`, it skips the prompt and removes each user automatically | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment