Ability to easily remove multiple followers at once

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.

11 Likes

You can try using plugins like RoSeal in the meanwhile to get around this. RoSeal has a multi-select feature for removing followers.


Back to the topic, yes it’s honestly something overlooked by Roblox. This shouldn’t be such a hassle to normal users.

Oh, maybe it was because I used a combination of BTRoblox and Roseal to multi-select followers. Sorry for the confusion…

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.

3 Likes

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}')

2 Likes

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?

I guess you could use ChatGPT to help you implement this check. As for whether or not it’ll work on Mac, I’m not sure.

Which application did you use to run your Python code?
Edit: Never mind, I’ll search for Python applications on Mac