Quitar todos los «me gusta» de X (Twitter) de una vez

Quita todos tus «me gusta» de X, o solo los más recientes, a un ritmo seguro para tu cuenta. Gratis, en tu navegador.

unlike-all.js · 101 líneaspégalo en la consola (F12) de x.com
// Responsive Muse · Unlike All Posts on X (Twitter) · v1.1 · 2026-10-22
// Removes your likes, newest first: all of them, or only the latest LIMIT. Runs only on
// x.com/i/history/likes. It asks before changing anything, then clicks the same heart button
// you would, at a human pace. It makes no network requests of its own and never reads
// cookies, passwords or tokens.
(async () => {
  const TOOL = 'Quitar todos los «me gusta»';
  const LIMIT = 0;        // only the latest this many posts (0 = all)
  const DELAY = 1500;     // pause between unlikes, in milliseconds. X limits fast actions: don't go lower.

  if (!/^(x|twitter)\.com$/.test(location.hostname) || location.pathname !== '/i/history/likes') {
    alert('Abre primero tus «me gusta» (con tu sesión iniciada):\nhttps://x.com/i/history/likes');
    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(); },
    };
  })();
  const sleep = ms => new Promise(r => setTimeout(r, ms));
  const idOf = art => ((art.querySelector('a[href*="/status/"] time')?.closest('a')?.getAttribute('href') || '')
    .match(/\/status\/(\d+)/) || [])[1];
  const done = new Set();   // X keeps unliked posts on screen, so remember which ones are handled

  // 1. Ask (X loads likes as you scroll, so the total isn't known in advance)
  const scope = LIMIT ? `tus últimos ${LIMIT} «me gusta»` : 'todos tus «me gusta», de más nuevo a más antiguo';
  if (!await panel.ask(`¿Quitar ${scope}?\nNo se puede deshacer. Puedes pararlo cuando quieras.`, LIMIT ? `Quitar ${LIMIT}` : 'Quitar todos')) {
    panel.finish('Cancelado. No se ha cambiado nada.');
    return 0;
  }

  // 2. Unlike one by one, scrolling to load more
  let stop = false;
  panel.stoppable(() => { stop = true; });
  window.scrollTo(0, 0);
  await sleep(DELAY);
  let count = 0, idle = 0;
  while (!stop && idle < 4 && !(LIMIT && count >= LIMIT)) {
    const art = [...document.querySelectorAll('article[data-testid="tweet"]')]
      .find(a => a.querySelector('button[data-testid="unlike"]') && !done.has(idOf(a)));
    if (!art) {
      window.scrollBy(0, window.innerHeight * 0.8);   // load more
      await sleep(DELAY);
      idle++;
      continue;
    }
    idle = 0;
    done.add(idOf(art));
    art.scrollIntoView({ block: 'center' });
    art.querySelector('button[data-testid="unlike"]').click();
    count++;
    panel.text(`Quitando… ${count}${LIMIT ? ` de ${LIMIT}` : ''}`);
    await sleep(DELAY);
  }
  if (!count && !stop) {
    panel.finish('No tienes publicaciones con «me gusta».');
    return 0;
  }
  panel.finish(`${stop ? 'Parado' : 'Hecho'}: quitados ${many(count, 'publicación')}.\nRecarga la página para ver el resultado.`);
  return count;
})();

Marcador: arrastra el botón del medio a tu barra de marcadores, abre x.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 x.com cargando tu lista.
  • No toca tu sesión. No lee cookies, contraseñas, tokens ni el almacenamiento del navegador.
  • Solo funciona en x.com. En cualquier otra web se detiene antes de hacer nada.
  • Corto y legible. 101 líneas comentadas, sin minificar ni ofuscar.
  • Pregunta antes de cambiar nada. Un recuadro en la página muestra lo que ha encontrado y espera tu OK. Puedes pararlo cuando quieras.
  • El mismo código para todos. SHA-256 de la versión por defecto: 640aa53bd2c25b01…
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 x.com.

Ten en cuenta: esto no se puede deshacer en bloque. El script siempre muestra cuántos hay y pregunta antes de empezar. Deja la pestaña abierta hasta que el recuadro diga «Hecho».

¿Te ha funcionado?

Cómo usarlo

  1. Abre tus «me gusta» 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. Un recuadro te dice cuántos ha encontrado y espera tu confirmación antes de empezar. Puedes pulsar Parar cuando quieras.

A ritmo seguro

X limita las cuentas que hacen acciones demasiado rápido. El script espera 1,5 segundos entre cada «me gusta». Si tienes miles, hazlo por tandas con «Solo los últimos».

Preguntas frecuentes

¿X me bloqueará la cuenta?

X limita las cuentas que actúan demasiado rápido. El script espera 1,5 segundos entre cada «me gusta», como lo haría una persona. Para miles, ejecútalo por tandas con «Solo los últimos».

¿Puedo quitar solo los «me gusta» recientes?

Sí. Salen ordenados de más nuevo a más antiguo, así que «Solo los últimos 50» quita tus 50 más recientes y deja el resto.

¿Se avisa a alguien?

No. Quitar un «me gusta» no notifica a nadie.

Más herramientas gratis

Limpiar

Exportar y hacer copia