Skip to content

Instantly share code, notes, and snippets.

@Subham-Maity
Created November 8, 2024 02:39
Show Gist options
  • Select an option

  • Save Subham-Maity/e6f499003c66d9329a2d0d8b34b5015a to your computer and use it in GitHub Desktop.

Select an option

Save Subham-Maity/e6f499003c66d9329a2d0d8b34b5015a to your computer and use it in GitHub Desktop.
Copy All the Titles and URLs From YouTube Channel || Copy All the Titles and URLs From YouTube Playlist

Steps to Extract All Video Links on a Page

  1. Open Console:

    • Right-click on the page, choose Inspect, then go to the Console tab.
  2. Auto-Scroll to Load All Videos:

    • To load all video elements on the page, paste this code in the console and press Enter:
      var scroll = setInterval(function() { window.scrollBy(0, 1000); }, 1000);
    • This will scroll the page down by 1000 pixels every second.
  3. Optional: Manual Scrolling

    • For better results, you can also scroll manually to make sure all videos are fully loaded.
  4. Stop Scrolling:

    • When you’ve reached the end of the page and all content is loaded, stop the scrolling by pasting this in the console:
      clearInterval(scroll);
  5. Extract Video Titles and Links:

    • Scroll to the top of the page, then paste this code in the console to get a list of all video titles and URLs:
      console.clear();
      const urls = document.querySelectorAll('a#video-title');
      urls.forEach(video => console.log(`${video.title}\t${video.href}`));
  6. Review Output:

    • The console will display each video’s title and link in a tab-separated format just copy those.
@infinitehoax

Copy link
Copy Markdown

What about shorts?

@sarasohail398-source

Copy link
Copy Markdown

Same here, I was wondering abt tht as well

@sarasohail398-source

Copy link
Copy Markdown

Not working..

@marluan

marluan commented Sep 16, 2025 •

Copy link
Copy Markdown

here a working script with the time of each video:

const url = document.querySelectorAll("ytd-rich-item-renderer");
url.forEach(video => {
    const videoLink = video.querySelector('a#video-title-link');
    if (videoLink) { // Check if videoLink is not null
        console.log(`${videoLink.title}\t${videoLink.href}\t${video.querySelector('div#overlays > ytd-thumbnail-overlay-time-status-renderer > div.thumbnail-overlay-badge-shape.style-scope.ytd-thumbnail-overlay-time-status-renderer > badge-shape > div').textContent}`);
    }
});

@igarcez

igarcez commented Jan 9, 2026

Copy link
Copy Markdown

here is a version that prints a table on the console

const urls = document.querySelectorAll('a#video-title-link');
const data = [];
for (const video of urls) {
  data.push([video.title, video.href]);
}
console.table(data);

@abbyshark-art

Copy link
Copy Markdown

Sorry if it asking for too much but possible to have the View Count too? Thats an important metric.

@Enjoyfree25

Copy link
Copy Markdown

Fully Automatic YouTube Video Extractor

(async function() {
    const config = { scrollDelay: 400, scrollAmount: 1000, maxStalls: 6 };
    
    console.clear();
    console.log('πŸš€ YouTube Video Extractor - Starting...');
    console.log('⏳ Auto-scrolling to load all videos...\n');
    
    // Auto-scroll until no new content loads
    let lastHeight = 0, stallCount = 0, totalScrolls = 0;
    while (stallCount < config.maxStalls) {
        window.scrollBy(0, config.scrollAmount);
        await new Promise(r => setTimeout(r, config.scrollDelay));
        totalScrolls++;
        
        const newHeight = document.documentElement.scrollHeight;
        stallCount = (newHeight === lastHeight) ? stallCount + 1 : 0;
        lastHeight = newHeight;
        
        if (totalScrolls % 20 === 0) console.log(`πŸ“œ Still scrolling... (${totalScrolls} scrolls)`);
    }
    
    window.scrollTo(0, 0);
    console.log('βœ… Scrolling complete!\n');
    
    // Extract all videos
    const videos = new Map();
    
    // Channel videos (regular)
    document.querySelectorAll('ytd-rich-item-renderer').forEach(item => {
        const link = item.querySelector('a#video-title-link');
        const duration = item.querySelector('span.ytd-thumbnail-overlay-time-status-renderer');
        const meta = item.querySelectorAll('#metadata-line span.inline-metadata-item');
        if (link && link.href) {
            videos.set(link.href, {
                title: link.title || link.textContent.trim(),
                url: link.href,
                duration: duration?.textContent?.trim() || 'N/A',
                views: meta[0]?.textContent?.trim() || 'N/A',
                date: meta[1]?.textContent?.trim() || 'N/A'
            });
        }
    });
    
    // Playlist videos
    document.querySelectorAll('ytd-playlist-video-renderer').forEach(item => {
        const link = item.querySelector('a#video-title');
        const duration = item.querySelector('span.ytd-thumbnail-overlay-time-status-renderer');
        const index = item.querySelector('#index');
        if (link && link.href) {
            const cleanUrl = link.href.split('&list=')[0].split('&index=')[0];
            videos.set(cleanUrl, {
                title: link.title || link.textContent.trim(),
                url: cleanUrl,
                duration: duration?.textContent?.trim() || 'N/A',
                views: 'N/A',
                index: index?.textContent?.trim() || 'N/A'
            });
        }
    });
    
    // Shorts
    document.querySelectorAll('ytd-rich-item-renderer ytd-rich-grid-slim-media, ytd-reel-item-renderer').forEach(item => {
        const link = item.querySelector('a#thumbnail, a');
        const title = item.querySelector('#video-title, h3');
        const views = item.querySelector('.ytd-rich-grid-slim-media span, #metadata span');
        if (link?.href?.includes('/shorts/')) {
            videos.set(link.href, {
                title: title?.textContent?.trim() || 'Short Video',
                url: link.href,
                duration: 'SHORT',
                views: views?.textContent?.trim() || 'N/A'
            });
        }
    });
    
    // Fallback for other layouts
    if (videos.size === 0) {
        document.querySelectorAll('a#video-title, a#video-title-link').forEach(link => {
            if (link?.href) {
                videos.set(link.href, {
                    title: link.title || link.textContent.trim(),
                    url: link.href,
                    duration: 'N/A',
                    views: 'N/A'
                });
            }
        });
    }
    
    const results = [...videos.values()];
    
    // Create output
    const tsvOutput = 'Title\tURL\tDuration\tViews\n' + 
        results.map(v => `${v.title}\t${v.url}\t${v.duration}\t${v.views}`).join('\n');
    
    // Copy to clipboard
    try {
        await navigator.clipboard.writeText(tsvOutput);
        console.log('πŸ“‹ βœ… COPIED TO CLIPBOARD!\n');
    } catch(e) {
        console.log('⚠️ Clipboard access denied. Copy from below:\n');
    }
    
    // Display results
    console.log(`🎬 Found ${results.length} videos!\n`);
    console.table(results.map(({title, url, duration, views}) => ({Title: title.substring(0,50), Duration: duration, Views: views, URL: url})));
    
    console.log('\nπŸ“ RAW OUTPUT (Tab-Separated):\n');
    console.log(tsvOutput);
    
    return results;
})();

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