Back to Deck
[snippet]
YouTube Music Liked Songs Exporter
SOURCE YouTube Music
VERSION 1.0.0
AUTHOR Cododel
Run this one-time browser console snippet on your Liked Music playlist in YouTube Music. It scrolls through the list, collects visible artist and title pairs, and offers copy and .txt download buttons when finished.
How to use
- Open your Liked Music playlist at
music.youtube.comand wait for the first tracks to appear. - Open your browser’s developer console, paste the entire code below, and run it.
- Keep the tab open while the script scrolls. When it finishes, use the on-screen button to copy or download the list.
- To stop early, run
window.__stopScraper = truein the console. The tracks collected so far will still be available.
The output has one Artist — Title pair per line. Identical pairs are deduplicated. The script stops after about ten seconds without finding a new unique pair, so check the exported count if the playlist loads slowly. It reads the current page DOM; YouTube Music interface changes can affect what it finds.
Source code
// YouTube Music Liked Songs Scraper & Exporter;(async () => { window.__stopScraper = false const tracks = new Set() let lastSize = 0 let stagnantTurns = 0 const maxStagnant = 12
console.log('🚀 Scraping started. Please wait while the playlist scrolls to the end...') console.log('ℹ️ To stop early, run: window.__stopScraper = true;')
while (stagnantTurns < maxStagnant && !window.__stopScraper) { // Collect tracks from currently mounted DOM nodes in the virtual list document.querySelectorAll('ytmusic-responsive-list-item-renderer').forEach((row) => { const title = row.querySelector('.title')?.innerText?.trim() const artist = row.querySelector('.secondary-flex-columns')?.innerText?.split('•')[0]?.trim() if (title && artist) tracks.add(`${artist} — ${title}`) })
if (tracks.size === lastSize) { stagnantTurns++ } else { stagnantTurns = 0 lastSize = tracks.size console.log(`Unique tracks collected: ${tracks.size}`) }
// Scroll to the last mounted element to trigger the next batch const items = document.querySelectorAll('ytmusic-responsive-list-item-renderer') if (items.length) { items[items.length - 1].scrollIntoView({ behavior: 'instant', block: 'end' }) } window.scrollTo(0, document.documentElement.scrollHeight)
await new Promise((res) => setTimeout(res, 850)) }
const result = Array.from(tracks).join('\n') window.__collectedTracks = result
// DevTools provides copy() in some browsers try { copy(result) } catch (e) {}
document.getElementById('ytm-scraper-result')?.remove() const banner = document.createElement('div') banner.id = 'ytm-scraper-result' banner.style.cssText = ` position: fixed; top: 20px; right: 20px; z-index: 999999; background: #181818; color: #fff; border: 2px solid #ff0000; border-radius: 12px; padding: 16px 20px; font-family: sans-serif; box-shadow: 0 10px 30px rgba(0,0,0,0.8); display: flex; flex-direction: column; gap: 10px; ` banner.innerHTML = ` <div style="font-size: 15px; font-weight: bold; color: #4ade80;"> ✅ Scraping complete! Found: ${tracks.size} tracks </div> <div style="display: flex; gap: 8px;"> <button id="ytm-copy-btn" style=" background: #ff0000; color: #fff; border: none; border-radius: 6px; padding: 8px 14px; font-weight: bold; cursor: pointer;"> 📋 Copy to clipboard </button> <button id="ytm-dl-btn" style=" background: #333; color: #fff; border: 1px solid #555; border-radius: 6px; padding: 8px 14px; cursor: pointer;"> 💾 Download .txt </button> <button id="ytm-close-btn" style=" background: transparent; color: #888; border: none; padding: 8px; cursor: pointer;"> ✕ </button> </div> `
document.body.appendChild(banner)
document.getElementById('ytm-copy-btn').onclick = async () => { const btn = document.getElementById('ytm-copy-btn') try { await navigator.clipboard.writeText(window.__collectedTracks) btn.innerText = 'Copied! ✓' btn.style.background = '#16a34a' } catch (error) { btn.innerText = 'Copy failed — use Download .txt' console.error('Clipboard copy failed:', error) } }
document.getElementById('ytm-dl-btn').onclick = () => { const blob = new Blob([window.__collectedTracks], { type: 'text/plain;charset=utf-8' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `liked_tracks_${tracks.size}.txt` a.click() setTimeout(() => URL.revokeObjectURL(url), 1000) }
document.getElementById('ytm-close-btn').onclick = () => banner.remove()
console.log( `🎉 Done! Collected ${tracks.size} tracks. Use the on-screen buttons to copy or download.`, )})()