download most played beatmaps This article provides a Python script that downloads a specified number of a user's most played beatmaps from the game osu! using the osu.py library and the osu API v2. The script requires the user to input their API client ID and secret, then prompts for a username and the number of beatmaps to download, saving them as .osz files in a local folder. It includes error handling and rate limiting to avoid exceeding one request per second. download most played.py 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 Show hidden characters """ Requires osu.py https://github.com/sheppsu/osu.py Can install via pip with "pip install osu.py" Also must insert your osu api v2 client id and client secret below where it says "CLIENT ID" and "CLIENT SECRET." You can get a client id and client secret via your settings on the osu website, at the bottom, where it says "OAuth." """ from osu import Client, UserBeatmapType import requests import os import time CLIENT ID = 0 CLIENT SECRET = " " if CLIENT ID == 0: print "Edit the CLIENT ID and CLIENT SECRET variables before running the script. Read the docstring at the top of the file for more info." quit client = Client.from client credentials CLIENT ID, CLIENT SECRET, None def get user : user = input "User to fetch from username : " .strip try: user = client.get user user, key="username" except: print "Unable to find a user by that name" return return user def get limit : while True: try: return int input "Number of beatmaps to download: " .strip except ValueError: print "Input a valid integer" def yield beatmaps user id, limit : cnt = 0 while limit-cnt 0: max limit = min 50, limit-cnt for beatmap in client.get user beatmaps user id, UserBeatmapType.MOST PLAYED, max limit, cnt : yield beatmap cnt += max limit def download beatmapset beatmap : attempts = 0 while True: try: resp = requests.get f"https://catboy.best/d/{beatmap.beatmapset.id}" except Exception as exc: print "Failed to download: ", exc print "Retrying in a second..." time.sleep 1 continue map string = f"{beatmap.beatmapset.artist} - {beatmap.beatmapset.title} {beatmap.beatmapset.id} " returns 200, 404, or 500 according to docs if resp.status code == 200: with open f"beatmap downloads/{beatmap.beatmapset.id}.osz", "wb" as f: for chunk in resp.iter content 4096 : f.write chunk print f"Downloaded {map string}" break elif resp.status code == 404: print f"Unable to find {map string}" elif resp.status code == 500: print f"The api returned a server error for {map string}" else: print f"Failed to download {map string} HTTP {resp.status code}" attempts += 1 if attempts == 3: break print "Trying again in a second..." time.sleep 1 if not os.path.isdir "beatmap downloads" : os.mkdir "beatmap downloads" user = get user limit = get limit beatmapsets downloaded = for beatmap in yield beatmaps user.id, limit : if beatmap.beatmapset.id in beatmapsets downloaded: continue beatmapsets downloaded.append beatmap.beatmapset.id start = time.monotonic download beatmapset beatmap time.sleep max 1 - time.monotonic - start , 0 stay under 1 request per second print "Finished downloading "