<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic 403 Error When Calling /v1/audio-features Despite Valid Access Token in Spotify for Developers</title>
    <link>https://community.spotify.com/t5/Spotify-for-Developers/403-Error-When-Calling-v1-audio-features-Despite-Valid-Access/m-p/6970901#M17922</link>
    <description>&lt;P&gt;&lt;STRONG&gt;Plan&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Premium&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Operating System&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Windows 11&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;My Question or Issue&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;I'm building a Flask app that analyzes a user's music personality using Spotify Web API. I use the Authorization Code Flow to get an access token and fetch the user’s top tracks, then try to retrieve audio features. The /me/top/tracks endpoint works correctly, but the /audio-features endpoint returns:&lt;/P&gt;&lt;P&gt;403 Forbidden&lt;BR /&gt;{"error": {"status": 403}}&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;&lt;FONT size="3"&gt;What I’ve Checked&lt;/FONT&gt;&lt;/H3&gt;&lt;UL&gt;&lt;LI&gt;&lt;P class=""&gt;The token works for /me and /me/top/tracks, so it's valid.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P class=""&gt;The scopes used are:&lt;/P&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;SPAN&gt;&lt;SPAN class=""&gt;user&lt;/SPAN&gt;-top-&lt;SPAN class=""&gt;read&lt;/SPAN&gt; &lt;SPAN class=""&gt;user&lt;/SPAN&gt;-&lt;SPAN class=""&gt;read&lt;/SPAN&gt;-private &lt;SPAN class=""&gt;user&lt;/SPAN&gt;-&lt;SPAN class=""&gt;read&lt;/SPAN&gt;-email &lt;SPAN class=""&gt;user&lt;/SPAN&gt;-&lt;SPAN class=""&gt;read&lt;/SPAN&gt;-playback-state &lt;SPAN class=""&gt;user&lt;/SPAN&gt;-&lt;SPAN class=""&gt;read&lt;/SPAN&gt;-currently-playing &lt;/SPAN&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P class=""&gt;The audio features request uses valid track IDs (from top tracks).&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;I include the Authorization header correctly.&lt;/LI&gt;&lt;/UL&gt;&lt;H3&gt;&lt;FONT size="3"&gt;Minimal Code Example&lt;/FONT&gt;&lt;/H3&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;P&gt;from flask import Flask, session, redirect, request, url_for&lt;BR /&gt;import requests&lt;BR /&gt;import os&lt;BR /&gt;import urllib.parse&lt;/P&gt;&lt;P&gt;app = Flask(__name__)&lt;BR /&gt;app.secret_key = os.urandom(24)&lt;/P&gt;&lt;P&gt;CLIENT_ID = "my-client-id"&lt;BR /&gt;CLIENT_SECRET = "my-client-secret"&lt;BR /&gt;REDIRECT_URI = "&lt;A href="https://example.ngrok-free.app/callback" target="_blank" rel="noopener"&gt;https://example.ngrok-free.app/callback&lt;/A&gt;"&lt;BR /&gt;API_BASE_URL = "&lt;A href="https://api.spotify.com/v1" target="_blank" rel="noopener"&gt;https://api.spotify.com/v1&lt;/A&gt;"&lt;BR /&gt;AUTH_URL = "&lt;A href="https://accounts.spotify.com/authorize" target="_blank" rel="noopener"&gt;https://accounts.spotify.com/authorize&lt;/A&gt;"&lt;BR /&gt;TOKEN_URL = "&lt;A href="https://accounts.spotify.com/api/token" target="_blank" rel="noopener"&gt;https://accounts.spotify.com/api/token&lt;/A&gt;"&lt;/P&gt;&lt;P&gt;SCOPE = "user-top-read user-read-private user-read-email user-read-playback-state user-read-currently-playing"&lt;/P&gt;&lt;P&gt;@app.route("/")&lt;BR /&gt;def index():&lt;BR /&gt;return '&amp;lt;a href="/login"&amp;gt;Login with Spotify&amp;lt;/a&amp;gt;'&lt;/P&gt;&lt;P&gt;@app.route("/login")&lt;BR /&gt;def login():&lt;BR /&gt;params = {&lt;BR /&gt;"client_id": CLIENT_ID,&lt;BR /&gt;"response_type": "code",&lt;BR /&gt;"redirect_uri": REDIRECT_URI,&lt;BR /&gt;"scope": SCOPE,&lt;BR /&gt;}&lt;BR /&gt;return redirect(AUTH_URL + "?" + urllib.parse.urlencode(params))&lt;/P&gt;&lt;P&gt;@app.route("/callback")&lt;BR /&gt;def callback():&lt;BR /&gt;code = request.args.get("code")&lt;BR /&gt;if not code:&lt;BR /&gt;return "Authorization failed."&lt;/P&gt;&lt;P&gt;data = {&lt;BR /&gt;"grant_type": "authorization_code",&lt;BR /&gt;"code": code,&lt;BR /&gt;"redirect_uri": REDIRECT_URI,&lt;BR /&gt;"client_id": CLIENT_ID,&lt;BR /&gt;"client_secret": CLIENT_SECRET,&lt;BR /&gt;}&lt;BR /&gt;headers = {"Content-Type": "application/x-www-form-urlencoded"}&lt;BR /&gt;res = requests.post(TOKEN_URL, data=data, headers=headers)&lt;BR /&gt;if res.status_code != 200:&lt;BR /&gt;return f"Token fetch failed: {res.text}"&lt;/P&gt;&lt;P&gt;session["access_token"] = res.json()["access_token"]&lt;BR /&gt;return redirect("/analyze")&lt;/P&gt;&lt;P&gt;@app.route("/analyze")&lt;BR /&gt;def analyze():&lt;BR /&gt;access_token = session.get("access_token")&lt;BR /&gt;if not access_token:&lt;BR /&gt;return redirect(url_for("login"))&lt;/P&gt;&lt;P&gt;headers = {"Authorization": f"Bearer {access_token}"}&lt;/P&gt;&lt;P&gt;# Fetch top tracks&lt;BR /&gt;top_tracks_res = requests.get(f"{API_BASE_URL}/me/top/tracks?limit=10", headers=headers)&lt;BR /&gt;if top_tracks_res.status_code != 200:&lt;BR /&gt;return f"Top tracks fetch failed: {top_tracks_res.status_code}"&lt;/P&gt;&lt;P&gt;track_ids = [track["id"] for track in top_tracks_res.json().get("items", [])]&lt;/P&gt;&lt;P&gt;# Fetch audio features&lt;BR /&gt;audio_features_res = requests.get(&lt;BR /&gt;f"{API_BASE_URL}/audio-features",&lt;BR /&gt;headers=headers,&lt;BR /&gt;params={"ids": ",".join(track_ids)},&lt;BR /&gt;)&lt;/P&gt;&lt;P&gt;print("Request URL:", audio_features_res.url)&lt;BR /&gt;print("Status:", audio_features_res.status_code)&lt;BR /&gt;print("Text:", audio_features_res.text)&lt;/P&gt;&lt;P&gt;if audio_features_res.status_code != 200:&lt;BR /&gt;return f"Audio features fetch failed: {audio_features_res.status_code} {audio_features_res.text}"&lt;/P&gt;&lt;P&gt;return "Audio features retrieved successfully."&lt;/P&gt;&lt;P&gt;if __name__ == "__main__":&lt;BR /&gt;app.run(debug=True)&lt;/P&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Questions&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Is there a known reason why calling /v1/audio-features with a valid access token (that works for other endpoints) would return a 403?&lt;BR /&gt;Does it require any special approval, account type, or additional scope?&lt;/P&gt;</description>
    <pubDate>Wed, 21 May 2025 12:14:53 GMT</pubDate>
    <dc:creator>Adrien0010</dc:creator>
    <dc:date>2025-05-21T12:14:53Z</dc:date>
    <item>
      <title>403 Error When Calling /v1/audio-features Despite Valid Access Token</title>
      <link>https://community.spotify.com/t5/Spotify-for-Developers/403-Error-When-Calling-v1-audio-features-Despite-Valid-Access/m-p/6970901#M17922</link>
      <description>&lt;P&gt;&lt;STRONG&gt;Plan&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Premium&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Operating System&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Windows 11&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;My Question or Issue&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;I'm building a Flask app that analyzes a user's music personality using Spotify Web API. I use the Authorization Code Flow to get an access token and fetch the user’s top tracks, then try to retrieve audio features. The /me/top/tracks endpoint works correctly, but the /audio-features endpoint returns:&lt;/P&gt;&lt;P&gt;403 Forbidden&lt;BR /&gt;{"error": {"status": 403}}&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;&lt;FONT size="3"&gt;What I’ve Checked&lt;/FONT&gt;&lt;/H3&gt;&lt;UL&gt;&lt;LI&gt;&lt;P class=""&gt;The token works for /me and /me/top/tracks, so it's valid.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P class=""&gt;The scopes used are:&lt;/P&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;SPAN&gt;&lt;SPAN class=""&gt;user&lt;/SPAN&gt;-top-&lt;SPAN class=""&gt;read&lt;/SPAN&gt; &lt;SPAN class=""&gt;user&lt;/SPAN&gt;-&lt;SPAN class=""&gt;read&lt;/SPAN&gt;-private &lt;SPAN class=""&gt;user&lt;/SPAN&gt;-&lt;SPAN class=""&gt;read&lt;/SPAN&gt;-email &lt;SPAN class=""&gt;user&lt;/SPAN&gt;-&lt;SPAN class=""&gt;read&lt;/SPAN&gt;-playback-state &lt;SPAN class=""&gt;user&lt;/SPAN&gt;-&lt;SPAN class=""&gt;read&lt;/SPAN&gt;-currently-playing &lt;/SPAN&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P class=""&gt;The audio features request uses valid track IDs (from top tracks).&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;I include the Authorization header correctly.&lt;/LI&gt;&lt;/UL&gt;&lt;H3&gt;&lt;FONT size="3"&gt;Minimal Code Example&lt;/FONT&gt;&lt;/H3&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;P&gt;from flask import Flask, session, redirect, request, url_for&lt;BR /&gt;import requests&lt;BR /&gt;import os&lt;BR /&gt;import urllib.parse&lt;/P&gt;&lt;P&gt;app = Flask(__name__)&lt;BR /&gt;app.secret_key = os.urandom(24)&lt;/P&gt;&lt;P&gt;CLIENT_ID = "my-client-id"&lt;BR /&gt;CLIENT_SECRET = "my-client-secret"&lt;BR /&gt;REDIRECT_URI = "&lt;A href="https://example.ngrok-free.app/callback" target="_blank" rel="noopener"&gt;https://example.ngrok-free.app/callback&lt;/A&gt;"&lt;BR /&gt;API_BASE_URL = "&lt;A href="https://api.spotify.com/v1" target="_blank" rel="noopener"&gt;https://api.spotify.com/v1&lt;/A&gt;"&lt;BR /&gt;AUTH_URL = "&lt;A href="https://accounts.spotify.com/authorize" target="_blank" rel="noopener"&gt;https://accounts.spotify.com/authorize&lt;/A&gt;"&lt;BR /&gt;TOKEN_URL = "&lt;A href="https://accounts.spotify.com/api/token" target="_blank" rel="noopener"&gt;https://accounts.spotify.com/api/token&lt;/A&gt;"&lt;/P&gt;&lt;P&gt;SCOPE = "user-top-read user-read-private user-read-email user-read-playback-state user-read-currently-playing"&lt;/P&gt;&lt;P&gt;@app.route("/")&lt;BR /&gt;def index():&lt;BR /&gt;return '&amp;lt;a href="/login"&amp;gt;Login with Spotify&amp;lt;/a&amp;gt;'&lt;/P&gt;&lt;P&gt;@app.route("/login")&lt;BR /&gt;def login():&lt;BR /&gt;params = {&lt;BR /&gt;"client_id": CLIENT_ID,&lt;BR /&gt;"response_type": "code",&lt;BR /&gt;"redirect_uri": REDIRECT_URI,&lt;BR /&gt;"scope": SCOPE,&lt;BR /&gt;}&lt;BR /&gt;return redirect(AUTH_URL + "?" + urllib.parse.urlencode(params))&lt;/P&gt;&lt;P&gt;@app.route("/callback")&lt;BR /&gt;def callback():&lt;BR /&gt;code = request.args.get("code")&lt;BR /&gt;if not code:&lt;BR /&gt;return "Authorization failed."&lt;/P&gt;&lt;P&gt;data = {&lt;BR /&gt;"grant_type": "authorization_code",&lt;BR /&gt;"code": code,&lt;BR /&gt;"redirect_uri": REDIRECT_URI,&lt;BR /&gt;"client_id": CLIENT_ID,&lt;BR /&gt;"client_secret": CLIENT_SECRET,&lt;BR /&gt;}&lt;BR /&gt;headers = {"Content-Type": "application/x-www-form-urlencoded"}&lt;BR /&gt;res = requests.post(TOKEN_URL, data=data, headers=headers)&lt;BR /&gt;if res.status_code != 200:&lt;BR /&gt;return f"Token fetch failed: {res.text}"&lt;/P&gt;&lt;P&gt;session["access_token"] = res.json()["access_token"]&lt;BR /&gt;return redirect("/analyze")&lt;/P&gt;&lt;P&gt;@app.route("/analyze")&lt;BR /&gt;def analyze():&lt;BR /&gt;access_token = session.get("access_token")&lt;BR /&gt;if not access_token:&lt;BR /&gt;return redirect(url_for("login"))&lt;/P&gt;&lt;P&gt;headers = {"Authorization": f"Bearer {access_token}"}&lt;/P&gt;&lt;P&gt;# Fetch top tracks&lt;BR /&gt;top_tracks_res = requests.get(f"{API_BASE_URL}/me/top/tracks?limit=10", headers=headers)&lt;BR /&gt;if top_tracks_res.status_code != 200:&lt;BR /&gt;return f"Top tracks fetch failed: {top_tracks_res.status_code}"&lt;/P&gt;&lt;P&gt;track_ids = [track["id"] for track in top_tracks_res.json().get("items", [])]&lt;/P&gt;&lt;P&gt;# Fetch audio features&lt;BR /&gt;audio_features_res = requests.get(&lt;BR /&gt;f"{API_BASE_URL}/audio-features",&lt;BR /&gt;headers=headers,&lt;BR /&gt;params={"ids": ",".join(track_ids)},&lt;BR /&gt;)&lt;/P&gt;&lt;P&gt;print("Request URL:", audio_features_res.url)&lt;BR /&gt;print("Status:", audio_features_res.status_code)&lt;BR /&gt;print("Text:", audio_features_res.text)&lt;/P&gt;&lt;P&gt;if audio_features_res.status_code != 200:&lt;BR /&gt;return f"Audio features fetch failed: {audio_features_res.status_code} {audio_features_res.text}"&lt;/P&gt;&lt;P&gt;return "Audio features retrieved successfully."&lt;/P&gt;&lt;P&gt;if __name__ == "__main__":&lt;BR /&gt;app.run(debug=True)&lt;/P&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Questions&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Is there a known reason why calling /v1/audio-features with a valid access token (that works for other endpoints) would return a 403?&lt;BR /&gt;Does it require any special approval, account type, or additional scope?&lt;/P&gt;</description>
      <pubDate>Wed, 21 May 2025 12:14:53 GMT</pubDate>
      <guid>https://community.spotify.com/t5/Spotify-for-Developers/403-Error-When-Calling-v1-audio-features-Despite-Valid-Access/m-p/6970901#M17922</guid>
      <dc:creator>Adrien0010</dc:creator>
      <dc:date>2025-05-21T12:14:53Z</dc:date>
    </item>
    <item>
      <title>Re: 403 Error When Calling /v1/audio-features Despite Valid Access Token</title>
      <link>https://community.spotify.com/t5/Spotify-for-Developers/403-Error-When-Calling-v1-audio-features-Despite-Valid-Access/m-p/6971183#M17923</link>
      <description>&lt;P&gt;Hi &lt;a href="https://community.spotify.com/t5/user/viewprofilepage/user-id/26835524"&gt;@Adrien0010&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This endpoint has long since stopped working for apps that did not have a quota extension before November 27, 2024. You can read more about it &lt;A href="https://community.spotify.com/t5/Spotify-for-Developers/Changes-to-Web-API/td-p/6540414" target="_blank" rel="noopener"&gt;here&lt;/A&gt;.&lt;/P&gt;</description>
      <pubDate>Wed, 21 May 2025 16:30:12 GMT</pubDate>
      <guid>https://community.spotify.com/t5/Spotify-for-Developers/403-Error-When-Calling-v1-audio-features-Despite-Valid-Access/m-p/6971183#M17923</guid>
      <dc:creator>Ximzend</dc:creator>
      <dc:date>2025-05-21T16:30:12Z</dc:date>
    </item>
    <item>
      <title>Re: 403 Error When Calling /v1/audio-features Despite Valid Access Token</title>
      <link>https://community.spotify.com/t5/Spotify-for-Developers/403-Error-When-Calling-v1-audio-features-Despite-Valid-Access/m-p/6971291#M17924</link>
      <description>&lt;P&gt;Got it. Thanks for your reply.&lt;/P&gt;</description>
      <pubDate>Wed, 21 May 2025 18:00:25 GMT</pubDate>
      <guid>https://community.spotify.com/t5/Spotify-for-Developers/403-Error-When-Calling-v1-audio-features-Despite-Valid-Access/m-p/6971291#M17924</guid>
      <dc:creator>Adrien0010</dc:creator>
      <dc:date>2025-05-21T18:00:25Z</dc:date>
    </item>
  </channel>
</rss>

