As a Roblox developer it is currently too hard to remove unwanted followers.
The current method used to accomplish this goal is to navigate to the profile of a user following you and block them? Simple, right?
Well, this practice is very time-consuming and unrealistic to be used in application if the user is experiencing a situation in which they desire to remove hundreds or thousands of unwanted followers. In other words, it is too hard for users to remove followers in bulk (multiple at once).
Consider my example which is one experienced by many other users who have undergone manipulation in follower count. For a few years now, I have had over ten thousand bot followers. I do not wish to keep these followers. The accumulated, unrealistic follower statistic that I have misleads users into believing that I have a false number of followers and subsequently damages my reputation as a Roblox developer once they uncover the truth. I am not going to spend hours and/or days blocking these bot followers one by one. Even if I put my head into blocking over ten thousand bots, I would feel immense stress and frustration during the process because of the quota given to block users, which is at 300 blocks per user - meaning, I would constantly have to change those 300 users I have blocked in order to accomplish my goal. This limitation significantly adds time to the blocking process. Furthermore, some Roblox users have even more severe experiences with bots in which they have over hundreds of thousands or millions of bot followers…good luck getting rid of all of them one by one!
Additionally, the current practice cannot be applied to followers who are deleted from the platform. As a Roblox developer, I want to prove to other users visiting my profile that I have an active community following me. Being able to remove deleted followers from my followers list would enable me to achieve this goal.
If this issue were to be addressed, it would improve my UX using the followers feature.
I have some Python code here given to me by ChatGPT to block and quickly unblock people who follow you. Of course, it had some of the API endpoints wrong, like “users.roblox.com/v1/users/1/block”, which doesn’t exist, but I’ve corrected that. This code allowed me to get rid of all my followers, leaving only my friends.
import requests
import time
# Replace with your actual user ID and authentication cookie value
user_id = 'USERID'
auth_cookie = 'ROBLOSECURITYCOOKIE'
# Set up headers with the authentication cookie
headers = {
'Cookie': f'.ROBLOSECURITY={auth_cookie}'
}
# Function to get the CSRF token
def get_csrf_token():
url = 'https://auth.roblox.com/v2/logout' # A simple endpoint that returns the CSRF token
response = requests.post(url, headers=headers)
if response.status_code == 403:
return response.headers['x-csrf-token']
else:
response.raise_for_status()
# Get the CSRF token
csrf_token = get_csrf_token()
headers.update({'x-csrf-token': csrf_token})
# Function to handle API requests with retry mechanism
def api_request(url, method='GET', data=None):
retries = 10
backoff = 1
for attempt in range(retries):
if method == 'GET':
response = requests.get(url, headers=headers)
elif method == 'POST':
response = requests.post(url, headers=headers, json=data)
else:
raise ValueError("Unsupported HTTP method")
if response.status_code == 429: # Too Many Requests
print(f"Rate limited. Retrying in {backoff} seconds...")
time.sleep(backoff)
backoff *= 2
elif response.status_code == 400:
print(f"Rate limited. Retrying in {backoff} seconds...")
time.sleep(backoff)
backoff *= 2
elif response.status_code == 200:
return response
elif response.status_code == 403 and 'x-csrf-token' in response.headers:
# Update CSRF token and retry
headers['x-csrf-token'] = response.headers['x-csrf-token']
continue
else:
response.raise_for_status()
raise Exception(f"API request failed after {retries} retries")
# Function to get all followers with pagination
def get_all_followers(user_id):
followers = []
cursor = ""
while True:
followers_url = f'https://friends.roblox.com/v1/users/{user_id}/followers?limit=100&cursor={cursor}'
response = api_request(followers_url)
data = response.json()
followers.extend(data['data'])
cursor = data.get('nextPageCursor')
if not cursor:
break
return followers
# Function to get all friends with pagination
def get_all_friends(user_id):
friends = []
cursor = ""
while True:
friends_url = f'https://friends.roblox.com/v1/users/{user_id}/friends?limit=100&cursor={cursor}'
response = api_request(friends_url)
data = response.json()
friends.extend(data['data'])
cursor = data.get('nextPageCursor')
if not cursor:
break
return friends
# Get list of all followers and friends
followers = get_all_followers(user_id)
friends = get_all_friends(user_id)
friend_ids = {friend['id'] for friend in friends}
# Block and unblock each follower who is not a friend
block_url = 'https://accountsettings.roblox.com/v1/users/{userId}/block'
unblock_url = 'https://accountsettings.roblox.com/v1/users/{userId}/unblock'
for follower in followers:
follower_id = follower['id']
if follower_id not in friend_ids:
# Block the user
block_response = api_request(block_url.format(userId=follower_id), method='POST', data={"userId": follower_id})
print(f'Blocked user {follower_id}')
# Wait for 5 seconds
time.sleep(5)
# Unblock the user
unblock_response = api_request(unblock_url.format(userId=follower_id), method='POST', data={"userId": follower_id})
print(f'Unblocked user {follower_id}')
else:
print(f'Skipped friend {follower_id}')
If you don’t have many followers, you can remove set “time.sleep(5)” to 0, because you won’t have to worry very much about rate-limiting. In my case, however, I had to leave it due to how many followers I had at the time. You can just open up Notepad and save this as “remove_followers.py” or something, and then use “python remove_followers.py” and then you should be good to go.
Thank you so much for this amazing tool! I’ve been searching for an efficient way to do this for a year!
I asked ChatGPT to edit the script to remove likely bot accounts (uses 0 followers and 0 friends as a benchmark).
import requests
import time
# Replace with your actual user ID and authentication cookie value
user_id = 'USERID'
auth_cookie = 'ROBLOSECURITYCOOKIE'
# Set up headers with the authentication cookie
headers = {
'Cookie': f'.ROBLOSECURITY={auth_cookie}'
}
# Function to get the CSRF token
def get_csrf_token():
url = 'https://auth.roblox.com/v2/logout' # A simple endpoint that returns the CSRF token
response = requests.post(url, headers=headers)
if response.status_code == 403:
return response.headers['x-csrf-token']
else:
response.raise_for_status()
# Get the CSRF token
csrf_token = get_csrf_token()
headers.update({'x-csrf-token': csrf_token})
# Function to handle API requests with retry mechanism and improved logging
def api_request(url, method='GET', data=None):
retries = 10
backoff = 1
for attempt in range(retries):
try:
if method == 'GET':
response = requests.get(url, headers=headers)
elif method == 'POST':
response = requests.post(url, headers=headers, json=data)
else:
raise ValueError("Unsupported HTTP method")
if response.status_code == 429:
print(f"Rate limit exceeded. Retrying in {backoff} seconds...")
time.sleep(backoff)
backoff *= 2
elif response.status_code == 500:
print(f"Server error (500). Retrying in {backoff} seconds...")
time.sleep(backoff)
backoff *= 2
elif response.status_code == 200:
return response
elif response.status_code == 403 and 'x-csrf-token' in response.headers:
headers['x-csrf-token'] = response.headers['x-csrf-token']
continue
else:
response.raise_for_status()
except requests.RequestException as e:
print(f"Request failed: {e}. Retrying in {backoff} seconds...")
time.sleep(backoff)
backoff *= 2
raise Exception(f"API request failed after {retries} retries")
# Function to get all followers with pagination
def get_all_followers(user_id):
followers = []
cursor = ""
while True:
followers_url = f'https://friends.roblox.com/v1/users/{user_id}/followers?limit=100&cursor={cursor}'
response = api_request(followers_url)
data = response.json()
followers.extend(data['data'])
cursor = data.get('nextPageCursor')
if not cursor:
break
return followers
# Function to get all friends with pagination
def get_all_friends(user_id):
friends = []
cursor = ""
while True:
friends_url = f'https://friends.roblox.com/v1/users/{user_id}/friends?limit=100&cursor={cursor}'
response = api_request(friends_url)
data = response.json()
friends.extend(data['data'])
cursor = data.get('nextPageCursor')
if not cursor:
break
return friends
# Function to check if a user is a bot
def is_bot(follower_id):
url = f'https://friends.roblox.com/v1/users/{follower_id}/followers/count'
followers_response = api_request(url)
followers_count = followers_response.json().get('count', 0)
url = f'https://friends.roblox.com/v1/users/{follower_id}/friends/count'
friends_response = api_request(url)
friends_count = friends_response.json().get('count', 0)
return followers_count == 0 and friends_count == 0
# Get list of all followers and friends
followers = get_all_followers(user_id)
friends = get_all_friends(user_id)
friend_ids = {friend['id'] for friend in friends}
# Block and unblock each follower who is not a friend and is a bot
block_url = 'https://accountsettings.roblox.com/v1/users/{userId}/block'
unblock_url = 'https://accountsettings.roblox.com/v1/users/{userId}/unblock'
for follower in followers:
follower_id = follower['id']
if follower_id not in friend_ids:
if is_bot(follower_id):
# Block the user
block_response = api_request(block_url.format(userId=follower_id), method='POST', data={"userId": follower_id})
print(f'Blocked bot user {follower_id}')
# Wait for 5 seconds
time.sleep(5)
# Unblock the user
unblock_response = api_request(unblock_url.format(userId=follower_id), method='POST', data={"userId": follower_id})
print(f'Unblocked bot user {follower_id}')
else:
print(f'Skipped non-bot follower {follower_id}')
else:
print(f'Skipped friend {follower_id}')
Very cool! I’d like to have a version of the bot detector that uses different conditions. Basically, if the user has no experience badges AND the user has no followers AND the user isn’t in any group AND the user follows more than 500 users, then run the unfollow code on them.
Would this be easy to implement? Also, what application should I use to run this code on Mac?