hi this is my first blog post! i suck at writing anything down anything so hopefully talking about random things helps.
this all started when i wanted to display my favorite songs on my /about page, i already have a spotify playlist of them so i could just use the official embed. the problem is that the embed loads 1.96 mb of minified javascript.
…and also makes tons of strange requests back to spotify, is extremely loud (with no volume slider!), and preloads some songs. on my old site i just gave in and used the official embed, but after seeing that scraping spotify embeds was possible (thanks l-m!), i tried making my own.
all of that javascript is even more insane considering this was meant to be used on other sites, you’d think the multi-billion $ company would care about performance for a simple embed. but it’s no secret that a lot of the web is getting megabytes of javascript larger, from complex frameworks and overkill libraries just to render mostly static sites. tonsky already has a great article on this.
here they are!
extremely good songs
open in spotifymedia offline
ariiol
1
The End
Danny Brown, ta Ukrainka, Zheani, Cynthoni
2
Music and Me
fakemink
3
MIRINAE
TAK, Zekk
4
Rain Capsule
Namitape
5
Overfeel
Namitape
6
All At Once
Ninajirachi
7
Infohazard
Ninajirachi
8
Delete
Ninajirachi
9
weathergirl
FLAVOR FOLEY
10
Lawsyn
ayowitty
11
THUNDRRR
Quadeca
12
THAT'S WHY
Quadeca
13
WAGING WAR
Quadeca, Olēka
14
NO QUESTIONS ASKED
Quadeca
15
Always Have Always Will
Jane Remover
16
SLAM PUNK
Che
17
Akibare
Mylta
18
My life is mine alone! (feat. nenne)
Mylta, nenne
19
disarmed
kumosai, Sayako
20
spectrum
icesawder
21
NOWNEVER
Jaron
22
Pretty Peach
Lucy Bedroque
23
How to Pretend
Lucy Bedroque
24
Knot Me
Lucy Bedroque
25
Sweet Pitcher
Lucy Bedroque
26
Thousand yard stare
kmoe
27
angels in camo
Jane Remover
28
Professional Vengeance
Jane Remover
29
Dreamflasher
Jane Remover
30
Experimental Skin
Jane Remover
31
Psychoboost
Jane Remover, Danny Brown
32
Dancing with your eyes closed
Jane Remover
33
Spider
venturing
34
Believe
venturing
35
alucarda lives!
smiling broadly
36
fake blood recipe
smiling broadly
37
flower bed
defsharp
38
sheaskedwhatmylifeislike
ericdoa
39
Caught up (in circles)
Syzy
40
Pastel Express
Cynax
41
St. Chroma (feat. Daniel Caesar)
Tyler, The Creator, Daniel Caesar
42
let's go home
Jane Remover
43
can you tell?
Jane Remover
44
champ
Jane Remover
45
pretender
Jane Remover
46
kodak moment
Jane Remover
47
movies for guys
Jane Remover
48
misplace
Jane Remover
49
Catch me if you can
tn-shi
50
natural
zeroth
51
mint
Snail's House
52
Emerald Lakeside - Action
はがね, Kitsui Akira
53
back off!!!
Jane Remover, kmoe, juno
54
one more life
Murphmusic, park.
55
Clinozoisite
Ludicin
56
Duhhhhhhhhhhhhhhhhh
underscores
57
Rabbit In The Black Room
Rabbit House
58
String Theocracy - Key Ingredient ver.
Mili
59
My guy (Corporate shuffle)
underscores
60
Wizards
xaev, mopearound
61
Everything Goes On
Porter Robinson, League of Legends
62
phobie d’impulsion
glaive
63
PUSH UR T3MPRR
femtanyl
64
Amethyst Aurora
BilliumMoto
65
the now now and never
what is your name?
66
Reverse Nightmare Tower
bye2
67
pop music
Limonène
68
EXACTLY WHY I'M STILL HERE - TURQUOISEDEATH Remix
bunnyprodge, TURQUOISEDEATH
69
even when the sun is dead, will you tell them how hard i tried
glaive
70
Tojita Sekai
Camellia
71
commatose
glass beach
72
200
glass beach
73
until the dawn breaks
Deathbrain
74
dumb party
Internet Girl
75
skinz
8485
76
Algas Danses
seatrus
77
うみのゆき
seatrus
78
Palmy Flakes
seatrus
79
Cloud99 (As Above Mix)
Machine Girl
80
enchanted love
linear ring
81
Midnight Theater
Kano, Nagi Nemoto
82
Mola mola
Marmalade butcher
83
Another Ride
ippo.tsk, Synthesizer V ANRI
84
neon glow
glass beach
85
I Still Miss You
bo en, Tomggg
86
(We Are) Friends
bo en, Winamp Boys
87
Our Time
bo en, PAS TASTA
88
Kansoku-eisei
Nanahira, Camellia
89
GURUGURU
Snail's House
90
About 10 Hours of Doubting Myself
Yem
91
GHOST OF LORELEY
lasah
92
awesome ends with ME and ugly starts with U
c0ncernn
93
DILF repellent
c0ncernn
94
タイニーリトル・アジアンタム
ShibayanRecords
95
lastnaut
Sleeping Pola
96
NekovhParavh
Sad Keyboard Guy, Gardens
97
cool delusions about morphing into a cat
crxw
98
Blooming Afternoon
ミツキヨ
99
you're Nxt -Dreams Remix- (feat. MisoilePunch)
uma, Morimori Atsushi, MisoilePunch♪
100
there's more songs on spotify :)
the track embed was made with 0 JS, and the playlist embed was made with 1.84kb (minified) of JS, that’s 99.9061% smaller than the official embed, and i think it fits my site much better :)
ill get the playlist volume slider done one of these days… (9/14/2024: done!)
how
first, you can just make a fetch request to the normal embed url (either for a song or playlist) pretending to be a browser
const res = await fetch(
`https://open.spotify.com/embed/playlist/2m2lebj9Lg6Riwfyv7G9AD`,
{
headers: {
"User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:124.0) Gecko/20100101 Firefox/124.0",
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "iframe",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "cross-site",
Pragma: "no-cache",
"Cache-Control": "no-cache",
},
method: "GET",
},
);
const html = await res.text();
and in the html response you get back, at the end there’s a magical script tag with the id __NEXT_DATA__ that contains everything you need!

const json = html.substring(
html.lastIndexOf(`type="application/json">`) +
`type="application/json">`.length,
html.lastIndexOf(`</script>`),
);
const data: PlaylistEmbedData = JSON.parse(json);
you can make whatever with this data now! i’d highly recommend caching it. you can cache song embed data much more aggressively than playlists cause those shouldn’t change.
it’s possible to make your embeds use 0 JS by using the native <audio /> element, which is what i do for singular song embeds. there’s a pretty big problem when using <audio /> for each song in a playlist embed though, it might take safari 8 seconds to load your site sometimes (not an exaggeration).
yes i did pinpoint the loading times to the hundred <audio /> elements, safari really doesn’t like that rendering that many…
note that you can barely style <audio /> elements and the element looks very different across each browser. because of all that i used a bit of JS with web components for my playlist embed, which gets server side rendered with astro.