Skip to content

Instantly share code, notes, and snippets.

@karbassi
Last active June 15, 2025 21:25
Show Gist options
  • Save karbassi/d7499bf9da6407fde1ff45dcde582a12 to your computer and use it in GitHub Desktop.
Save karbassi/d7499bf9da6407fde1ff45dcde582a12 to your computer and use it in GitHub Desktop.
Archive all messages in Google Messages web app

Archive all messages in Google Messages web app

This code was something I quickly put together to archive over 5000 text messages in Google Messages. I have no idea if Google frowns on this or not, but it's basically the same as if a human sat there and archived all the messages by hand.

Tested and working as of Monday, November 4, 2019.

How to run

  1. Sign into https://messages.google.com/web/
  2. Open Chrome Developers console by going to View > Developer > JavaScript Console.
  3. Copy and paste the code below into console. It should automatically run.

Warning

Don't run any code before you know what it does. Review it and make sure it's safe. I accept no fault if something goes wrong. Google may change their code at anytime and this code may not work. I provide no support.

function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function archive() {
let menu = document.querySelectorAll('button.menu-button');
console.log(menu.length);
if(menu.length) {
menu[0].click();
document.querySelectorAll('button.mat-mdc-menu-item')[0].click()
await sleep(1000);
archive();
}
}
archive();
@ryantimjohn
Copy link

ryantimjohn commented Jun 15, 2025

Adding this script to scroll all the way down the nav panel in case you had the same problem I did where all convos didn't load. Can be run simultaneously with the above:

(function scrollToLoadAll() {
  const container = document.querySelector(
    'body > mw-app > mw-bootstrap > div > mw-g-ui-container > main > div > mw-main-container > div > mw-main-nav > mws-conversations-list > nav'
  );

  if (!container) {
    console.error("Scroll container not found.");
    return;
  }

  let lastScrollTop = -1;
  let triesWithoutChange = 0;
  const maxTries = 60; // 60 tries * 1000ms = ~1 minute

  const interval = setInterval(() => {
    container.scrollTop += 500;
    console.log("Scrolling…", container.scrollTop);

    if (container.scrollTop === lastScrollTop) {
      triesWithoutChange++;
      if (triesWithoutChange >= maxTries) {
        clearInterval(interval);
        console.log("Done scrolling: likely all conversations loaded.");
      }
    } else {
      lastScrollTop = container.scrollTop;
      triesWithoutChange = 0; // Reset if progress is made
    }
  }, 1000); // Wait 1 second between scrolls
})();

You might have to change that query selector up top. Use find that in the console by right clicking then inspect element.

@ryantimjohn
Copy link

ryantimjohn commented Jun 15, 2025

Okay, going to share what I ended up with, with some enhanced console logging (ty AI) and some stop functions. Also, if it hits something Google won't let it archive, it goes to the next record. Again, you can run these both at the same time and then just leave it running in the background. (I got a new phone, everything got unarchived and I had to churn through 2k messages 😢 )

to stop run either:

stopScrolling();
stopArchiving();

scroll:

// Global handle so you can stop scrolling manually
window.stopScrolling = () => {
  clearInterval(window.scrollIntervalId);
  console.log("⛔️ Auto-scroll manually stopped.");
};

(function scrollToLoadAll() {
  const container = document.querySelector(
    'body > mw-app > mw-bootstrap > div > mw-g-ui-container > main > div > mw-main-container > div > mw-main-nav > mws-conversations-list > nav'
  );

  if (!container) {
    console.error("❌ Scroll container not found.");
    return;
  }

  let lastScrollTop = -1;
  let triesWithoutChange = 0;
  const maxTries = 60; // 60 tries * 1000ms = ~1 minute

  window.scrollIntervalId = setInterval(() => {
    container.scrollTop += 500;
    console.log("↘️ Scrolling…", container.scrollTop);

    if (container.scrollTop === lastScrollTop) {
      triesWithoutChange++;
      if (triesWithoutChange >= maxTries) {
        clearInterval(window.scrollIntervalId);
        console.log("✅ Done: All conversations likely loaded.");
      }
    } else {
      lastScrollTop = container.scrollTop;
      triesWithoutChange = 0;
    }
  }, 1000);
})();

archive:

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// Global state
let isArchiving = true;
let currentIndex = 0;

window.stopArchiving = () => {
  isArchiving = false;
  console.log("⛔️ Archiving manually stopped.");
};

async function archive() {
  const menuButtons = document.querySelectorAll('button.menu-button');

  if (!isArchiving) {
    console.log("🛑 Archiving stopped.");
    return;
  }

  if (currentIndex >= menuButtons.length) {
    console.log("🎉 Reached the end of visible conversations.");
    return;
  }

  const currentButton = menuButtons[currentIndex];
  console.log(`📦 Trying to archive item ${currentIndex + 1} of ${menuButtons.length}`);

  try {
    currentButton.click();
    await sleep(300);

    const archiveButtons = document.querySelectorAll('button.mat-mdc-menu-item');
    if (!archiveButtons.length) {
      console.warn("⚠️ Archive button not found. Retrying same item.");
      return archive();
    }

    archiveButtons[0].click();
    await sleep(1000);

    const overlay = document.querySelector('div.cdk-overlay-container');
    const error = overlay?.innerText.includes("Could not archive conversation");

    if (error) {
      console.error("❌ Archive failed for this thread. Skipping to next.");
      currentIndex++; // Increment only on failure
    } else {
      console.log("✅ Archived successfully.");
      // Do NOT increment; conversation list has shifted up
    }

    await sleep(500);
    archive();
  } catch (err) {
    console.error("💥 Unexpected error:", err);
    // Don't increment — retry this item
    await sleep(1000);
    archive();
  }
}

// Start
archive();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment