Exportar una lista de Google Maps a CSV, Excel o KML, gratis (guardadas o compartidas)

Descarga cualquier lista de Google Maps como hoja de cálculo o archivo KML: nombre, dirección, coordenadas, tus notas y un enlace de cada sitio. Funciona con tus listas guardadas y con las que te han compartido. Gratis, en tu navegador, sin instalar nada ni conectar tu cuenta de Google a ninguna web.

Abre la lista en el navegador del ordenador (Guardados > Listas, o el enlace que te han compartido), recarga la página una vez y ejecuta el script.

export-google-maps-list.js · 144 líneaspégalo en la consola (F12) de www.google.com
// Responsive Muse · Google Maps List Exporter · v1.0 · 2026-11-05
// Saves a Google Maps list (one of your saved lists or any list someone shared with you) to CSV,
// KML or plain text: name, address, latitude/longitude, your note, date added and a Maps link for
// every place. Open the list on Google Maps in a computer browser and run the script.
// It reads the list the page already loaded: it makes no network requests of its own and never
// reads cookies, passwords or tokens.
(async () => {
  const TOOL = 'Exportar lista de Google Maps';
  const FORMAT = 'csv';        // 'csv' (Excel, Sheets), 'kml' (Google My Maps, Google Earth) or 'txt' (one place per line)

  if (!/^(www\.)?google\.[a-z.]+$/.test(location.hostname) || !location.pathname.startsWith('/maps')) {
    alert('Abre primero la lista en Google Maps (Guardados > Listas, o el enlace que te han compartido):\nhttps://www.google.com/maps');
    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]]);
  };

  // 1. The whole list comes with the page itself, inside its start-up data
  let raw = '';
  const seek = v => {
    if (raw) return;
    if (typeof v === 'string') {
      if (v.startsWith(")]}'") && v.includes('placelists/list')) raw = v;
    } else if (v && typeof v === 'object') {
      for (const k in v) seek(v[k]);
    }
  };
  seek(window.APP_INITIALIZATION_STATE);
  let info = null;
  try { info = JSON.parse(raw.slice(raw.indexOf('\n') + 1))[0]; } catch (e) { /* handled below */ }
  const items = Array.isArray(info?.[8]) ? info[8] : [];
  const title = typeof info?.[4] === 'string' ? info[4] : '';
  // Opening a list from the menu changes the page without reloading it, so the start-up data
  // may belong to another list (or to none): then a reload fixes it.
  const shown = document.title.replace(/\s*[-–]\s*Google Maps\s*$/, '').trim();
  if (!items.length || !title || (shown && shown !== 'Google Maps' && shown !== title)) {
    panel.finish('Recarga la página (F5) con la lista abierta y vuelve a ejecutar el script.\n' +
      'Si sigue sin encontrar nada, abre la propia lista (no el menú Guardados) y comprueba que tiene sitios.');
    return 0;
  }

  // 2. One row per place
  const day = t => t ? new Date(t * 1000).toISOString().slice(0, 10) : '';
  const places = items.map(e => {
    const p = Array.isArray(e?.[1]) ? e[1] : [];
    const at = Array.isArray(p[5]) ? p[5] : [];
    const cid = Array.isArray(p[6]) && p[6][1] ? BigInt.asUintN(64, BigInt(p[6][1])).toString() : '';
    const name = String(e?.[2] || (p[2] || '').split(',')[0] || '').trim();
    return {
      name,
      address: String(p[4] || '').trim(),
      lat: typeof at[2] === 'number' ? at[2] : '',
      lng: typeof at[3] === 'number' ? at[3] : '',
      note: String(e?.[3] || '').trim(),
      added: day(Array.isArray(e?.[9]) && typeof e[9][0] === 'number' ? e[9][0] : 0),
      url: cid ? `https://maps.google.com/?cid=${cid}`
        : name ? `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(name + ' ' + (p[4] || ''))}` : '',
    };
  }).filter(x => x.name);

  // 3. Build the file and offer it
  const cell = v => '"' + String(v).replace(/"/g, '""') + '"';
  const xml = v => String(v).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  let body;
  if (FORMAT === 'kml') {
    body = ['<?xml version="1.0" encoding="UTF-8"?>', '<kml xmlns="http://www.opengis.net/kml/2.2"><Document>',
      `<name>${xml(title)}</name>`,
      ...places.filter(x => x.lat !== '').map(x => '<Placemark>' +
        `<name>${xml(x.name)}</name>` +
        `<description>${xml([x.address, x.note, x.url].filter(Boolean).join('\n'))}</description>` +
        `<Point><coordinates>${x.lng},${x.lat},0</coordinates></Point></Placemark>`),
      '</Document></kml>'].join('\n');
  } else if (FORMAT === 'txt') {
    body = places.map(x => [x.name, x.address, x.note].filter(Boolean).join(' - ')).join('\n');
  } else {
    body = ['Nombre,Dirección,Latitud,Longitud,Nota,Fecha en que se añadió,URL de Google Maps',
      ...places.map(x => [x.name, x.address, x.lat, x.lng, x.note, x.added, x.url].map(cell).join(','))].join('\n');
  }
  const total = typeof info[12] === 'number' ? info[12] : places.length;
  const notes = places.filter(x => x.note).length;
  const summary = `"${title}": ${many(places.length, 'lugar')}` +
    (total > places.length ? ` de ${total} (Google solo ha enviado estos con la página)` : '') +
    `, ${many(notes, 'nota')}.`;
  deliver(summary, body, `google-maps-list-${title.replace(/[\\/:*?"<>|\s]+/g, '_').slice(0, 60) || 'list'}.${FORMAT}`);
  return places.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: 144 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 lista de Google Maps a tu barra de marcadores y haz clic en él estando en www.google.com. Así no sale el aviso.

Marcador: arrastra el botón del medio a tu barra de marcadores, abre www.google.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 5 nov 2026
  • No envía nada a ningún sitio. Sin fetch, XHR ni scripts externos. La única actividad de red es la de www.google.com cargando tu lista.
  • No toca tu sesión. No lee cookies, contraseñas, tokens ni el almacenamiento del navegador.
  • Solo funciona en www.google.com. En cualquier otra web se detiene antes de hacer nada.
  • Corto y legible. 144 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: e3fd4d27c6b92c58…
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 www.google.com.
¿Te ha funcionado?

Cómo usarlo

  1. Abre la lista en Google Maps en el navegador del ordenador: Guardados > Listas para las tuyas, o el enlace que te han enviado. Después recarga la página una vez (F5).
  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. Lee la lista que la página ya ha cargado y te ofrece el archivo al momento.

Qué obtienes

Una fila por sitio: nombre, dirección, latitud, longitud, la nota que guardaste, la fecha en que se añadió y un enlace de Google Maps que abre ese sitio exacto. Elige KML para importar la lista en Google My Maps, Google Earth u otra app de mapas, o TXT para una lista simple.

¿Por qué no Google Takeout?

Takeout solo exporta las listas que has creado tú, tarda en llegar y te da enlaces en vez de direcciones y coordenadas. Las demás opciones son scripts de Python, scrapers de pago o extensiones que piden acceso a tu cuenta. Este es corto, se puede leer y solo funciona en Google Maps, en tu propia pestaña.

Preguntas frecuentes

¿Funciona con listas que me han compartido?

Sí. Vale cualquier lista que puedas abrir en Google Maps: las tuyas y las que te han compartido por enlace. Google Takeout solo exporta las listas que has creado tú.

¿Qué trae el archivo?

Una fila por sitio: nombre, dirección, latitud y longitud, tu nota, la fecha en que lo añadiste y un enlace de Google Maps que abre ese sitio exacto.

¿Cómo paso la lista a Apple Maps, Waze u otra app?

Descarga el KML: Google My Maps, Google Earth y la mayoría de apps de mapas lo importan. Para una hoja de cálculo, elige CSV.

Me dice «Recarga la página». ¿Por qué?

Cuando abres una lista desde el menú Guardados, Google Maps cambia la vista sin volver a cargar la página, así que los datos de la lista aún no están. Pulsa F5 con la lista abierta y vuelve a ejecutar el script.

¿Tengo que iniciar sesión?

Solo para tus listas privadas. Las listas compartidas se abren para cualquiera que tenga el enlace.

Más herramientas de Google Maps

Exportar y hacer copia