Created
August 30, 2025 20:20
-
-
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…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (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