├── .gitignore ├── README.md ├── follow_bot.py ├── main.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | accounts.txt 3 | *.pyc 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | ## Based on useragents' [spotify bot](https://github.com/useragents/Proxyless-Spotify-Follow-Bot). 5 | 6 |
7 | 8 | ## TODO 9 | 10 | - [x] Follow Playlist 11 | - [ ] Proxies 12 | 13 |
14 | 15 | ## Installation 16 | 17 | ```bash 18 | git clone https://github.com/Qoft/Spotify-Follow-Bot.git 19 | pip install -r requirements.txt 20 | py main.py 21 | ``` 22 | 23 |
24 | 25 | ### Please note 26 | 27 | This script was made for educational purposes, I am not responsible for your actions using this script. 28 |
29 | -------------------------------------------------------------------------------- /follow_bot.py: -------------------------------------------------------------------------------- 1 | import requests, random, string 2 | 3 | class spotify: 4 | 5 | def __init__(self, profile=None, playlist=None): 6 | self.session = requests.Session() 7 | self.playlist = playlist 8 | self.profile = profile 9 | 10 | def register_account(self): 11 | headers = { 12 | "Accept": "*/*", 13 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36", 14 | "Content-Type": "application/x-www-form-urlencoded", 15 | "Referer": "https://www.spotify.com/" 16 | } 17 | email = ("").join(random.choices(string.ascii_letters + string.digits, k = 8)) + "@gmail.com" 18 | data = f"birth_day=1&birth_month=01&birth_year=1970&collect_personal_info=undefined&creation_flow=&creation_point=https://www.spotify.com/uk/&displayname=qoftgenlol&email={email}&gender=neutral&iagree=1&key=a1e486e2729f46d6bb368d6b2bcda326&password=D8c7mc82chb4sdX2Q&password_repeat=D8c7mc82chb4sdX2Q&platform=www&referrer=&send-email=1&thirdpartyemail=0&fb=0" 19 | try: 20 | create = self.session.post( 21 | "https://spclient.wg.spotify.com/signup/public/v1/account", 22 | headers = headers, 23 | data = data 24 | ) 25 | return create.json()['login_token'] 26 | except: 27 | return None 28 | 29 | def get_csrf_token(self): 30 | try: 31 | r = self.session.get("https://www.spotify.com/uk/signup/?forward_url=https://accounts.spotify.com/en/status&sp_t_counter=1") 32 | return r.text.split('csrfToken":"')[1].split('"')[0] 33 | except: 34 | return None 35 | 36 | def get_token(self, login_token): 37 | headers = { 38 | "Accept": "*/*", 39 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36", 40 | "Content-Type": "application/x-www-form-urlencoded", 41 | "X-CSRF-Token": self.get_csrf_token(), 42 | "Host": "www.spotify.com" 43 | } 44 | self.session.post("https://www.spotify.com/api/signup/authenticate", headers = headers, data = "splot=" + login_token) 45 | headers = { 46 | "accept": "application/json", 47 | "Accept-Encoding": "gzip, deflate, br", 48 | "accept-language": "en", 49 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36", 50 | "spotify-app-version": "1.1.52.204.ge43bc405", 51 | "app-platform": "WebPlayer", 52 | "Host": "open.spotify.com", 53 | "Referer": "https://open.spotify.com/" 54 | } 55 | try: 56 | r = self.session.get( 57 | "https://open.spotify.com/get_access_token?reason=transport&productType=web_player", 58 | headers = headers 59 | ) 60 | return r.json()["accessToken"] 61 | except: 62 | return None 63 | 64 | def follow(self, sex = None): 65 | try: 66 | if "/user/" in self.profile: 67 | self.profile = self.profile.split("/user/")[1] 68 | if "?" in self.profile: 69 | self.profile = self.profile.split("?")[0] 70 | login_token = self.register_account() 71 | if login_token == None: 72 | return None 73 | auth_token = self.get_token(login_token) 74 | if auth_token == None: 75 | return None 76 | if sex: 77 | auth_token = sex 78 | headers = { 79 | "accept": "application/json", 80 | "Accept-Encoding": "gzip, deflate, br", 81 | "accept-language": "en", 82 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36", 83 | "app-platform": "WebPlayer", 84 | "Referer": "https://open.spotify.com/", 85 | "spotify-app-version": "1.1.52.204.ge43bc405", 86 | "authorization": "Bearer {}".format(auth_token.replace("\n", "")), 87 | } 88 | try: 89 | d = self.session.put( 90 | "https://api.spotify.com/v1/me/following?type=user&ids=" + self.profile, 91 | headers = headers 92 | ) 93 | return True 94 | except Exception as e: 95 | print(e) 96 | return False 97 | except Exception as e: 98 | print(e) 99 | def follow_playlist(self): 100 | if "/playlist/" in self.playlist: 101 | self.playlist = self.playlist.split("/playlist/")[1] 102 | if "?" in self.playlist: 103 | self.playlist = self.playlist.split("?")[0] 104 | login_token = self.register_account() 105 | if login_token == None: 106 | return None 107 | auth_token = self.get_token(login_token) 108 | if auth_token == None: 109 | return None 110 | headers = { 111 | "accept": "application/json", 112 | "Accept-Encoding": "gzip, deflate, br", 113 | "accept-language": "en", 114 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36", 115 | "app-platform": "WebPlayer", 116 | "Referer": "https://open.spotify.com/", 117 | "spotify-app-version": "1.1.52.204.ge43bc405", 118 | "authorization": "Bearer {}".format(auth_token), 119 | } 120 | try: 121 | self.session.put( 122 | "https://api.spotify.com/v1/playlists/%s/followers" % (self.playlist,), 123 | headers = headers 124 | ) 125 | return True 126 | except: 127 | return False 128 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from re import T 2 | from follow_bot import spotify 3 | import threading, os, time 4 | 5 | 6 | 7 | lock = threading.Lock() 8 | counter = 0 9 | 10 | 11 | 12 | class ThreadWithResult(threading.Thread): 13 | def __init__(self, group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None): 14 | def function(): 15 | self.result = target(*args, **kwargs) 16 | super().__init__(group=group, target=function, name=name, daemon=daemon) 17 | 18 | 19 | def safe_print(arg): 20 | lock.acquire() 21 | print(arg) 22 | lock.release() 23 | 24 | 25 | def thread_follow(account): 26 | global counter 27 | obj = spotify(account) 28 | result = obj.follow() 29 | if result: 30 | counter += 1 31 | safe_print("Followed {}".format(counter)) 32 | else: 33 | print(result) 34 | safe_print("Error") 35 | 36 | 37 | def follow_user(account: str, threads: int): 38 | while True: 39 | if threading.active_count() <= threads: 40 | try: 41 | threading.Thread(target = thread_follow, args=(account, )).start() 42 | except Exception as e: 43 | print(e) 44 | safe_print("Error") 45 | 46 | def thread_follow_authtoken(account: str, token: str): 47 | global counter 48 | obj = spotify(profile=account) 49 | result = obj.follow(token) 50 | if result: 51 | counter += 1 52 | safe_print("Followed {}".format(counter)) 53 | else: 54 | safe_print("Error") 55 | 56 | 57 | def follow_user_authtoken(account): 58 | with open("accounts.txt", "r") as f: 59 | for line in f: 60 | try: 61 | threading.Thread(target = thread_follow_authtoken, args=(account, line, )).start() 62 | except: 63 | safe_print("Error") 64 | 65 | def thread_create(): 66 | try: 67 | global counter 68 | obj = spotify() 69 | result = obj.register_account() 70 | auth_token = obj.get_token(result) 71 | if auth_token != None: 72 | with open("accounts.txt", "a") as f: 73 | f.write(f"\n{auth_token}") 74 | counter += 1 75 | safe_print("Created {}".format(counter)) 76 | 77 | except Exception as e: 78 | print(e) 79 | 80 | 81 | def create_account(threads: int): 82 | while True: 83 | if threading.active_count() <= threads: 84 | try: 85 | threading.Thread(target = thread_create).start() 86 | except: 87 | safe_print("Error") 88 | 89 | 90 | def thread_follow_playlist(playlistd): 91 | try: 92 | global counter 93 | obj = spotify(playlist=playlistd) 94 | result = obj.register_account() 95 | auth_token = obj.get_token(result) 96 | result = obj.follow_playlist() 97 | if result: 98 | counter += 1 99 | safe_print("Followed {}".format(counter)) 100 | else: 101 | safe_print("Error") 102 | except Exception as e: 103 | print(e) 104 | 105 | 106 | def follow_playlist(playlist, threads: int): 107 | while True: 108 | if threading.active_count() <= threads: 109 | try: 110 | threading.Thread(target = thread_follow_playlist, args=(playlist, )).start() 111 | except: 112 | safe_print("Error") 113 | 114 | def clear(): 115 | os.system("cls" if os.name == "nt" else "clear") 116 | 117 | 118 | 119 | def main(): 120 | print("1. Follow Accounts") 121 | print("2. Follow Playlist") 122 | print("3. Create accounts") 123 | print("4. Follow accounts from file") 124 | userinpt = int(input("")) 125 | clear() 126 | if userinpt == 1: 127 | threads = input("Threads: ") 128 | account = input("Account: ") 129 | follow_user(account, int(threads)) 130 | elif userinpt == 2: 131 | playlist = input("Playlist: ") 132 | threads = input("\nThreads: ") 133 | follow_playlist(playlist, int(threads)) 134 | elif userinpt == 3: 135 | threads = input("\nThreads: ") 136 | create_account(int(threads)) 137 | elif userinpt == 4: 138 | account = input("Account: ") 139 | follow_user_authtoken(account) 140 | else: 141 | print("Invalid input"); time.sleep(1); clear(); main() 142 | if __name__ == "__main__": 143 | main() -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.27.1 2 | --------------------------------------------------------------------------------