Skip to content

Instantly share code, notes, and snippets.

@AKASGaming
Created August 30, 2025 20:20
Show Gist options
  • Select an option

  • Save AKASGaming/ab52b96231d3662e25d20321a586d4db to your computer and use it in GitHub Desktop.

Select an option

Save AKASGaming/ab52b96231d3662e25d20321a586d4db to your computer and use it in GitHub Desktop.
This script auto-scrolls through Plex > Your Movie Library > Table View, scrapes all the movie titles, and saves them as a clean list. Works by simulating scrolling until the end of the list is reached. Captures each row as it becomes visible (so even if Plex unmounts off-screen items, you still keep them). Outputs results to the console and cop…
(async () => {
// 🔧 EDIT these if needed
const SCROLL_CONTAINER_SELECTOR = ".DirectoryListPageContent-pageContentScroller-O3oHlt.PageContent-pageContentScroller-dvaH3C.Scroller-scroller-S6_dko.Scroller-omni-bAqZII";
const ROW_SELECTOR = ".MetadataTableRow-title-CrTfGf a, a.MetadataTableRow-title-CrTfGf";
// --- helpers ---
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
const isVisible = (el) => {
if (!el) return false;
const rects = el.getClientRects();
if (rects.length === 0) return false;
const cs = window.getComputedStyle(el);
return cs && cs.display !== "none" && cs.visibility !== "hidden" && cs.opacity !== "0";
};
const container =
document.querySelector(SCROLL_CONTAINER_SELECTOR) ||
document.scrollingElement ||
document.documentElement;
const scrollOnce = () => {
if (container === document.scrollingElement || container === document.documentElement || container === document.body) {
window.scrollBy(0, window.innerHeight);
} else {
container.scrollBy(0, container.clientHeight);
}
};
const seen = new Set();
const collectNow = () => {
document.querySelectorAll(ROW_SELECTOR).forEach(el => {
if (!el) return;
if (isVisible(el)) {
const t = (el.textContent || "").trim();
if (t) seen.add(t);
}
});
};
// --- main auto-scroll loop ---
let lastHeight = container.scrollHeight || document.body.scrollHeight;
let idleCycles = 0;
const MAX_IDLE_CYCLES = 60; // stop after this many cycles with no growth
const MAX_TOTAL_CYCLES = 500; // safety cap
const PAUSE_MS = 350;
console.log("▶️ Starting auto-scroll & scrape…");
collectNow();
for (let cycle = 0; cycle < MAX_TOTAL_CYCLES; cycle++) {
scrollOnce();
await sleep(PAUSE_MS);
collectNow();
const newHeight = container.scrollHeight || document.body.scrollHeight;
if (newHeight <= lastHeight + 2) {
idleCycles++;
} else {
idleCycles = 0;
lastHeight = newHeight;
}
if (cycle % 5 === 0) {
console.log(`Cycle ${cycle} • items: ${seen.size} • height: ${newHeight} • idle: ${idleCycles}/${MAX_IDLE_CYCLES}`);
}
if (idleCycles >= MAX_IDLE_CYCLES) break;
}
collectNow();
const values = Array.from(seen);
console.clear();
console.table(values);
console.log("✅ Total grabbed:", values.length);
try {
await navigator.clipboard.writeText(values.join("\n"));
console.log("📋 Copied to clipboard (newline-separated).");
} catch (e) {
console.warn("⚠️ Could not copy to clipboard. Copy manually from console.");
}
return values;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment