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 spotifyThe End
Danny Brown, ta Ukrainka, Zheani, Cynthoni
1
Music and Me
fakemink
2
MIRINAE
TAK, Zekk
3
Rain Capsule
Namitape
4
Overfeel
Namitape
5
All At Once
Ninajirachi
6
Infohazard
Ninajirachi
7
Delete
Ninajirachi
8
weathergirl
FLAVOR FOLEY
9
Lawsyn
ayowitty
10
THUNDRRR
Quadeca
11
THAT'S WHY
Quadeca
12
WAGING WAR
Quadeca, Olēka
13
NO QUESTIONS ASKED
Quadeca
14
Always Have Always Will
Jane Remover
15
SLAM PUNK
Che
16
Akibare
Mylta
17
My life is mine alone! (feat. nenne)
Mylta, nenne
18
disarmed
kumosai, Sayako
19
spectrum
icesawder
20
NOWNEVER
Jaron
21
Pretty Peach
Lucy Bedroque
22
How to Pretend
Lucy Bedroque
23
Knot Me
Lucy Bedroque
24
Sweet Pitcher
Lucy Bedroque
25
Thousand yard stare
kmoe
26
angels in camo
Jane Remover
27
Professional Vengeance
Jane Remover
28
Dreamflasher
Jane Remover
29
Experimental Skin
Jane Remover
30
Psychoboost
Jane Remover, Danny Brown
31
Dancing with your eyes closed
Jane Remover
32
Spider
venturing
33
Believe
venturing
34
alucarda lives!
smiling broadly
35
fake blood recipe
smiling broadly
36
flower bed
defsharp
37
sheaskedwhatmylifeislike
ericdoa
38
Caught up (in circles)
Syzy
39
Pastel Express
Cynax
40
St. Chroma (feat. Daniel Caesar)
Tyler, The Creator, Daniel Caesar
41
let's go home
Jane Remover
42
can you tell?
Jane Remover
43
champ
Jane Remover
44
pretender
Jane Remover
45
kodak moment
Jane Remover
46
movies for guys
Jane Remover
47
misplace
Jane Remover
48
Catch me if you can
tn-shi
49
natural
zeroth
50
mint
Snail's House
51
Emerald Lakeside - Action
はがね, Kitsui Akira
52
back off!!!
Jane Remover, kmoe, juno
53
one more life
Murphmusic, park.
54
Clinozoisite
Ludicin
55
Duhhhhhhhhhhhhhhhhh
underscores
56
Rabbit In The Black Room
Rabbit House
57
String Theocracy - Key Ingredient ver.
Mili
58
My guy (Corporate shuffle)
underscores
59
Wizards
xaev, mopearound
60
Everything Goes On
Porter Robinson, League of Legends
61
phobie d’impulsion
glaive
62
PUSH UR T3MPRR
femtanyl
63
Amethyst Aurora
BilliumMoto
64
the now now and never
what is your name?
65
Reverse Nightmare Tower
bye2
66
pop music
Limonène
67
EXACTLY WHY I'M STILL HERE - TURQUOISEDEATH Remix
bunnyprodge, TURQUOISEDEATH
68
even when the sun is dead, will you tell them how hard i tried
glaive
69
Tojita Sekai
Camellia
70
commatose
glass beach
71
200
glass beach
72
until the dawn breaks
Deathbrain
73
dumb party
Internet Girl
74
skinz
8485
75
Algas Danses
seatrus
76
うみのゆき
seatrus
77
Palmy Flakes
seatrus
78
Cloud99 (As Above Mix)
Machine Girl
79
enchanted love
linear ring
80
Midnight Theater
Kano, Nagi Nemoto
81
Mola mola
Marmalade butcher
82
Another Ride
ippo.tsk, Synthesizer V ANRI
83
neon glow
glass beach
84
I Still Miss You
bo en, Tomggg
85
(We Are) Friends
bo en, Winamp Boys
86
Our Time
bo en, PAS TASTA
87
Kansoku-eisei
Nanahira, Camellia
88
GURUGURU
Snail's House
89
About 10 Hours of Doubting Myself
Yem
90
GHOST OF LORELEY
lasah
91
awesome ends with ME and ugly starts with U
c0ncernn
92
DILF repellent
c0ncernn
93
タイニーリトル・アジアンタム
ShibayanRecords
94
lastnaut
Sleeping Pola
95
NekovhParavh
Sad Keyboard Guy, Gardens
96
cool delusions about morphing into a cat
crxw
97
Blooming Afternoon
ミツキヨ
98
you're Nxt -Dreams Remix- (feat. MisoilePunch)
uma, Morimori Atsushi, MisoilePunch♪
99
Tenebre Rosso Sangue (ULTRAKILL Original Game Soundtrack)
Keygen Church
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.