调用Spotify API遇401无令牌错误,请求头已携带令牌
问题描述
我调用Spotify API时遇到了问题:获取令牌的请求正常返回,控制台也能输出令牌,但后续请求返回401, no token provided错误,尽管开发者工具显示请求头里已经包含了令牌。我试了多种设置请求头的方式,都没解决问题。附上代码和网络面板截图,求帮忙!
async function getAuth() { const res = await fetch('https://accounts.spotify.com/api/token', { headers: { "Content-Type": 'application/x-www-form-urlencoded', }, method: 'POST', body: 'grant_type=client_credentials&client_id=***&client_secret=***' }); return res.json(); } async function fetchWebApi(endpoint, method, token) { console.log('Bearer ' + token) const res = await fetch('https://api.spotify.com/' + endpoint, { method: 'GET', headers: new Headers({ 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/x-www-form-urlencoded' }) }); return res.json(); } async function getTopTracks(token){ // Endpoint reference : https://developer.spotify.com/documentation/web-api/reference/get-users-top-artists-and-tracks return ( await fetchWebApi( 'v1/me/top/tracks?time_range=short_term&limit=5', 'GET', token )).items; } //6p21dRudS9FmcyGvKWPq2R?si=591aadc63f934b7c async function getRandomPlaylist(token) { return ( await fetchWebApi ( 'v1/me/playlists/3cEYpjA9oz9GiPac4AsH4n/tracks', 'GET', token )).items; } // getTopTracks().then(data => console.log(data)) getAuth().then(data => { myToken = data['access_token'] console.log(myToken) getRandomPlaylist(myToken).then(aplaylist => console.log(aplaylist)) })

问题原因与解决方案
核心原因
你用的**客户端凭证流(Client Credentials Flow)获取的令牌,只能访问Spotify的公开数据(比如搜索歌曲、查看公开播放列表),根本无权访问/me开头的用户专属接口——这类接口要求令牌必须绑定用户身份,只能通过授权码流(Authorization Code Flow)**获取。
具体解决步骤
- 换授权流程:改用授权码流(推荐搭配PKCE提升安全性),流程大致是:
- 引导用户跳转到Spotify的授权页面,带上你的client_id、回调地址、需要的权限scope以及PKCE验证参数。
- 用户授权后,用返回的授权码去交换带用户上下文的access_token。
- 删多余请求头:
fetchWebApi里的Content-Type: application/x-www-form-urlencoded对GET请求完全没用,删掉能避免不必要的请求头冲突。 - 确认权限范围:授权时要申请对应接口的权限,比如访问用户私有播放列表需要
playlist-read-private,获取听歌排行需要user-top-read。
修正后的接口调用示例
async function fetchWebApi(endpoint, method, token) { console.log('Bearer ' + token) const res = await fetch('https://api.spotify.com/' + endpoint, { method: method, // 改为使用传入的method参数,之前写死GET是冗余的 headers: { 'Authorization': 'Bearer ' + token // 移除多余的Content-Type头 } }); return res.json(); }
内容的提问来源于stack exchange,提问作者Ian McGarry
相关产品推荐
相关产品推荐

