From b7f09058a9fcf81b4bb13b2e0f43824c6828dc7a Mon Sep 17 00:00:00 2001 From: Honey Date: Sat, 9 May 2026 20:55:00 +0200 Subject: [PATCH] fix: use sp_t cookie trick for Spotify anonymous token (spotdl approach) --- backend/novasonic-server.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/backend/novasonic-server.js b/backend/novasonic-server.js index 484297e..9c2f7e3 100644 --- a/backend/novasonic-server.js +++ b/backend/novasonic-server.js @@ -72,22 +72,23 @@ let _spTokenExpiry = 0; async function fetchSpotifyToken() { if (_spTokenCache && Date.now() < _spTokenExpiry) return _spTokenCache; - // Extract anonymous token from embed page — works from any IP unlike get_access_token - const r = await fetch('https://open.spotify.com/embed/track/4uLU6hMCjMI75M1A2tKUQC', { + // spotdl trick: send a random sp_t cookie — Spotify requires some value but doesn't validate it + const sp_t = require('crypto').randomUUID(); + const r = await fetch('https://open.spotify.com/get_access_token?reason=transport&productType=web_player', { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36', - 'Accept': 'text/html,application/xhtml+xml', + 'Accept': 'application/json', 'Accept-Language': 'en-US,en;q=0.9', + 'Referer': 'https://open.spotify.com/', + 'Cookie': `sp_t=${sp_t}`, }, - signal: AbortSignal.timeout(12000), + signal: AbortSignal.timeout(10000), }); - if (!r.ok) throw new Error(`Spotify-Embed nicht erreichbar (${r.status})`); - const html = await r.text(); - const tokenMatch = html.match(/"accessToken"\s*:\s*"([^"]+)"/); - if (!tokenMatch) throw new Error('Kein Token in Spotify-Embed gefunden'); - const expiryMatch = html.match(/"accessTokenExpirationTimestampMs"\s*:\s*(\d+)/); - _spTokenCache = tokenMatch[1]; - _spTokenExpiry = (expiryMatch ? parseInt(expiryMatch[1]) : (Date.now() + 55 * 60 * 1000)) - 30000; + if (!r.ok) throw new Error(`Spotify-Token nicht abrufbar (${r.status})`); + const d = await r.json(); + if (!d.accessToken) throw new Error('Kein Spotify-Token erhalten'); + _spTokenCache = d.accessToken; + _spTokenExpiry = (d.accessTokenExpirationTimestampMs || (Date.now() + 55 * 60 * 1000)) - 30000; return _spTokenCache; }