├── .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 |
--------------------------------------------------------------------------------