[GH-ISSUE #726] Spotipy Search Method fails to find results containing a Right Single Quotation Mark #437

Open
opened 2026-02-27 23:22:38 +03:00 by kerem · 6 comments
Owner

Originally created by @jospkelly on GitHub (Sep 8, 2021).
Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/726

Bug Description
I am using Spotipy to build code that fetches Spotify Track IDs and generates a playlist. My input is a list of track information extracted from my Plex server.

I discovered that the Spotipy Search Method fails to return a track if the Track Name contains a Right Single Quotation Mark (i.e., a punctuation mark commonly used in contractions).

My Code (example)

artist = 'Broods'
track = 'Couldn’t Believe'
album = 'Conscious'
track_info_sp = sp.search(q='artist:' + artist + ' track:' + track + ' album:' + album, type='track', limit=25)

Expected Behavior
The code should return a dictionary with one track item:

track_info_sp['tracks']['items'][0]['id']
'2SCblOXQDX2ToK7JvqCksw'

Actual Behavior
The code does not locate the track, and returns a dictionary with zero track items:

track_info_sp['tracks']['items'][0]['id']
Traceback (most recent call last):
  File "/Applications/PyCharm CE.app/Contents/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_exec2.py", line 3, in Exec
    exec(exp, global_vars, local_vars)
  File "<input>", line 1, in <module>
IndexError: list index out of range

Environment:
OS = MacOS Big Sur 11.3
Python = version 3.8
Spotipy = version 2.19.0
IDE = Pycharm

Additional Context
If I remove the Right Single Quotation Mark from the track name:

artist = 'Broods'
track = 'Couldn t Believe'
album = 'Conscious'
track_info_sp = sp.search(q='artist:' + artist + ' track:' + track + ' album:' + album, type='track', limit=25)

The Search Method returns the expected response:

track_info_sp['tracks']['items'][0]['id']
'2SCblOXQDX2ToK7JvqCksw'

It appears that when Spotipy encodes the URL for use by the API, the Right Single Quotation Mark is converted to %E2%80%99:

artist = 'Broods'
track = 'Couldn’t Believe'
album = 'Conscious'
track_info_sp = sp.search(q='artist:' + artist + ' track:' + track + ' album:' + album, type='track', limit=25)

track_info_sp['tracks']['href']
'https://api.spotify.com/v1/search?query=artist%3ABroods+track%3ACouldn%E2%80%99t+Believe+album%3AConscious&type=track&offset=0&limit=25'
Originally created by @jospkelly on GitHub (Sep 8, 2021). Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/726 **Bug Description** I am using Spotipy to build code that fetches Spotify Track IDs and generates a playlist. My input is a list of track information extracted from my Plex server. I discovered that the Spotipy Search Method fails to return a track if the Track Name contains a _Right Single Quotation Mark_ (i.e., a punctuation mark commonly used in contractions). **My Code (example)** ``` artist = 'Broods' track = 'Couldn’t Believe' album = 'Conscious' track_info_sp = sp.search(q='artist:' + artist + ' track:' + track + ' album:' + album, type='track', limit=25) ``` **Expected Behavior** The code should return a dictionary with one track item: ``` track_info_sp['tracks']['items'][0]['id'] '2SCblOXQDX2ToK7JvqCksw' ``` **Actual Behavior** The code does not locate the track, and returns a dictionary with zero track items: ``` track_info_sp['tracks']['items'][0]['id'] Traceback (most recent call last): File "/Applications/PyCharm CE.app/Contents/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_exec2.py", line 3, in Exec exec(exp, global_vars, local_vars) File "<input>", line 1, in <module> IndexError: list index out of range ``` **Environment:** OS = MacOS Big Sur 11.3 Python = version 3.8 Spotipy = version 2.19.0 IDE = Pycharm **Additional Context** If I remove the _Right Single Quotation Mark_ from the track name: ``` artist = 'Broods' track = 'Couldn t Believe' album = 'Conscious' track_info_sp = sp.search(q='artist:' + artist + ' track:' + track + ' album:' + album, type='track', limit=25) ``` The Search Method returns the expected response: ``` track_info_sp['tracks']['items'][0]['id'] '2SCblOXQDX2ToK7JvqCksw' ``` It appears that when Spotipy encodes the URL for use by the API, the _Right Single Quotation Mark_ is converted to %E2%80%99: ``` artist = 'Broods' track = 'Couldn’t Believe' album = 'Conscious' track_info_sp = sp.search(q='artist:' + artist + ' track:' + track + ' album:' + album, type='track', limit=25) track_info_sp['tracks']['href'] 'https://api.spotify.com/v1/search?query=artist%3ABroods+track%3ACouldn%E2%80%99t+Believe+album%3AConscious&type=track&offset=0&limit=25' ```
Author
Owner

@Peter-Schorn commented on GitHub (Sep 8, 2021):

The track you are searching for does not contain a RIGHT SINGLE QUOTATION MARK. It contains an apostrophe. That's why including the former in your search query does not return the track. Furthermore, I created a playlist with a RIGHT SINGLE QUOTATION MARK and was able to successfully retrieve it using the search function. This character is percent-encoded correctly.

<!-- gh-comment-id:915399602 --> @Peter-Schorn commented on GitHub (Sep 8, 2021): The track you are searching for does not contain a *RIGHT SINGLE QUOTATION MARK*. It contains an apostrophe. That's why including the former in your search query does not return the track. Furthermore, I created a playlist with a *RIGHT SINGLE QUOTATION MARK* and was able to successfully retrieve it using the `search` function. This character is percent-encoded correctly.
Author
Owner

@jospkelly commented on GitHub (Sep 8, 2021):

The track you are searching for does not contain a RIGHT SINGLE QUOTATION MARK. It contains an apostrophe. That's why including the former in your search query does not return the track. Furthermore, I created a playlist with a RIGHT SINGLE QUOTATION MARK and was able to successfully retrieve it using the search function. This character is percent-encoded correctly.

@Peter-Schorn - %E2%80%99 is described as a RIGHT SINGLE QUOTATION MARK HERE and HERE. I did find a second reference HERE that describes the character as an apostrophe and as a Right Single Quote. This is the character stored in my Plex database for this track.
Please let me know the encoding of the character that you used successfully for your search.

If I change my search to this (change the character to an apostrophe, %27, as defined HERE):
artist = 'Broods'
track = "Couldn't Believe"
album = 'Conscious'
track_info_sp = sp.search(q='artist:' + artist + ' track:' + track + ' album:' + album, type='track', limit=25)
``
The search returns no track results:

track_info_sp['tracks']['items'][0]['id']
Traceback (most recent call last):
  File "/Applications/PyCharm CE.app/Contents/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_exec2.py", line 3, in Exec
    exec(exp, global_vars, local_vars)
  File "<input>", line 1, in <module>
IndexError: list index out of range

and the returned dictionary shows this as the href :

track_info_sp['tracks']['href']
'https://api.spotify.com/v1/search?query=artist%3ABroods+track%3ACouldn%27t+Believe+album%3AConscious&type=track&offset=0&limit=25'

<!-- gh-comment-id:915447523 --> @jospkelly commented on GitHub (Sep 8, 2021): > The track you are searching for does not contain a _RIGHT SINGLE QUOTATION MARK_. It contains an apostrophe. That's why including the former in your search query does not return the track. Furthermore, I created a playlist with a _RIGHT SINGLE QUOTATION MARK_ and was able to successfully retrieve it using the `search` function. This character is percent-encoded correctly. @Peter-Schorn - %E2%80%99 is described as a _RIGHT SINGLE QUOTATION MARK_ [HERE](http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=2019&mode=hex) and [HERE](https://www.fileformat.info/info/unicode/char/2019/index.htm). I did find a second reference [HERE](https://www.real-world-systems.com/docs/Characters.html) that describes the character as an apostrophe and as a Right Single Quote. This is the character stored in my Plex database for this track. **Please let me know the encoding of the character that you used successfully for your search.** If I change my search to this (change the character to an apostrophe, %27, as defined [HERE](https://www.fileformat.info/info/unicode/char/27/index.htm)): artist = 'Broods' track = "Couldn't Believe" album = 'Conscious' track_info_sp = sp.search(q='artist:' + artist + ' track:' + track + ' album:' + album, type='track', limit=25) `` The search returns no track results: ``` track_info_sp['tracks']['items'][0]['id'] Traceback (most recent call last): File "/Applications/PyCharm CE.app/Contents/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_exec2.py", line 3, in Exec exec(exp, global_vars, local_vars) File "<input>", line 1, in <module> IndexError: list index out of range ``` and the returned dictionary shows this as the href : ``` track_info_sp['tracks']['href'] 'https://api.spotify.com/v1/search?query=artist%3ABroods+track%3ACouldn%27t+Believe+album%3AConscious&type=track&offset=0&limit=25' ```
Author
Owner

@Peter-Schorn commented on GitHub (Sep 8, 2021):

%E2%80%99 is described as a RIGHT SINGLE QUOTATION MARK.

Yes, as I said, this is the correct percent-encoding for this character.

This is the character stored in my Plex database for this track.

It doesn't matter what you have stored in your Plex database. What matters is that the name of the track in the Spotify content catalog (and everywhere else I can find it) is Couldn't Believe (with an apostrophe, not a RIGHT SINGLE QUOTATION MARK).

If I change my search to this (change the character to an apostrophe, %27, as defined HERE):

artist = 'Broods'
track = "Couldn't Believe"
album = 'Conscious'
track_info_sp = sp.search(q='artist:' + artist + ' track:' + track + ' album:' + album, type='track', limit=25)

The search returns no track results:

I also didn't get any results. This is a bug, but not with spotipy. This is a bug with the Spotify web API.

Interestingly, this does return the track you're looking for. I can't explain why.

artist = 'BROODS'
track = "Couldn't Believe"
album = 'Conscious'
query = f'{track} {artist} {album}'
track_info = sp.search(q=query, type='track', limit=25)
<!-- gh-comment-id:915495741 --> @Peter-Schorn commented on GitHub (Sep 8, 2021): > %E2%80%99 is described as a RIGHT SINGLE QUOTATION MARK. Yes, as I said, this is the correct percent-encoding for this character. > This is the character stored in my Plex database for this track. It doesn't matter what you have stored in your Plex database. What matters is that the name of the track in the Spotify content catalog (and everywhere else I can find it) is `Couldn't Believe` (with an apostrophe, not a *RIGHT SINGLE QUOTATION MARK*). > If I change my search to this (change the character to an apostrophe, %27, as defined HERE): > ```python > artist = 'Broods' > track = "Couldn't Believe" > album = 'Conscious' > track_info_sp = sp.search(q='artist:' + artist + ' track:' + track + ' album:' + album, type='track', limit=25) > ``` > The search returns no track results: I also didn't get any results. This *is* a bug, but not with spotipy. This is a bug with the Spotify web API. Interestingly, this does return the track you're looking for. I can't explain why. ```python artist = 'BROODS' track = "Couldn't Believe" album = 'Conscious' query = f'{track} {artist} {album}' track_info = sp.search(q=query, type='track', limit=25) ```
Author
Owner

@jospkelly commented on GitHub (Sep 8, 2021):

Interestingly, this does return the track you're looking for. I can't explain why.

artist = 'BROODS'
track = "Couldn't Believe"
album = 'Conscious'
query = f'{track} {artist} {album}'
track_info = sp.search(q=query, type='track', limit=25)

@Peter-Schorn - Thanks for the response. I noticed that for the successful search, Spotipy does not create and send the same href message to the Spotify API – it does not the strings as field filters:

artist = 'BROODS'
track = "Couldn't Believe"
album = 'Conscious'
query = f'{track} {artist} {album}'
track_info = sp.search(q=query, type='track', limit=25)
track_info['tracks']['href']
'https://api.spotify.com/v1/search?query=Couldn%27t+Believe+BROODS+Conscious&type=track&offset=0&limit=25'

If I construct my command like you did (but instead using a Right Single Quotation Mark instead on an apostrophe), I also get the expected result:

artist = 'BROODS'
track = 'Couldn’t Believe'
album = 'Conscious'
query = f'{track} {artist} {album}'
track_info = sp.search(q=query, type='track', limit=25)
track_info['tracks']['href']
'https://api.spotify.com/v1/search?query=Couldn%E2%80%99t+Believe+BROODS+Conscious&type=track&offset=0&limit=25'
track_info['tracks']['items'][0]['id']
'2SCblOXQDX2ToK7JvqCksw'

If I omit the field filters and just pass the artist, track, and album as strings in the q, either form of the contraction Couldn’t will fetch the expected result.

<!-- gh-comment-id:915560410 --> @jospkelly commented on GitHub (Sep 8, 2021): > Interestingly, this does return the track you're looking for. I can't explain why. > > ```python > artist = 'BROODS' > track = "Couldn't Believe" > album = 'Conscious' > query = f'{track} {artist} {album}' > track_info = sp.search(q=query, type='track', limit=25) > ``` @Peter-Schorn - Thanks for the response. I noticed that for the successful search, Spotipy does not create and send the same href message to the Spotify API – it does not the strings as field filters: ``` artist = 'BROODS' track = "Couldn't Believe" album = 'Conscious' query = f'{track} {artist} {album}' track_info = sp.search(q=query, type='track', limit=25) track_info['tracks']['href'] 'https://api.spotify.com/v1/search?query=Couldn%27t+Believe+BROODS+Conscious&type=track&offset=0&limit=25' ``` If I construct my command like you did (but instead using a Right Single Quotation Mark instead on an apostrophe), I also get the expected result: ``` artist = 'BROODS' track = 'Couldn’t Believe' album = 'Conscious' query = f'{track} {artist} {album}' track_info = sp.search(q=query, type='track', limit=25) track_info['tracks']['href'] 'https://api.spotify.com/v1/search?query=Couldn%E2%80%99t+Believe+BROODS+Conscious&type=track&offset=0&limit=25' track_info['tracks']['items'][0]['id'] '2SCblOXQDX2ToK7JvqCksw' ``` If I omit the field filters and just pass the `artist`, `track`, and `album` as strings in the `q`, either form of the contraction `Couldn’t` will fetch the expected result.
Author
Owner

@Earthscott commented on GitHub (Nov 14, 2021):

I agree there's some sort of bug on Spotify's end.

I ran a ~40,000 song dataset with song title and artist through sp.search() two nights ago. About 10,000 failed, a third of which have an apostrophe (my dataset doesn't have any right single quotation marks). Also worth noting, over 3,000 of my successful matches did have an apostrophe, so it's not a global problem.

This is my query string:

query = f"track:{song} artist:{artist}"

I just did some testing with Don't Be Cruel by Elvis Presley, which fails. (using the right single quotation mark also fails). If I search for just Elvis Presley, Don't Be Cruel shows up first as the 18th item (apostrophe). Interestingly, if I search for just Don't be cruel (either punctuation mark), I get back 20 results (all covers), 19 of which have the right single quotation mark and 1 of which has the left single quotation mark.

Removing the quotation mark does work as noted by @jospkelly (I used Dont Be Cruel). This also works in testing with a few other songs. I'll rerun the failed items without the punctuation mark within the next few days and let y'all know how it goes.

<!-- gh-comment-id:968353669 --> @Earthscott commented on GitHub (Nov 14, 2021): I agree there's some sort of bug on Spotify's end. I ran a ~40,000 song dataset with song title and artist through sp.search() two nights ago. About 10,000 failed, a third of which have an apostrophe (my dataset doesn't have any right single quotation marks). Also worth noting, over 3,000 of my successful matches did have an apostrophe, so it's not a global problem. This is my query string: `query = f"track:{song} artist:{artist}"` I just did some testing with _Don't Be Cruel_ by _Elvis Presley_, which fails. (using the right single quotation mark also fails). If I search for just _Elvis Presley_, `Don't Be Cruel` shows up first as the 18th item (apostrophe). Interestingly, if I search for just _Don't be cruel_ (either punctuation mark), I get back 20 results (all covers), 19 of which have the right single quotation mark and 1 of which has the left single quotation mark. Removing the quotation mark does work as noted by @jospkelly (I used _Dont Be Cruel_). This also works in testing with a few other songs. I'll rerun the failed items without the punctuation mark within the next few days and let y'all know how it goes.
Author
Owner

@bghill commented on GitHub (Aug 15, 2022):

Punctuation encoding aside, in the answers listed here, many are ditching Spotify's query field system. It seems like request as library isn't a great match for how Spotify wants to do queries. The API docs seem to be clear about encoding of query field filters.

Spotify wants a : between a field and the value, a + between field/value pairs, and standard URL encoding for the song titles and artist names (e.g. %20 for spaces). Spotify is trying to do its best when Spotipy queries come in mangled. If you add the :, request encodes it. There doesn't seem to be a way to encode things yourself instead. If you put %20 into the song titles with something like urllib.parse.quote(), then request will just encode your encoding. So people are just dropping the field names and getting much messier results. Or they leave them in but I think Spotify is just adding another word to the overall search.

When send the queries by hand via Spotify requests using Curl, I get tight, accurate results.

Anyone know how to get request to stop trying to be so smart on our behalf? Does it make sense to detect more elaborate queries and bypass request's encoding via one of the suggestions here?

<!-- gh-comment-id:1215598849 --> @bghill commented on GitHub (Aug 15, 2022): Punctuation encoding aside, in the answers listed here, many are ditching Spotify's query field system. It seems like `request` as library isn't a great match for how Spotify wants to do queries. The API docs seem to be clear about encoding of [query field filters](https://developer.spotify.com/documentation/web-api/reference/#/operations/search). Spotify wants a `:` between a field and the value, a `+` between field/value pairs, and standard URL encoding for the song titles and artist names (e.g. `%20` for spaces). Spotify is trying to do its best when Spotipy queries come in mangled. If you add the `:`, `request` encodes it. There doesn't seem to be a way to encode things yourself instead. If you put `%20` into the song titles with something like `urllib.parse.quote()`, then `request` will just encode your encoding. So people are just dropping the field names and getting much messier results. Or they leave them in but I think Spotify is just adding another word to the overall search. When send the queries by hand via [Spotify requests using Curl](https://stackoverflow.com/questions/67128486/connect-to-spotify-api-with-command-line), I get tight, accurate results. Anyone know how to get `request` to stop trying to be so smart on our behalf? Does it make sense to detect more elaborate queries and bypass `request`'s encoding via one of the suggestions [here](https://stackoverflow.com/questions/23496750/how-to-prevent-python-requests-from-percent-encoding-my-urls)?
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/spotipy#437
No description provided.