Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

429/500/404 Errors and Rate Limiting Issues #2142

Open
xnetcat opened this issue Jul 21, 2024 · 16 comments
Open

429/500/404 Errors and Rate Limiting Issues #2142

xnetcat opened this issue Jul 21, 2024 · 16 comments
Labels
Feature Request Feature Request

Comments

@xnetcat
Copy link
Member

xnetcat commented Jul 21, 2024

Hey everyone,

I've been seeing more 429/404/500 errors, and slow query processing lately. This is because of Spotify's rate limits on our shared project.

Quick Fix: Use Your Own Client ID and Secret

To avoid these issues, we recommend using your own client ID and secret from Spotify. Here’s how:

  1. Visit the Spotify Developer Dashboard: Go to Spotify Developer Dashboard.
  2. Log In: Sign in or create a Spotify account.
  3. Create a New App: Click "Create an App" and fill in the details. (Set APIs used to Web API and Redirect URIs to http://127.0.0.1:9900/ (or whatever you want to use))
  4. Get Your Credentials: Copy your client ID and secret.

Update Your Settings:

  1. Config File: Update your settings in the config file as described here.
  2. Command Line Options: Alternatively, use the following command line options:
    --client-id CLIENT_ID
    --client-secret CLIENT_SECRET
    

I’m working on a long-term fix to better manage our rate limits. Stay tuned for updates!

@ForceConstant
Copy link

I am confused, since I thought downloads are from youtube these days, what is the spotify key used for?

@xnetcat
Copy link
Member Author

xnetcat commented Jul 21, 2024

I am confused, since I thought downloads are from youtube these days, what is the spotify key used for?

Getting the metadata from Spotify. We can't do that without authorization.

@flowerpoweruk
Copy link

thank you @xnetcat this worked perfectly to resolve the issue.

@unsync
Copy link

unsync commented Jul 23, 2024

i've been getting the same behaviour (sync hanging after DEBUG MainThread - Found 50 songs in 1 lists).

i'm rotating 3 different spotify apps, but still doesn't (always) helps.

any chance we could get some debug logs that could warn about the process being stuck and the reason ? (i guess if we don't get a console feedback after 30 minutes the issue is clear, but avoiding the infinite hanging would be nice)

@xnetcat xnetcat changed the title 429/500 Errors and Rate Limiting Issues 429/500/404 Errors and Rate Limiting Issues Jul 30, 2024
@square-nine
Copy link

For anyone else having issues with the 429 Too Many Requests error:
I just did this: #2139 (comment)
And also what was recommended as the "quick fix" (first post in this issue)

And now, this works for small albums, but when I try on a larger playlist (like my 300+ liked songs) it returns the 429 error. No matter, for if that's the case, it's probably better to split your liked songs playlist into several smaller public playlists, to then download sequentially.

@eltrueno
Copy link

eltrueno commented Sep 3, 2024

Fix doesn't work for me when searching for a song, only works if you enter album or song link. But still downloading very slowly compared to version 4.2.5

@lancelotimb
Copy link

FWIW, using the --user-auth option fixed the issue for me (specifying client id/secret did not work). You'd have to be logged in on your browser though.

@Wallvon
Copy link

Wallvon commented Oct 13, 2024

Using a client id + client secret or user auth doesn't work for me when using spotdl sync {filename}.spotdl. I keep getting the following 429 error:

Processing query: https://open.spotify.com/playlist/[redacted]
Max Retries reached

An error occurred
ResponseError: too many 429 error responses

The above exception was the direct cause of the following exception:

╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /opt/homebrew/lib/python3.11/site-packages/requests/adapters.py:667 in send  │
│                                                                              │
│   664 │   │   │   timeout = TimeoutSauce(connect=timeout, read=timeout)      │
│   665 │   │                                                                  │
│   666 │   │   try:                                                           │
│ ❱ 667 │   │   │   resp = conn.urlopen(                                       │
│   668 │   │   │   │   method=request.method,                                 │
│   669 │   │   │   │   url=url,                                               │
│   670 │   │   │   │   body=request.body,                                     │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/urllib3/connectionpool.py:948 in  │
│ urlopen                                                                      │
│                                                                              │
│    945 │   │   │   response.drain_conn()                                     │
│    946 │   │   │   retries.sleep(response)                                   │
│    947 │   │   │   log.debug("Retry: %s", url)                               │
│ ❱  948 │   │   │   return self.urlopen(                                      │
│    949 │   │   │   │   method,                                               │
│    950 │   │   │   │   url,                                                  │
│    951 │   │   │   │   body,                                                 │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/urllib3/connectionpool.py:948 in  │
│ urlopen                                                                      │
│                                                                              │
│    945 │   │   │   response.drain_conn()                                     │
│    946 │   │   │   retries.sleep(response)                                   │
│    947 │   │   │   log.debug("Retry: %s", url)                               │
│ ❱  948 │   │   │   return self.urlopen(                                      │
│    949 │   │   │   │   method,                                               │
│    950 │   │   │   │   url,                                                  │
│    951 │   │   │   │   body,                                                 │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/urllib3/connectionpool.py:948 in  │
│ urlopen                                                                      │
│                                                                              │
│    945 │   │   │   response.drain_conn()                                     │
│    946 │   │   │   retries.sleep(response)                                   │
│    947 │   │   │   log.debug("Retry: %s", url)                               │
│ ❱  948 │   │   │   return self.urlopen(                                      │
│    949 │   │   │   │   method,                                               │
│    950 │   │   │   │   url,                                                  │
│    951 │   │   │   │   body,                                                 │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/urllib3/connectionpool.py:938 in  │
│ urlopen                                                                      │
│                                                                              │
│    935 │   │   has_retry_after = bool(response.headers.get("Retry-After"))   │
│    936 │   │   if retries.is_retry(method, response.status, has_retry_after) │
│    937 │   │   │   try:                                                      │
│ ❱  938 │   │   │   │   retries = retries.increment(method, url, response=res │
│    939 │   │   │   except MaxRetryError:                                     │
│    940 │   │   │   │   if retries.raise_on_status:                           │
│    941 │   │   │   │   │   response.drain_conn()                             │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/urllib3/util/retry.py:515 in      │
│ increment                                                                    │
│                                                                              │
│   512 │   │                                                                  │
│   513 │   │   if new_retry.is_exhausted():                                   │
│   514 │   │   │   reason = error or ResponseError(cause)                     │
│ ❱ 515 │   │   │   raise MaxRetryError(_pool, url, reason) from reason  # typ │ignore[arg-type]                                                       │
│   516 │   │                                                                  │
│   517 │   │   log.debug("Incremented Retry for (url='%s'): %r", url, new_ret │
│   518                                                                        │
╰──────────────────────────────────────────────────────────────────────────────╯
MaxRetryError: HTTPSConnectionPool(host='api.spotify.com', port=443): Max
retries exceeded with url:
/v1/playlists/[redacted]?additional_types=track (Caused by
ResponseError('too many 429 error responses'))

During handling of the above exception, another exception occurred:

╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /opt/homebrew/lib/python3.11/site-packages/spotipy/client.py:270 in          │
│ _internal_call                                                               │
│                                                                              │
│    267 │   │   │   │   │    method, url, args.get("params"), headers, args.g │
│    268 │   │                                                                 │
│    269 │   │   try:                                                          │
│ ❱  270 │   │   │   response = self._session.request(                         │
│    271 │   │   │   │   method, url, headers=headers, proxies=self.proxies,   │
│    272 │   │   │   │   timeout=self.requests_timeout, **args                 │
│    273 │   │   │   )                                                         │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/requests/sessions.py:589 in       │
│ request                                                                      │
│                                                                              │
│   586 │   │   │   "allow_redirects": allow_redirects,                        │
│   587 │   │   }                                                              │
│   588 │   │   send_kwargs.update(settings)                                   │
│ ❱ 589 │   │   resp = self.send(prep, **send_kwargs)                          │
│   590 │   │                                                                  │
│   591 │   │   return resp                                                    │
│   592                                                                        │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/requests/sessions.py:703 in send  │
│                                                                              │
│   700 │   │   start = preferred_clock()                                      │
│   701 │   │                                                                  │
│   702 │   │   # Send the request                                             │
│ ❱ 703 │   │   r = adapter.send(request, **kwargs)                            │
│   704 │   │                                                                  │
│   705 │   │   # Total elapsed time of the request (approximately)            │706 │   │   elapsed = preferred_clock() - start                            │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/requests/adapters.py:691 in send  │
│                                                                              │
│   688 │   │   │   │   │   raise ConnectTimeout(e, request=request)           │
│   689 │   │   │                                                              │
│   690 │   │   │   if isinstance(e.reason, ResponseError):                    │
│ ❱ 691 │   │   │   │   raise RetryError(e, request=request)                   │
│   692 │   │   │                                                              │
│   693 │   │   │   if isinstance(e.reason, _ProxyError):                      │
│   694 │   │   │   │   raise ProxyError(e, request=request)                   │
╰──────────────────────────────────────────────────────────────────────────────╯
RetryError: HTTPSConnectionPool(host='api.spotify.com', port=443): Max retries
exceeded with url: /v1/playlists/[redacted]?additional_types=track
(Caused by ResponseError('too many 429 error responses'))

During handling of the above exception, another exception occurred:

╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /opt/homebrew/lib/python3.11/site-packages/spotdl/console/entry_point.py:160 │
│ in entry_point                                                               │
│                                                                              │
│   157try:                                                               │
│   158 │   │   # Pick the operation to perform                                │159 │   │   # based on the name and run it!                                │
│ ❱ 160 │   │   OPERATIONS[arguments.operation](                               │
│   161 │   │   │   query=arguments.query,                                     │
│   162 │   │   │   downloader=downloader,                                     │
│   163 │   │   )                                                              │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/spotdl/console/sync.py:109 in     │
│ sync                                                                         │
│                                                                              │
│   106 │   │   │   raise ValueError("Sync file is not a valid sync file.")    │
│   107 │   │                                                                  │
│   108 │   │   # Parse the query                                              │
│ ❱ 109 │   │   songs_playlist = parse_query(                                  │
│   110 │   │   │   query=sync_data["query"],                                  │
│   111 │   │   │   threads=downloader.settings["threads"],                    │
│   112 │   │   │   use_ytm_data=downloader.settings["ytm_data"],              │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/spotdl/utils/search.py:97 in      │
│ parse_query                                                                  │
│                                                                              │
│    94- List of song objects                                             │
│    95"""                                                                │
│    96 │                                                                      │
│ ❱  97 │   songs: List[Song] = get_simple_songs(                              │
│    98 │   │   query,                                                         │
│    99 │   │   use_ytm_data=use_ytm_data,                                     │
│   100 │   │   playlist_numbering=playlist_numbering,                         │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/spotdl/utils/search.py:260 in     │
│ get_simple_songs                                                             │
│                                                                              │
│   257 │   │   │   )                                                          │
│   258 │   │   │   songs.extend(full_lists)                                   │
│   259 │   │   elif "open.spotify.com" in request and "playlist" in request:  │
│ ❱ 260 │   │   │   lists.append(Playlist.from_url(request, fetch_songs=False) │
│   261 │   │   elif "open.spotify.com" in request and "album" in request:     │
│   262 │   │   │   lists.append(Album.from_url(request, fetch_songs=False))   │
│   263 │   │   elif "open.spotify.com" in request and "artist" in request:    │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/spotdl/types/song.py:306 in       │
│ from_url                                                                     │
│                                                                              │
│   303 │   │   - The SongList object.                                         │
│   304 │   │   """                                                            │
│   305 │   │                                                                  │
│ ❱ 306 │   │   metadata, songs = cls.get_metadata(url)                        │
│   307 │   │   urls = [song.url for song in songs]                            │
│   308 │   │                                                                  │
│   309 │   │   if fetch_songs:                                                │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/spotdl/types/playlist.py:48 in    │
│ get_metadata                                                                 │
│                                                                              │
│    45 │   │                                                                  │
│    46 │   │   spotify_client = SpotifyClient()                               │
│    47 │   │                                                                  │
│ ❱  48 │   │   playlist = spotify_client.playlist(url)                        │
│    49 │   │   if playlist is None:                                           │
│    50 │   │   │   raise PlaylistError("Invalid playlist URL.")               │
│    51                                                                        │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/spotipy/client.py:666 in playlist │
│                                                                              │
│    663 │   │   │   │   │   │   │   │   │    valid types are: track and episo │
│    664 │   │   """                                                           │
│    665 │   │   plid = self._get_id("playlist", playlist_id)                  │
│ ❱  666 │   │   return self._get(                                             │
│    667 │   │   │   f"playlists/{plid}",                                      │
│    668 │   │   │   fields=fields,                                            │
│    669 │   │   │   market=market,                                            │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/spotdl/utils/spotify.py:195 in    │
│ _get                                                                         │
│                                                                              │
│   192 │   │   retries = self.max_retries  # type: ignore # pylint: disable=E │
│   193 │   │   while response is None:                                        │
│   194 │   │   │   try:                                                       │
│ ❱ 195 │   │   │   │   response = self._internal_call("GET", url, payload, kw │
│   196 │   │   │   except (requests.exceptions.Timeout, requests.ConnectionEr │
│   197 │   │   │   │   retries -= 1                                           │
│   198 │   │   │   │   if retries <= 0:                                       │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/spotipy/client.py:311 in          │
│ _internal_call                                                               │
│                                                                              │
│    308 │   │   │   │   reason = retry_error.args[0].reason                   │
│    309 │   │   │   except (IndexError, AttributeError):                      │
│    310 │   │   │   │   reason = None                                         │
│ ❱  311 │   │   │   raise SpotifyException(                                   │
│    312 │   │   │   │   429,                                                  │
│    313 │   │   │   │   -1,                                                   │
│    314 │   │   │   │   f"{request.path_url}:\n Max Retries",                 │
╰──────────────────────────────────────────────────────────────────────────────╯
SpotifyException: http status: 429, code:-1 -
/v1/playlists/[redacted]?additional_types=track:
 Max Retries, reason: too many 429 error responses

I have already tried creating a new sync file to no avail:

SpotifyException: http status: 429, code:-1 -
/v1/playlists/[redacted]/tracks?offset=400&limit=100&additional_type
s=track:
Max Retries, reason: too many 429 error responses

@SudoZachCampbell
Copy link

Just want to chip in and say I'm having the same issue as @Wallvon, no auth solution is fixing the sync command for myself

@zigzag1001
Copy link
Contributor

I had the same issue as @Wallvon and @SudoZachCampbell, using my own Client ID and Secret, but it would still throw 429.

What fixed it for me was to use your own Client ID and Secret, and delete ~/.spotdl/.spotipy

@Wallvon
Copy link

Wallvon commented Oct 28, 2024

Hi, thanks for the comment. After having done that I am now getting a different error:

An error occurred
╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /opt/homebrew/lib/python3.11/site-packages/spotdl/console/entry_point.py:160 │
│ in entry_point                                                               │
│                                                                              │
│   157try:                                                               │
│   158 │   │   # Pick the operation to perform                                │159 │   │   # based on the name and run it!                                │
│ ❱ 160 │   │   OPERATIONS[arguments.operation](                               │
│   161 │   │   │   query=arguments.query,                                     │
│   162 │   │   │   downloader=downloader,                                     │
│   163 │   │   )                                                              │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/spotdl/console/sync.py:121 in     │
│ sync                                                                         │
│                                                                              │
│   118 │   │   old_files = []                                                 │
│   119 │   │   for entry in sync_data["songs"]:                               │
│   120 │   │   │   file_name = create_file_name(                              │
│ ❱ 121 │   │   │   │   Song.from_dict(entry),                                 │
│   122 │   │   │   │   downloader.settings["output"],                         │
│   123 │   │   │   │   downloader.settings["format"],                         │
│   124 │   │   │   │   downloader.settings["restrict"],                       │
│                                                                              │
│ /opt/homebrew/lib/python3.11/site-packages/spotdl/types/song.py:237 in       │
│ from_dict                                                                    │
│                                                                              │
│   234 │   │   """                                                            │
│   235 │   │                                                                  │
│   236 │   │   # Return product object                                        │
│ ❱ 237 │   │   return cls(**data)                                             │
│   238 │                                                                      │
│   239 │   @classmethod                                                       │
│   240 │   def from_missing_data(cls, **kwargs) -> "Song":                    │
╰──────────────────────────────────────────────────────────────────────────────╯
TypeError: Song.__init__() missing 1 required positional argument: 'album_type'

For further information:
I am running spotdl 4.2.8 on MacOS 15.0.1 and trying to use the sync command. I have also tried creating a new sync file, but after waiting for over 2 hours nothing has happened and it's still stuck on Found 1647 songs in [redacted] (Playlist).

@SudoZachCampbell
Copy link

SudoZachCampbell commented Oct 30, 2024

Once again I am matching @Wallvon, I am also seeing the same thing where it hangs on Found X songs in Y (Playlist). I have tried a different developer app, changing permissions for the app, rotating secrets, but I'm getting nothing back and the process becomes unkillable via command line

@zigzag1001
Copy link
Contributor

Once again I am matching @Wallvon, I am also seeing the same thing where it hangs on Found X songs in Y (Playlist). I have tried a different developer app, changing permissions for the app, rotating secrets, but I'm getting nothing back and the process becomes unkillable via command line

So it seems like the Spotify api is working correctly, have you tried to use yt-dlp to download something from YouTube? Recently, YouTube has also started flagging IPs and requiring you to be logged in. I got around this by using a proxy and passing it to spotdl through the config file.

@Wallvon
Copy link

Wallvon commented Oct 30, 2024

So it seems like the Spotify api is working correctly, have you tried to use yt-dlp to download something from YouTube? Recently, YouTube has also started flagging IPs and requiring you to be logged in. I got around this by using a proxy and passing it to spotdl through the config file.

Yes, I have coincidentally used yt-dlp an hour ago on the same machine which worked fine.

@Pineappleman123
Copy link

Pineappleman123 commented Nov 26, 2024

I had the same issue as @Wallvon and @SudoZachCampbell, using my own Client ID and Secret, but it would still throw 429.

What fixed it for me was to use your own Client ID and Secret, and delete ~/.spotdl/.spotipy

tried doing the deleting file, and also using own id and secret, but it still gives 429 and 404 errors, last time spotdl worked for me was Nov 14(havent used it since then till today)

@Pineappleman123
Copy link

I had the same issue as @Wallvon and @SudoZachCampbell, using my own Client ID and Secret, but it would still throw 429.
What fixed it for me was to use your own Client ID and Secret, and delete ~/.spotdl/.spotipy

tried doing the deleting file, and also using own id and secret, but it still gives 429 and 404 errors, last time spotdl worked for me was Nov 14(havent used it since then till today)

nvm, turns out it was a private playlist that caused the problem, just had to duplicate and make public

@spotDL spotDL deleted a comment from jordancartier23451 Nov 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Request Feature Request
Projects
None yet
Development

No branches or pull requests