Descarga cualquier playlist, álbum o tus Canciones favoritas de Deezer como hoja de cálculo o lista simple: título, artista, álbum, duración y enlace al álbum. Gratis, en tu navegador, sin instalar nada ni dar acceso a tu cuenta a ninguna web de transferencia.
Funciona en Deezer para la web (deezer.com) en Windows, Mac, Linux y Chromebook. Abre la playlist y ejecuta el script.
// Responsive Muse · Deezer Playlist Exporter · v1.0 · 2026-11-12
// Saves any Deezer playlist, album or Favourite tracks list that you can open on deezer.com
// to CSV or TXT: title, artists, album, duration and album link. Useful to back up a playlist
// or move it to Spotify, Apple Music, YouTube 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 Deezer';
const FORMAT = 'csv'; // 'csv' (Excel, Sheets, playlist converters) or 'txt' ("Artist - Title", one per line)
if (!/(^|\.)deezer\.com$/.test(location.hostname) || !/\/(playlist|album)\/\d+|\/profile\/\d+\/loved/.test(location.pathname)) {
alert('Abre primero una playlist, un álbum o tus Canciones favoritas en deezer.com, por ejemplo:\nhttps://www.deezer.com/es/playlist/3155776842');
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 clean = s => (s || '').replace(/\s+/g, ' ').trim();
const grid = document.querySelector('[aria-rowcount]');
const expected = grid ? Number(grid.getAttribute('aria-rowcount')) : 0;
const heading = clean(document.querySelector('[data-testid="masthead"] h1, [data-testid="masthead"] h2')?.textContent);
// album pages only name the album's artist once, at the top, and don't link the album in each row
const onAlbum = /\/album\//.test(location.pathname);
const pageAlbum = onAlbum ? heading : '';
const pageArtist = onAlbum ? clean(document.querySelector('[data-testid="masthead-subtitle"]')?.textContent) : '';
const pageUrl = onAlbum ? 'https://www.deezer.com/album/' + location.pathname.match(/\/album\/(\d+)/)[1] : '';
// Read the songs currently on screen (rows are recycled while scrolling: key = row number)
const collect = () => {
for (const row of (grid || document).querySelectorAll('[role="row"][aria-rowindex]')) {
const n = Number(row.getAttribute('aria-rowindex'));
const title = row.querySelector('[data-testid="title"]');
if (!title || !(n > 0) || tracks.has(n)) continue;
const album = row.querySelector('a[data-testid="album"]');
tracks.set(n, {
n,
// the title carries the row number for screen readers ("12. Song"): drop it
title: clean(title.textContent).replace(new RegExp('^' + n + '\\.\\s*'), ''),
artist: [...new Set([pageArtist, ...[...row.querySelectorAll('[data-testid="artist"]')].map(x => clean(x.textContent))])].filter(Boolean).join(', '),
album: clean(album?.textContent) || pageAlbum,
duration: clean(row.querySelector('[data-testid="duration"]')?.textContent).replace(/^0(\d:)/, '$1'),
url: album ? 'https://www.deezer.com/' + album.getAttribute('href').replace(/^\/([a-z]{2}(-[a-z]{2})?\/)?/i, '') : pageUrl,
});
}
};
// 1. Scroll to the end, collecting as we go, until nothing new appears three times in a row
let stop = false;
panel.stoppable(() => { stop = true; });
window.scrollTo(0, 0);
await sleep(800);
let idle = 0;
while (idle < 3 && !stop && !(expected && tracks.size >= expected)) {
const before = tracks.size;
collect();
[...document.querySelectorAll('[role="row"][aria-rowindex]')].pop()?.scrollIntoView({ block: 'start' });
await sleep(700);
collect();
idle = tracks.size === before ? idle + 1 : 0;
panel.text(`Recogiendo canciones… ${tracks.size}${expected ? ' de ' + expected : ''}`);
}
const list = [...tracks.values()].sort((x, y) => x.n - y.n);
if (!list.length) {
panel.finish('No se han encontrado canciones. ¿La playlist está vacía o es privada? Si no, puede que Deezer 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 del álbum', ...list.map(t =>
[t.n, t.title, t.artist, t.album, t.duration, t.url].map(cell).join(','))].join('\n');
const missing = expected && list.length < expected ? ` (la playlist dice ${expected}; si faltan, baja hasta el final y vuelve a ejecutarlo)` : '';
const name = (heading || 'deezer-playlist').replace(/[\\/:*?"<>|]+/g, '_');
deliver(`${stop ? 'Parado antes de terminar. ' : ''}Listo: ${many(list.length, 'canción')}${missing}.`, 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: 137 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 playlist de Deezer a tu barra de marcadores y haz clic en él estando en www.deezer.com. Así no sale el aviso.
Marcador: arrastra el botón del medio a tu barra de marcadores, abre www.deezer.com y pulsa el marcador. Ejecuta el mismo script con las opciones de arriba.
- No envía nada a ningún sitio. Sin fetch, XHR ni scripts externos. La única actividad de red es la de www.deezer.com cargando tu lista.
- No toca tu sesión. No lee cookies, contraseñas, tokens ni el almacenamiento del navegador.
- Solo funciona en www.deezer.com. En cualquier otra web se detiene antes de hacer nada.
- Corto y legible. 137 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:
c999a5491e04f1a4…
Compruébalo tú mismo en 30 segundos
- Léelo: todas las líneas están arriba, con comentarios.
- Busca en el código
fetch,XMLHttpRequest,cookie,localStorageoeval. No aparece ninguna. - Abre la pestaña Red (Network) antes de ejecutarlo: solo verás peticiones a www.deezer.com.
Cómo usarlo
- Abre la playlist en deezer.com en el navegador del ordenador. Las playlists públicas y los álbumes funcionan sin iniciar sesión; para tus playlists o tus Canciones favoritas, inicia sesión antes.
- Abre la consola: F12 o Ctrl+Mayús+J (Cmd+Opción+J en Mac). Si Chrome te lo pide, escribe
permitir pegary pulsa Enter. - Copia el script, pégalo en la consola y pulsa Enter. Recorre la lista y te ofrece el archivo.
Qué obtienes
Una fila por canción con su posición, título, artistas, álbum, duración y enlace al álbum. Elige TXT para una lista «Artista – Título» que entienden los conversores de playlists y los buscadores.
¿Por qué no una web de transferencia?
Las webs de transferencia te piden entrar en Deezer y en el otro servicio, y sus planes gratis limitan cuántas canciones puedes pasar. La solicitud de datos de Deezer tarda días. Este script lee la lista que ya tienes en pantalla y no envía nada a ningún sitio.
Preguntas frecuentes
¿Deezer no tiene botón de exportar?
No. Puedes pedir tus datos personales a Deezer, pero llegan días después y no como archivo de playlist. Este script guarda la playlist que tienes abierta en unos segundos.
¿Tengo que iniciar sesión o conectar mi cuenta?
No para playlists públicas y álbumes: se abren sin iniciar sesión. Tus playlists y tus Canciones favoritas necesitan tu sesión. Nunca autorizas a ninguna app.
¿Puedo pasar la playlist a Spotify, Apple Music o TIDAL?
Sí. Expórtala en CSV e impórtala con un conversor de playlists, o usa el formato TXT («Artista - Título» por línea) y pégalo en uno.
¿Funciona con playlists largas?
Sí. Deezer solo deja unas pocas filas en pantalla, así que el script se desplaza y las recoge todas.
