Exportar tu historial de pedidos de Amazon a Excel (CSV)

Descarga todos tus pedidos de Amazon y sus productos en una hoja de cálculo: fecha, número, importe, estado, producto y enlaces. Funciona en Amazon.es y en cualquier otra tienda de Amazon.

Funciona en todas las tiendas de Amazon: .es, .com, .co.uk, .de, .fr, .it, .com.mx… Abre Mis pedidos en tu tienda.

export-orders.js · 154 líneaspégalo en la consola (F12) de www.amazon.com
// Responsive Muse · Amazon Order History Exporter · v1.1 · 2026-10-22
// Exports your Amazon orders to CSV, one row per product: order date, order number, order total,
// status, product title, ASIN and links. Works on any Amazon store (.com, .co.uk, .de, .es…).
// Runs only on amazon.*/your-orders (Returns & Orders). To read every page of results it opens
// them in a hidden frame of the same Amazon site, like clicking "Next" yourself. It never sends
// anything anywhere and never reads cookies, passwords or tokens.
(async () => {
  const TOOL = 'Exportar pedidos de Amazon';
  const YEARS = 'all';         // 'all', one year like '2025', or several like '2024,2025'
  const DELAY = 1500;          // pause between pages, in milliseconds

  if (!/^(www\.|smile\.)?amazon\.[a-z.]+$/.test(location.hostname) ||
      !/^\/(your-orders|gp\/css\/order-history|gp\/your-account\/order-history)/.test(location.pathname)) {
    alert('Abre primero Devoluciones y pedidos (con tu sesión iniciada),\npor ejemplo amazon.es/your-orders/orders');
    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' })[word] || word + 's'}`;   // 1 vídeo, 2 vídeos
  const panel = (() => {
    const box = document.createElement('div');
    box.style.cssText = '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));

  // Years offered by Amazon's own "orders placed in" menu
  const offered = [...document.querySelectorAll('select[name="timeFilter"] option, #time-filter option')]
    .map(o => o.value).filter(v => /^year-\d{4}$/.test(v)).map(v => v.slice(5));
  const years = YEARS === 'all' ? offered : String(YEARS).split(',').map(y => y.trim()).filter(Boolean);
  if (!years.length) {
    panel.finish('No se encuentra el menú de años. Puede que Amazon haya cambiado su diseño: avísanos en responsive-muse.com.');
    return 0;
  }

  // Load one results page of Amazon's own order history in a hidden frame and wait for it
  const loadPage = path => new Promise(resolve => {
    const frame = document.createElement('iframe');
    frame.style.cssText = 'position:absolute;left:-9999px;width:1000px;height:800px';
    const done = doc => { resolve(doc); setTimeout(() => frame.remove(), 0); };
    frame.onload = () => done(frame.contentDocument);
    setTimeout(() => done(null), 30000);
    frame.src = new URL(path, location.origin).href;
    document.body.appendChild(frame);
  });

  // Read the order cards of one page
  const readOrders = doc => [...doc.querySelectorAll('.js-order-card, .order-card')].map(card => {
    const text = el => (el?.textContent || '').replace(/\s+/g, ' ').trim();
    // Header blocks: "Order placed / <date>", "Total / <amount>", "Ship to / <name>"
    const blocks = card.querySelectorAll('.order-header__header-list-item');
    const values = [...(blocks.length ? blocks : card.querySelectorAll('.order-header .a-column'))]
      .map(b => text(b.querySelectorAll('.a-row')[1] || b.querySelector('.a-size-base')));
    const id = text(card.querySelector('.yohtmlc-order-id bdi, .yohtmlc-order-id span[dir="ltr"]'));
    // Amazon leaves the status empty on older delivered orders
    const status = [...card.querySelectorAll('.delivery-box__primary-text, .yohtmlc-shipment-status-primaryText')]
      .map(text).find(Boolean) || '';
    const products = new Map();
    card.querySelectorAll('a[href*="/dp/"], a[href*="/gp/product/"]').forEach(a => {
      const asin = (a.href.match(/\/(?:dp|product)\/([A-Z0-9]{10})/) || [])[1];
      if (!asin) return;
      const title = text(a) || a.querySelector('img')?.alt || '';
      if (!products.has(asin) || (title && !products.get(asin))) products.set(asin, title);
    });
    return { id, date: values[0] || '', total: values[1] || '', status, products: [...products] };
  });

  // 1. Every page of every year
  let stop = false;
  panel.stoppable(() => { stop = true; });
  const orders = [];
  for (const year of years) {
    for (let page = 1; page <= 100 && !stop; page++) {
      panel.text(`Leyendo ${year}, página ${page}… ${orders.length} pedidos hasta ahora`);
      const doc = await loadPage(`/your-orders/orders?timeFilter=year-${year}&page=${page}`);
      if (!doc) break;
      const found = readOrders(doc).filter(o => o.id && !orders.some(x => x.id === o.id));
      orders.push(...found);
      const nextDisabled = doc.querySelector('.a-pagination .a-last.a-disabled');
      const hasNext = doc.querySelector('.a-pagination .a-last a');
      if (!found.length || nextDisabled || !hasNext) break;
      await sleep(DELAY);
    }
    if (stop) break;
  }
  if (!orders.length) {
    panel.finish('No hay pedidos en esos años. Revisa los años, o puede que Amazon haya cambiado su diseño.');
    return 0;
  }

  // 2. One row per product, then offer the file
  const cell = v => '"' + String(v).replace(/"/g, '""') + '"';
  const rows = orders.flatMap(o => (o.products.length ? o.products : [['', '']]).map(([asin, title]) => [
    o.date, o.id, o.total, o.status, title, asin, asin ? `${location.origin}/dp/${asin}` : '',
    `${location.origin}/gp/your-account/order-details?orderID=${o.id}`,
  ]));
  const body = ['Fecha del pedido,Número de pedido,Importe,Estado,Producto,ASIN,URL del producto,URL del pedido',
    ...rows.map(r => r.map(cell).join(','))].join('\n');
  deliver(`${stop ? 'Parado antes de terminar. ' : ''}Listo: ${many(orders.length, 'pedido')} (${many(rows.length, 'producto')}).`, body,
    `amazon-orders-${years.join('-')}.csv`);
  return orders.length;
})();

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

Por qué es seguro ejecutarloComprobación automática superada 23 oct 2026 · probado en una cuenta real el 22 oct 2026
  • No envía nada a ningún sitio. Sin fetch, XHR ni scripts externos. La única actividad de red es la de www.amazon.com cargando tu lista.
  • No toca tu sesión. No lee cookies, contraseñas, tokens ni el almacenamiento del navegador.
  • Solo funciona en www.amazon.com. En cualquier otra web se detiene antes de hacer nada.
  • Corto y legible. 154 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: ccbd38abc50cbd0c…
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.amazon.com.
¿Te ha funcionado?

Cómo usarlo

  1. Abre Mis pedidos en tu tienda de Amazon con tu sesión iniciada.
  2. Abre la consola: F12 o Ctrl+Mayús+J (Cmd+Opción+J en Mac). Si Chrome te lo pide, escribe permitir pegar (o allow pasting si lo tienes en inglés) y pulsa Enter.
  3. Elige las opciones, copia el script, pégalo en la consola y pulsa Enter. Al terminar aparece un recuadro: pulsa Descargar (o Copiar).

¿Y el informe de pedidos de Amazon?

Amazon retiró sus «Informes del historial de pedidos». Lo único oficial que queda es una solicitud de datos que puede tardar días. Este script lee las mismas páginas de Mis pedidos que ves tú, año a año, y te da el CSV en un par de minutos.

Preguntas frecuentes

¿Amazon no tiene un informe de pedidos?

Lo tenía («Informes del historial de pedidos»), pero Amazon lo retiró. La única opción oficial ahora es una solicitud de datos que puede tardar días. Este script lee las mismas páginas que ves en Mis pedidos.

¿Por qué el estado sale vacío en pedidos antiguos?

Amazon deja en blanco el estado de entrega de los pedidos antiguos, así que no hay nada que exportar ahí. Las fechas, importes y productos salen siempre.

¿Es lento con muchos pedidos?

Lee una página de 10 pedidos cada 2–3 segundos. Unos cientos de pedidos tardan un minuto o dos. Deja la pestaña abierta.

¿Ve mi tarjeta o mi dirección?

Solo lee la lista de pedidos: fecha, número, importe, estado y productos. No abre páginas de pago.

Más herramientas gratis

Exportar y hacer copia