
SpotifyのプレイリストをYouTubeに変換するツールを作って無料公開してみた!【Cloudflare】
はじめに
今回は「Spotify のプレイリストを YouTube の再生リストに変換するツール」を作って、Cloudflare で誰でも使えるように公開した話をしていきます!
友達に「このプレイリストいいよ」って送りたいのに、相手が Spotify を使ってない…ってこと、ありませんか?
正直、今までは1曲ずつ YouTube で検索してURLを貼ってました(笑)。曲が30曲とかあると地獄です。
なので、URLを貼るだけで全曲を YouTube のURLにして、そのまま再生リストとして開けるツールを作りました。
実際に動いているのはこちらです👇
https://spotify-to-youtube-80b.pages.dev
ログイン不要
Spotify の公開プレイリスト / アルバムのURLを貼るだけ
全曲の YouTube URL をコピー・txt・csv で保存できる
YouTube の再生リストとして開ける(そのリンクを友達に送ればOK)

この記事は「何か作って公開してみたい中高生・大学生」向けに、仕組みと詰まったところを中心に書いていきます!
1. どうやって動いているか
やっていることはシンプルで、3ステップだけです。
Spotify から曲名とアーティスト名の一覧を取る
1曲ずつ YouTube で「アーティスト名 曲名」を検索して、一番上の動画を取る
動画IDをまとめて YouTube の再生リストURLにする
ポイントは、どれも APIキーを使っていないことです。
Spotify の曲一覧は「埋め込みページ」から取る
Spotify の公式 API を使うには、開発者登録をしてキーを作る必要があります。
でも、ブログなどに貼る用の「埋め込みプレーヤー」のページ(open.spotify.com/embed/playlist/...)には、中に曲の一覧が JSON で入っています。
なので、そのページを読み込んで JSON を取り出すだけで曲名がわかります。
const NEXT_DATA_RE = /<script id="__NEXT_DATA__" type="application\/json">([\s\S]*?)<\/script>/;
const entity = JSON.parse(m[1]).props.pageProps.state.data.entity;
// entity.trackList に { title: 曲名, subtitle: アーティスト名 } が並んでいるただ、埋め込みページなので長いプレイリストは途中までしか取れません(試した感じだと100曲くらいまで)。全部取りたい場合は公式APIを使う必要があります。
YouTube も検索結果ページから取る
YouTube の公式 API にも検索機能はありますが、1日に使える回数(クォータ)がかなり少なくて、検索だと1日100回くらいで止まってしまいます。
なので、普通の検索結果ページ(youtube.com/results?search_query=...)を読み込んで、最初の動画IDを正規表現で抜き出しています。
const YT_VIDEO_RE = /"videoRenderer":\{"videoId":"([\w-]{11})"/;YouTube の動画IDは必ず11文字なので、[\w-]{11} で取れます。
再生リストは URL だけで作れる
ここが一番びっくりしたところなんですが、YouTube には
https://www.youtube.com/watch_videos?video_ids=ID1,ID2,ID3,...という URL があって、動画IDをカンマでつなぐだけで、その順番の再生リストとして開けるんです!
ログインもいらないし、このURLは誰が開いても同じ曲順で再生されるので、そのまま友達に送れます。
1つのURLに入れられるのは50曲までなので、それより多いときは50曲ずつに分けています。
2. 最初はPCで動かすPython版を作った
最初は Python(Flask)で、自分のPCだけで動く版を作りました。
画面はHTML1枚で、変換ボタンを押すと4曲ずつ並列で検索して、終わった曲から表に埋まっていくようにしました。間違った動画が当たったときは、表のURLを書き換えればそれが反映されます。
おまけ:自分のYouTubeに「本物の」プレイリストを作る機能
PC版には、Googleでログインして自分の YouTube アカウントに本物のプレイリストを作る機能も付けました(YouTube Data API + Google OAuth)。
ただ、これを公開版に入れるのはやめました。理由は2つです。
Google の審査を通していないアプリは「テストモード」になって、自分で登録した人(テストユーザー)しかログインできない
YouTube API の上限があって、プレイリストに曲を追加するのは全員合わせて1日200曲くらいまで
みんなに使ってもらうには向いてないので、公開版は「URLで開く再生リスト」だけにしました。
3. Cloudflare で公開する
PC版だと自分しか使えないので、Cloudflare で公開しました。
無料プランでも十分使えて、npx wrangler deploy の一発で公開できるのが楽です。
ただ、Cloudflare では Python の Flask がそのまま動かないので、TypeScript に書き直しました。中身はほぼ同じです。
最終的な構成はこうなりました。
Cloudflare Pages:画面(public/index.html)を配信。/api/ へのアクセスだけ下の Worker に渡す
Cloudflare Workers(spotify-to-youtube-api):Spotify の取得と YouTube の検索をするAPI本体
src/core.ts:Spotify の取得と YouTube の検索
src/api.ts:/api/playlist、/api/search などのAPI
なんで2つに分けているかは、下の「詰まったところ」で説明します。
連打対策を入れた
誰でも使える公開サービスにすると、ボタンを連打されたり、大量にアクセスされたりする可能性があります。
そうなると YouTube や Spotify にもアクセスが集中して迷惑なので、Cloudflare の「Rate Limiting」でIPごとに回数制限をかけました。
"ratelimits": [
{ "name": "SEARCH_LIMITER", "namespace_id": "2201", "simple": { "limit": 120, "period": 60 } },
{ "name": "PLAYLIST_LIMITER", "namespace_id": "2202", "simple": { "limit": 10, "period": 60 } }
]検索は1分に120回、プレイリスト読み込みは1分に10回までです。設定ファイルに書くだけでいいので簡単でした。
実際に30回連打してテストしたら、8回目くらいから「アクセスが多すぎます」が返ってきました(数え方がざっくりなので、ぴったり10回では止まらないみたいです)。
4. 詰まったところ
詰まり1:Cloudflare からだと検索が半分失敗する…と思ったら
公開してテストしたら、10曲中5曲くらい「見つかりませんでした」になりました。
「Cloudflare のサーバーからだと YouTube にブロックされてる?」と思って、デバッグ用のAPIを作って中身を見てみたら…
検索ワードが文字化けしてました。
原因は、テストに使っていた Windows のターミナル(Git Bash)の curl で日本語を送ると、UTF-8 じゃない文字コードで送られていたことでした。
「YOASOBI」みたいに英語だけの曲は成功して、「米津玄師 Lemon」みたいな日本語入りが失敗していたのはそのせいです。
Python の requests(ちゃんと UTF-8 で送る)でテストし直したら、10曲中10曲成功しました。ツールは最初から壊れてなかったです(笑)
テストのやり方が間違ってることもあるので、「おかしいな」と思ったら実際に届いているデータを見るのが大事だと学びました。
詰まり2:hidden にしたボタンが消えない
ボタンに hidden を付けて隠したはずなのに、画面に出っぱなしになっていました。
原因は CSS で .row { display: flex; } を書いていたことで、CSS の display が hidden より強いんです。
[hidden] { display: none !important; }この1行を足したら直りました。地味だけどハマりやすいです。
詰まり3:直したのに画面が変わらない
JavaScript のエラーを直してデプロイしたのに、ブラウザで開くと前のまま…。
これはブラウザが古いページをキャッシュしていただけでした。URLの後ろに ?v=2 みたいに適当な文字を付けて開き直したら、新しい版が出ました。
詰まり4:URLに自分の名前が出てしまう
最初は Cloudflare Workers だけで公開したんですが、URLが「spotify-to-youtube.(アカウント名).workers.dev」になって、自分の名前がURLに入ってしまいました。
workers.dev のこの部分はアカウント全体で共通なので、変えると他に公開しているツールのURLまで変わってしまいます。
そこで、URLがプロジェクト名だけになる Cloudflare Pages に引っ越すことにしました。
でも今度は、Pages ではさっきの回数制限(ratelimits)が使えないというエラーが…。
Configuration file for Pages projects does not support "ratelimits"最終的にはこうしました。
APIは今まで通り Worker で動かす(回数制限つき)。ただし workers_dev を false にして、名前入りの公開URLは作らない
画面は Pages で公開する
Pages の /api/ に来たアクセスは「Service Binding」という機能で Worker に直接渡す
// functions/api/[[path]].ts
export const onRequest: PagesFunction<PagesEnv> = ({ request, env }) => env.API.fetch(request);これで、URLは名前なしの pages.dev、回数制限もそのまま、という形にできました!
公開するときは、URLに何が出るかも最初に確認しておいた方がいいです(笑)
5. 使い方
Spotify でプレイリストの「共有」→「リンクをコピー」して貼る
「変換」を押す(1曲ずつ検索していくので少し待つ)
「YouTubeプレイリストを作る」→「YouTubeで開く」で再生
「友達に送るリンクをコピー」で LINE などに貼れば、友達もそのまま聴ける
「audio を付けて検索」にチェックを入れると、MVより音源の動画が出やすくなります。
注意点もあります。
非公開のプレイリストは読み込めません
長いプレイリストは途中(100曲くらい)までになります
たまに違う動画(カバーやライブ版)が当たるので、表のURLを書き換えて直してください
非公式ツールで、Spotify・YouTube とは関係ありません
最後に
「友達に曲を送るのがめんどくさい」っていう小さい不満から作ったツールですが、公開まで1日でできました!
特に、Python で作ったものを TypeScript に書き直して Cloudflare に載せる流れは、他のツールでも使えるのでおすすめです。
自分が「めんどくさいな」と思ったことは、だいたい他の人もめんどくさいと思ってるので、ぜひ何か作って公開してみてください!
質問があればコメントで聞いてください。ぜひ参考にしてください!
ここから下は、今回作った Cloudflare 版の全部のコードです。コピペでそのまま動かせます!
全部のコードはこちら
フォルダ構成はこうなっています。