JMPerez / spotify-web-api-js

A client-side JS wrapper for the Spotify Web API

Home Page:https://jmperezperez.com/spotify-web-api-js/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Preview URL is always null, even for available markets

novatorem opened this issue · comments

Tried a number of IDs and keep getting preview_url: null.
When using the ID directly from the API documentation, it returns the preview URL.

I don't think it matters since it's just a wrapper, but I'm using the node.js version.

The function call:

spotifyApi.getTrack('2cWBwpqMsDJC1ZUwz813lo',
        function(err, data) {
            if (err) {
                console.error('Something went wrong!');
            } else {
                result = data.body;
            }
        }
    );

The returned JSON.

{
  album: {
    album_type: 'album',
    artists: [ [Object] ],
    available_markets: [
      'AD', 'AE', 'AR', 'AT', 'AU', 'BE', 'BG', 'BH',
      'BO', 'BR', 'CA', 'CH', 'CL', 'CO', 'CR', 'CY',
      'CZ', 'DE', 'DK', 'DO', 'DZ', 'EC', 'EE', 'EG',
      'ES', 'FI', 'FR', 'GB', 'GR', 'GT', 'HK', 'HN',
      'HU', 'ID', 'IE', 'IL', 'IN', 'IS', 'IT', 'JO',
      'JP', 'KW', 'LB', 'LI', 'LT', 'LU', 'LV', 'MA',
      'MC', 'MT', 'MX', 'MY', 'NI', 'NL', 'NO', 'NZ',
      'OM', 'PA', 'PE', 'PH', 'PL', 'PT', 'PY', 'QA',
      'RO', 'SA', 'SE', 'SG', 'SK', 'SV', 'TH', 'TN',
      'TR', 'TW', 'US', 'UY', 'VN', 'ZA'
    ],
    external_urls: {
      spotify: 'https://open.spotify.com/album/2cWBwpqMsDJC1ZUwz813lo'
    },
    href: 'https://api.spotify.com/v1/albums/2cWBwpqMsDJC1ZUwz813lo',
    id: '2cWBwpqMsDJC1ZUwz813lo',
    images: [ [Object], [Object], [Object] ],
    name: 'The Eminem Show',
    release_date: '2002-05-26',
    release_date_precision: 'day',
    total_tracks: 20,
    type: 'album',
    uri: 'spotify:album:2cWBwpqMsDJC1ZUwz813lo'
  },
  artists: [
    {
      external_urls: [Object],
      href: 'https://api.spotify.com/v1/artists/7dGJo4pcD2V6oG8kP0tJRR',
      id: '7dGJo4pcD2V6oG8kP0tJRR',
      name: 'Eminem',
      type: 'artist',
      uri: 'spotify:artist:7dGJo4pcD2V6oG8kP0tJRR'
    },
    {
      external_urls: [Object],
      href: 'https://api.spotify.com/v1/artists/1Oa0bMld0A3u5OTYfMzp5h',
      id: '1Oa0bMld0A3u5OTYfMzp5h',
      name: 'Nate Dogg',
      type: 'artist',
      uri: 'spotify:artist:1Oa0bMld0A3u5OTYfMzp5h'
    }
  ],
  available_markets: [
    'AD', 'AE', 'AR', 'AT', 'AU', 'BE', 'BG', 'BH',
    'BO', 'BR', 'CA', 'CH', 'CL', 'CO', 'CR', 'CY',
    'CZ', 'DE', 'DK', 'DO', 'DZ', 'EC', 'EE', 'EG',
    'ES', 'FI', 'FR', 'GB', 'GR', 'GT', 'HK', 'HN',
    'HU', 'ID', 'IE', 'IL', 'IN', 'IS', 'IT', 'JO',
    'JP', 'KW', 'LB', 'LI', 'LT', 'LU', 'LV', 'MA',
    'MC', 'MT', 'MX', 'MY', 'NI', 'NL', 'NO', 'NZ',
    'OM', 'PA', 'PE', 'PH', 'PL', 'PT', 'PY', 'QA',
    'RO', 'SA', 'SE', 'SG', 'SK', 'SV', 'TH', 'TN',
    'TR', 'TW', 'US', 'UY', 'VN', 'ZA'
  ],
  disc_number: 1,
  duration_ms: 297786,
  explicit: true,
  external_ids: { isrc: 'USIR10211066' },
  external_urls: { spotify: 'https://open.spotify.com/track/4xkOaSrkexMciUUogZKVTS' },
  href: 'https://api.spotify.com/v1/tracks/4xkOaSrkexMciUUogZKVTS',
  id: '4xkOaSrkexMciUUogZKVTS',
  is_local: false,
  name: "'Till I Collapse",
  popularity: 85,
  preview_url: null,
  track_number: 18,
  type: 'track',
  uri: 'spotify:track:4xkOaSrkexMciUUogZKVTS'
}

Hm @Omnitenebris something seems weird here. So I was just trying to run your code with the ID of 2cWBwpqMsDJC1ZUwz813lo and that failed for me as that is an album ID and not a track id. Did the request of spotifyApi.getTrack('2cWBwpqMsDJC1ZUwz813lo') work for you fully? Or is there something missing from here?

When I did the request for the actual track ID of "'Till I Collapse" using the ID 4xkOaSrkexMciUUogZKVTS the returned JSON had the preview url:

...
href: "https://api.spotify.com/v1/tracks/4xkOaSrkexMciUUogZKVTS"
id: "4xkOaSrkexMciUUogZKVTS"
is_local: false
name: "'Till I Collapse"
popularity: 85
preview_url: "https://p.scdn.co/mp3-preview/e187a68b2932880bfe9586d4f4a809d7b50f38ea?cid=774b29d4f13844c495f206cafdad9c86"
track_number: 18
type: "track"
uri: "spotify:track:4xkOaSrkexMciUUogZKVTS"
}

Sorry, that was my bad in writing the code in here. In my actual code I run it as getSongInfo('4xkOaSrkexMciUUogZKVTS'); which returns the preview_url as null.

What did you run to get the output you placed above? Did you authenticate the user or just the client?

You're good - I figured as much. I ran as an authenticated user after using spotifyApi.setAccessToken(). Strange that those would return different results though...I wouldn't assume they would return the same thing?

Then perhaps Spotify's API only allows you to preview a song if logged in, but I thought that wouldn't be the case since I've used webapps that had the preview.

Is it possible to hardcode my own account's access token permanently and get the preview from there?

Are you able to make the request without authenticating? I'm pretty sure it's required?

And you definitely could with the client credentials flow for something like that! https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow

If you are only requesting API endpoints that don't require user authentication, that should work! If you need something more about the user...then it gets a bit tougher.
Not as a plug but as an example, I do that here: https://bpm.harvy.app. I don't need user authentication but I am passing through my client credentials to request song information. (Search for a song like 42 )

I am authenticated using the client credential flow, specifically clientCredentialsGrant - but not the authorization code requiring the user.

I assumed preview_url wouldn't require a user, but I'm not able to access it with various track IDs so that's my assumption. Really, I just need that preview for my project. I'm thinking I'll get my authorization ID and refresh token saved to the database and just keep using that if nothing else works.

For your application, it does seem you get the information you need - but are you able to get the sample song?

I can check to see if the preview_url is returned - you are right I am not using that so I dont know if it is there.

Your way would definitely work with authorization ID and refresh token. I would just be wary of making your access token very public as if someone else grabs it, they would then modify your private account if the scopes allow it. Also, it does require it to be refreshed every 60 minutes but if you are saving the refresh token, I'm sure you already know that.

Let me get back to you on the preview url, I will see if it is maybe a client credentials vs user access thing

Ohh looks like you did catch something. I did not receive back a preview_url from my client credentials but I did receive one from my user flow. That's strange but it looks like you may have to go with your refresh token solution

Thank you for confirming!
Okay it'll be messy, but at least it's confirmed that it's not possible with just client credentials.

Do you have any open sourced code that shows a saved user authentication?

Yeah, that's super weird. I may dig into it more as I am trying to understand the use case for not providing it with client credentials. Maybe since it never refreshes or times out, someone could abuse that token and preview URL?

Nothing open-sourced right now, unfortunately. Depending on your project and if you need user authentication or not, there is a passport.js helper for Spotify that's pretty easy. I currently use Firebase with Firebase Functions for my Spotify auth. That is all requiring multiple user accounts though....hm for you I would maybe look into https://github.com/thelinmichael/spotify-web-api-node and putting your access token on a server that refreshes it. Then instead of making calls directly to the Spotify API from your web app, you would call your server API that handles the Spotify API request. I'm not a security expert though so don't quote me on that 🙃

Thanks for all the help, I'm using passports.js for middleware authentication, but I'd rather avoid users requiring a spotify premium account. I'll put my info up on the server and take it down for the duration of my coursework, thanks again!

Thanks @novatorem and @kevinguebert. As far as I understand, the issue is not related with this library so I'll close it for now. If you think this is an issue on Spotify's side, you can file an issue on https://github.com/spotify/web-api/issues.

Note that preview urls might be only returned for specific whitelisted access tokens, and for content for certain labels. From the documentation:

A link to a 30 second preview (MP3 format) of the track. Can be null