How I Built a Rolling Collector to Grab X Threads for AI

By Joel Dare ⟡ Written December 11, 2025

Rolling Collector is a JavaScript bookmarklet designed to capture text from “infinite scroll” websites (like X/Twitter) that use DOM virtualization. Unlike standard scrapers that only see what is currently on the screen, Rolling Collector runs in the background while you scroll, grabbing every post before the browser unloads it from memory. It solves the problem of “missing text” when trying to copy long threads on mobile devices.

Installation

  1. Create a Bookmark: Open your browser (Chrome or Safari) and bookmark any page.
  2. Edit the Bookmark: Go to your bookmarks list and edit the new bookmark.
  3. Rename: Name it Rolling Collector.
  4. Paste Code: Delete the URL and paste the JavaScript code below into the address field.

Usage

  1. Navigate: Go to the start of the thread or feed you want to capture.
  2. Activate: Tap the address bar and search for “Rolling Collector,” then tap the bookmark to run it.
  3. Scroll: A counter button will appear in the bottom right corner. Slowly scroll down the page. Watch the counter increment as it “catches” new content.
  4. Export: When you reach the bottom, tap the “Tweets (Tap to Finish)” button.
  5. Copy: A text box will appear with the entire captured thread selected. Tap “Copy” and paste it wherever you need.

The Code

javascript:(function(){
  /* Initialize the collection bucket */
  if(window.collectingInterval) return; /* Prevent double-run */
  let seenTweets = new Set();
  
  /* Create the floating counter button */
  const btn = document.createElement('button');
  btn.innerText = '0 Tweets (Tap to Copy)';
  btn.style.cssText = 'position:fixed; bottom:20px; right:20px; z-index:999999; padding:15px; background:blue; color:white; border-radius:30px; border:none; box-shadow:0 4px 12px rgba(0,0,0,0.3); font-weight:bold; font-family:sans-serif;';
  document.body.appendChild(btn);

  /* The Scanner Function */
  const scan = () => {
    const nodes = document.querySelectorAll('[data-testid=\"tweetText\"]');
    nodes.forEach(node => {
        /* Clean text to ensure key uniqueness */
        const text = node.innerText.trim();
        if(text.length > 0) seenTweets.add(text);
    });
    btn.innerText = `${seenTweets.size} Tweets (Tap to Finish)`;
  };

  /* Run scanner every 500ms while you scroll */
  window.collectingInterval = setInterval(scan, 500);

  /* Finish & Export */
  btn.onclick = () => {
    clearInterval(window.collectingInterval);
    window.collectingInterval = null;
    
    /* Join all unique tweets */
    const fullText = Array.from(seenTweets).join('\\n\\n---\\n\\n');
    
    /* Overlay for copying */
    const overlay = document.createElement('textarea');
    overlay.value = fullText;
    overlay.style.cssText = 'position:fixed; top:0; left:0; width:100%; height:100%; z-index:1000000; background:#fff; color:#000; font-size:16px; padding:20px; box-sizing:border-box;';
    document.body.appendChild(overlay);
    
    /* Clean up button */
    btn.remove();
    
    /* Focus and help user copy */
    overlay.focus();
    overlay.select();
    overlay.setSelectionRange(0, 99999);
    alert('Captured ' + seenTweets.size + ' tweets! Tap Copy.');
  };
})();

Build your next site in pure HTML and CSS

Want to build your next site in pure HTML and CSS? Join the free Five-Day Neat Starter Email Course and build a lean, production-ready page before Friday.

Email Me the Crash Course


JoelDare.com © Dare Companies Dotcom LLC

Terms - Privacy