Exportar los Me gusta de YouTube Music a CSV o Excel, gratis (sin iniciar sesión en otras webs)

Descarga todas las canciones que te gustan en YouTube Music como hoja de cálculo o lista simple: título, artista, álbum, duración y enlace. Gratis, en tu navegador, sin instalar nada ni dar acceso a tu cuenta de Google a ninguna web de transferencia.

Inicia sesión en music.youtube.com en el navegador del ordenador, abre Música que me gusta (Biblioteca > Playlists) y ejecuta el script.

export-youtube-music-playlist.js · 140 líneaspégalo en la consola (F12) de music.youtube.com
// Responsive Muse · YouTube Music Playlist Exporter · v1.0 · 2026-10-31
// Saves any YouTube Music playlist or album you can open on music.youtube.com (your own playlists,
// your Liked Music or public ones) to CSV or TXT: title, artist, album, duration and link. Useful
// to back up a playlist or move it to Spotify, Apple Music or Tidal. Long playlists load while
// the script scrolls. It makes no network requests of its own and never reads cookies,
// passwords or tokens.
(async () => {
  const TOOL = 'Exportar playlist de YouTube Music';
  const FORMAT = 'csv';        // 'csv' (Excel, Sheets, playlist converters) or 'txt' ("Artist - Title", one per line)

  if (location.hostname !== 'music.youtube.com' || !/^\/(playlist|browse)/.test(location.pathname)) {
    alert('Abre primero una playlist en YouTube Music, por ejemplo tus Me gusta:\nhttps://music.youtube.com/playlist?list=LM');
    return;
  }
  // A small box on the page shows progress and asks before changing anything,
  // so you never need to read or edit the console.
  const many = (n, word) => `${n} ${n === 1 ? word : ({ canal: 'canales', 'canción': 'canciones', 'publicación': 'publicaciones', 'elemento guardado': 'elementos guardados', lugar: 'lugares' })[word] || word + 's'}`;   // 1 vídeo, 2 vídeos
  const panel = (() => {
    const box = document.createElement('div');
    box.style.cssText = 'display:block!important;position:fixed;right:16px;bottom:16px;z-index:2147483647;width:340px;max-width:calc(100vw - 32px);' +
      'background:#111318;color:#e6e8ee;font:14px/1.5 system-ui,sans-serif;border-radius:12px;padding:16px;' +
      'box-shadow:0 8px 30px rgba(0,0,0,.4);text-align:left';
    const head = document.createElement('strong');
    head.textContent = TOOL;
    const msg = document.createElement('p');
    msg.style.cssText = 'margin:8px 0 12px;white-space:pre-line';
    const row = document.createElement('div');
    row.style.cssText = 'display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end';
    box.append(head, msg, row);
    document.body.append(box);
    const button = (label, primary, onClick) => {
      const b = document.createElement('button');
      b.textContent = label;
      b.style.cssText = 'font:600 14px system-ui,sans-serif;padding:8px 14px;border-radius:8px;cursor:pointer;' +
        (primary ? 'background:#0f766e;color:#fff;border:1px solid #0f766e' : 'background:none;color:#e6e8ee;border:1px solid #3a3f4b');
      b.onclick = onClick;
      row.append(b);
    };
    return {
      text(t) { msg.textContent = t; },
      ask(t, yes) {
        msg.textContent = t;
        row.replaceChildren();
        return new Promise(r => {
          button('Cancelar', false, () => { row.replaceChildren(); r(false); });
          button(yes, true, () => { row.replaceChildren(); r(true); });
        });
      },
      stoppable(onStop) { row.replaceChildren(); button('Parar', false, onStop); },
      actions(t, list) {
        msg.textContent = t;
        row.replaceChildren();
        list.forEach(([label, primary, run]) => button(label, primary, run));
      },
      finish(t) { this.actions(t, [['Cerrar', true, () => box.remove()]]); },
      close() { box.remove(); },
    };
  })();
  // Offer the result as a downloaded file or as clipboard text (a real click, so it always works)
  const deliver = (summary, body, file) => {
    const save = () => {
      const a = document.createElement('a');
      a.href = URL.createObjectURL(new Blob([/\.csv$/.test(file) ? '\ufeff' + body : body], { type: 'text/plain;charset=utf-8' }));
      a.download = file;
      a.click();
      setTimeout(() => URL.revokeObjectURL(a.href), 5000);
      panel.text(`${summary}\nGuardado como ${file} (mira tu carpeta de Descargas).`);
    };
    const copy = () => navigator.clipboard.writeText(body)
      .then(() => panel.text(`${summary}\nCopiado. Pégalo en una hoja de cálculo o en una nota.`))
      .catch(() => panel.text(`${summary}\nEl navegador ha bloqueado el portapapeles: usa Descargar.`));
    panel.actions(summary, [['Cerrar', false, () => panel.close()], ['Copiar', false, copy], ['Descargar', true, save]]);
  };
  const sleep = ms => new Promise(r => setTimeout(r, ms));
  const tracks = new Map();
  const text = el => (el?.textContent || '').replace(/\s+/g, ' ').trim();

  // Read the songs currently on the page (YouTube Music keeps every loaded row in the page)
  const collect = () => {
    for (const row of document.querySelectorAll('ytmusic-responsive-list-item-renderer')) {
      const title = text(row.querySelector('.title-column .title') || row.querySelector('.title'));
      if (!title) continue;
      // Secondary columns: artist(s), then the album (only when it links to an album page;
      // on music videos and episodes that column holds the upload date instead)
      const cols = [...row.querySelectorAll('.secondary-flex-columns yt-formatted-string')].map(text);
      const hasAlbum = !!row.querySelector('.secondary-flex-columns a[href^="browse/"]');
      const watch = row.querySelector('a[href*="watch?v="]');
      const id = watch ? new URL(watch.href, location.origin).searchParams.get('v') : '';
      const link = id ? 'https://music.youtube.com/watch?v=' + id : (row.querySelector('.title a')?.href || '');
      const key = link || title + '|' + cols[0];
      if (tracks.has(key)) continue;
      tracks.set(key, {
        n: tracks.size + 1,
        title,
        artist: cols[0] || '',
        album: hasAlbum ? cols[1] || '' : '',
        duration: text(row.querySelector('.fixed-column yt-formatted-string, .fixed-columns yt-formatted-string')),
        url: link,
      });
    }
  };

  // YouTube Music scrolls an inner panel (div#content), not the window: find it from the first row
  const scroller = (() => {
    for (let e = document.querySelector('ytmusic-responsive-list-item-renderer'); e && e !== document.body; e = e.parentElement) {
      if (e.scrollHeight > e.clientHeight + 50 && /auto|scroll/.test(getComputedStyle(e).overflowY)) return e;
    }
    return document.scrollingElement;
  })();

  // 1. Scroll to the bottom again and again: YouTube Music loads the next 100 songs each time
  let stop = false;
  panel.stoppable(() => { stop = true; });
  let idle = 0;
  while (idle < 4 && !stop) {
    const before = tracks.size;
    collect();
    scroller.scrollTop = scroller.scrollHeight;
    document.querySelector('ytmusic-continuation-item-renderer')?.scrollIntoView({ block: 'end' });
    await sleep(1500);
    idle = tracks.size === before ? idle + 1 : 0;
    panel.text(`Recogiendo canciones… ${tracks.size}`);
  }
  const list = [...tracks.values()];
  if (!list.length) {
    panel.finish('No se han encontrado canciones. Puede que YouTube Music haya cambiado su diseño: avísanos en responsive-muse.com.');
    return 0;
  }

  // 2. Build the file and offer it
  const cell = v => '"' + String(v).replace(/"/g, '""') + '"';
  const body = FORMAT === 'txt'
    ? list.map(t => `${t.artist} - ${t.title}`).join('\n')
    : ['#,Título,Artista,Álbum,Duración,URL', ...list.map(t =>
        [t.n, t.title, t.artist, t.album, t.duration, t.url].map(cell).join(','))].join('\n');
  const name = (document.title.replace(/ - YouTube Music$/, '') || 'playlist').replace(/[\\/:*?"<>|]+/g, '_');
  deliver(`${stop ? 'Parado antes de terminar. ' : ''}Listo: ${many(list.length, 'canción')}.`, body, `${name}.${FORMAT}`);
  return list.length;
})();

🛡️ ¿Chrome te dice «No pegues código…»? Es normal. Escribe allow pasting en la consola (o permitir pegar si tu Chrome está en español), pulsa Intro y vuelve a pegar. Solo hace falta una vez.

¿Por qué avisa Chrome?

Chrome lo muestra la primera vez que alguien pega algo en la consola, para proteger de estafas en las que te piden pegar código desconocido. Hace bien en avisar, y por eso este script está entero a la vista: 140 líneas comentadas que no envían nada a ningún sitio ni tocan tus contraseñas o cookies. Por qué es seguro.

¿Prefieres no usar la consola? Arrastra el botón Exportar Me gusta de YouTube Music a tu barra de marcadores y haz clic en él estando en music.youtube.com. Así no sale el aviso.

Marcador: arrastra el botón del medio a tu barra de marcadores, abre music.youtube.com y pulsa el marcador. Ejecuta el mismo script con las opciones de arriba.

Por qué es seguro ejecutarloComprobación automática superada 9 nov 2026 · probado en una cuenta real el 31 oct 2026
  • No envía nada a ningún sitio. Sin fetch, XHR ni scripts externos. La única actividad de red es la de music.youtube.com cargando tu lista.
  • No toca tu sesión. No lee cookies, contraseñas, tokens ni el almacenamiento del navegador.
  • Solo funciona en music.youtube.com. En cualquier otra web se detiene antes de hacer nada.
  • Corto y legible. 140 líneas comentadas, sin minificar ni ofuscar.
  • Muestra su progreso en la página. Un pequeño recuadro te dice qué está haciendo y al final te ofrece Descargar o Copiar.
  • El mismo código para todos. SHA-256 de la versión por defecto: 0b3480b53a21d0e3…
Compruébalo tú mismo en 30 segundos
  1. Léelo: todas las líneas están arriba, con comentarios.
  2. Busca en el código fetch, XMLHttpRequest, cookie, localStorage o eval. No aparece ninguna.
  3. Abre la pestaña Red (Network) antes de ejecutarlo: solo verás peticiones a music.youtube.com.
¿Te ha funcionado?

Cómo usarlo

  1. Inicia sesión en music.youtube.com en el navegador del ordenador y abre Música que me gusta (Biblioteca > Playlists, o directamente music.youtube.com/playlist?list=LM).
  2. Abre la consola: F12 o Ctrl+Mayús+J (Cmd+Opción+J en Mac). Si Chrome te lo pide, escribe permitir pegar y pulsa Enter.
  3. Copia el script, pégalo en la consola y pulsa Enter. Recorre la lista (de 100 en 100 canciones) y te ofrece el archivo.

Qué obtienes

Una fila por canción con su posición, título, artista, álbum (cuando YouTube Music lo muestra), duración y enlace. Elige TXT para una lista «Artista – Título» que entienden los conversores de playlists y los buscadores.

¿Por qué no Google Takeout o un conversor?

Takeout envía tu biblioteca, no siempre tus Me gusta, y solo con los ID de los vídeos. Las webs de transferencia te piden entrar con Google y sus planes gratis limitan cuántas canciones puedes pasar. Este script lee la lista que ya tienes en pantalla.

Preguntas frecuentes

¿Google Takeout no exporta mis Me gusta?

Takeout exporta las canciones de tu biblioteca, no siempre las que marcaste con Me gusta, y esperas un email con los ID de los vídeos. Este script lee tu lista Música que me gusta y te da títulos, artistas y álbumes en un minuto.

¿Puedo pasar mis Me gusta a Spotify o Apple Music?

Sí. Expórtalos en CSV e importa el archivo con un conversor de playlists, o elige TXT («Artista - Título» por línea) y pega la lista en uno.

¿Es seguro?

El script se ejecuta en tu propia pestaña de YouTube Music, no envía nada a ningún sitio y nunca toca tu contraseña. No das acceso a tu cuenta de Google a ninguna app, al contrario que las webs de transferencia que te piden iniciar sesión.

¿Por qué salen menos canciones de las que marqué?

YouTube Music oculta las canciones que ya no están disponibles (borradas o bloqueadas en tu país), así que no se pueden exportar. Se exporta todo lo que ves en la lista.

Más herramientas para YouTube