无需用户数据,如何通过Spotify Web API获取艺人基础信息?
解决Spotify API 401未授权问题(非用户中心请求)
我完全懂你的困惑——之前很多API像SongKick/LastFM直接传密钥就能用,但Spotify的API规则不一样,哪怕是非用户相关的公开数据请求,现在也需要通过Client Credentials Flow获取访问令牌,不能直接裸发请求。
下面是修改后的可运行代码,你只需要把YOUR_CLIENT_ID和YOUR_CLIENT_SECRET替换成你在Spotify开发者后台创建应用时拿到的对应值就行:
// 替换成你的Spotify客户端ID和密钥 const CLIENT_ID = 'YOUR_CLIENT_ID'; const CLIENT_SECRET = 'YOUR_CLIENT_SECRET'; let accessToken = ''; // 获取访问令牌 const getAccessToken = async () => { const response = await fetch('https://accounts.spotify.com/api/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Authorization': 'Basic ' + btoa(CLIENT_ID + ':' + CLIENT_SECRET) }, body: 'grant_type=client_credentials' }); const data = await response.json(); accessToken = data.access_token; }; // 预获取令牌 getAccessToken(); // find template and compile it var templateSource = document.getElementById('results-template').innerHTML, template = Handlebars.compile(templateSource), resultsPlaceholder = document.getElementById('results'), playingCssClass = 'playing', audioObject = null; var fetchTracks = function (albumId, callback) { $.ajax({ url: 'https://api.spotify.com/v1/albums/' + albumId, headers: { 'Authorization': 'Bearer ' + accessToken }, success: function (response) { callback(response); }, error: function(xhr) { // 如果令牌过期,重新获取再重试 if (xhr.status === 401) { getAccessToken().then(() => { fetchTracks(albumId, callback); }); } } }); }; var searchAlbums = function (query) { $.ajax({ url: 'https://api.spotify.com/v1/search', headers: { 'Authorization': 'Bearer ' + accessToken }, data: { q: query, type: 'album' }, success: function (response) { resultsPlaceholder.innerHTML = template(response); }, error: function(xhr) { if (xhr.status === 401) { getAccessToken().then(() => { searchAlbums(query); }); } } }); }; results.addEventListener('click', function (e) { var target = e.target; if (target !== null && target.classList.contains('cover')) { if (target.classList.contains(playingCssClass)) { audioObject.pause(); } else { if (audioObject) { audioObject.pause(); } fetchTracks(target.getAttribute('data-album-id'), function (data) { audioObject = new Audio(data.tracks.items[0].preview_url); audioObject.play(); target.classList.add(playingCssClass); audioObject.addEventListener('ended', function () { target.classList.remove(playingCssClass); }); audioObject.addEventListener('pause', function () { target.classList.remove(playingCssClass); }); }); } } }); document.getElementById('search-form').addEventListener('submit', function (e) { e.preventDefault(); searchAlbums(document.getElementById('query').value); }, false);
关键修改点说明:
- 添加了
getAccessToken函数,通过Client Credentials Flow获取访问令牌(有效期1小时),代码还加入了401重试逻辑,自动刷新过期令牌。 - 所有API请求都新增了
Authorization: Bearer {accessToken}请求头,这是Spotify API强制要求的认证方式。 - 注意:前端代码直接暴露Client Secret存在安全风险,如果是生产环境应用,建议把令牌获取逻辑放到后端,前端从后端拿令牌;但做Demo/测试的话,这样写完全没问题。
你把这段代码放到JSFiddle里,替换好Client ID和Secret,就能正常运行了。
内容的提问来源于stack exchange,提问作者armyofda12mnkeys




