Skip to content

Instantly share code, notes, and snippets.

@wongcyrus
Last active December 22, 2024 03:28
Show Gist options
  • Select an option

  • Save wongcyrus/aff2eed5f7ef7db6418b0c3fc621e3a1 to your computer and use it in GitHub Desktop.

Select an option

Save wongcyrus/aff2eed5f7ef7db6418b0c3fc621e3a1 to your computer and use it in GitHub Desktop.
Export YouTube playlist to CSV with Google Chrome Developer Console. Open the playlist page, run this script to export playlist to CSV with title, url, and video length.
var ytp = document.querySelectorAll("ytd-playlist-video-list-renderer > #contents > ytd-playlist-video-renderer");
var time = 0;
function convertS(sec) {
var hrs = Math.floor(sec / 3600);
var min = Math.floor((sec - (hrs * 3600)) / 60);
var seconds = sec - (hrs * 3600) - (min * 60);
seconds = Math.round(seconds * 100) / 100
var result = (hrs < 10 ? "0" + hrs : hrs) + ':';
result += (min < 10 ? "0" + min : min) + ":";
result += (seconds < 10 ? "0" + seconds : seconds);
return result;
}
var videos = [];
for (var i = 0; i < ytp.length; i++) {
var a = ytp[i].getElementsByTagName('ytd-thumbnail-overlay-time-status-renderer')[0].innerText;
var tx = a.split(':');
var title = ytp[i].getElementsByTagName("a")[1].title;
var url = ytp[i].getElementsByTagName("a")[1].href;
if(url.includes("&t="))
url = url.split("&t=")[0];
if (tx.length < 3) {
videoLength = Number(tx[0]) * 60 + Number(tx[1]);
time = time + Number(tx[0]) * 60 + Number(tx[1]);
} else if (tx.length = 3) {
time = time + Number(tx[0]) * 60 * 60 + Number(tx[1]) * 60 + Number(tx[2]);
videoLength = Number(tx[0]) * 60 * 60 + Number(tx[1]) * 60 + Number(tx[2]);
}
videos.push({ title, videoLength: convertS(videoLength), seconds: videoLength, url });
}
function download_csv_file() {
//define the heading for each row of the data
var csv = 'Title,Url,Length,Seconds\n';
//merge the data with CSV
videos.forEach(function (row) {
csv += "\""+row.title + "\"," + row.url + "," + row.videoLength + "," + row.seconds;
csv += "\n";
});
//display the created CSV data on the web browser
document.write(csv);
var hiddenElement = document.createElement('a');
hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv);
hiddenElement.target = '_blank';
//provide the name for the CSV file to be downloaded
hiddenElement.download = 'YoutubePlayList.csv';
hiddenElement.click();
}
var ytpT = convertS(time)
var show = 'YouTube Playlist \n --------------- \n Total Videos : ' + ytp.length + '\n Total Duration : ' + ytpT + '\n Avg. Duration : ' + convertS(time / ytp.length);
// alert(show);
// console.log(videos);
download_csv_file();
@mskogly

mskogly commented Sep 29, 2023

Copy link
Copy Markdown

Might have found a bug. It stops if it encounters a # in the title of one of the videos.
Besides that: Thanks for a super useful script.

Pershaps something like this?

var ytp = document.querySelectorAll("ytd-playlist-video-list-renderer > #contents > ytd-playlist-video-renderer");
var time = 0;

function convertS(sec) {
    var hrs = Math.floor(sec / 3600);
    var min = Math.floor((sec - (hrs * 3600)) / 60);
    var seconds = sec - (hrs * 3600) - (min * 60);
    seconds = Math.round(seconds * 100) / 100;

    var result = (hrs < 10 ? "0" + hrs : hrs) + ":";
    result += (min < 10 ? "0" + min : min) + ":";
    result += (seconds < 10 ? "0" + seconds : seconds);
    return result;
}

var videos = [];
for (var i = 0; i < ytp.length; i++) {
    var a = ytp[i].getElementsByTagName('ytd-thumbnail-overlay-time-status-renderer')[0].innerText;
    var tx = a.split(':');
    var title = ytp[i].getElementsByTagName("a")[1].title;

    // Replace special characters in the title with safe characters (e.g., replace "#" with "-")
    title = title.replace(/#/g, '-');

    var url = ytp[i].getElementsByTagName("a")[1].href;
    if (url.includes("&t="))
        url = url.split("&t=")[0];
    if (tx.length < 3) {
        videoLength = Number(tx[0]) * 60 + Number(tx[1]);
        time = time + Number(tx[0]) * 60 + Number(tx[1]);
    } else if (tx.length = 3) {
        time = time + Number(tx[0]) * 60 * 60 + Number(tx[1]) * 60 + Number(tx[2]);
        videoLength = Number(tx[0]) * 60 * 60 + Number(tx[1]) * 60 + Number(tx[2]);
    }

    videos.push({ title, videoLength: convertS(videoLength), seconds: videoLength, url });
}

function download_csv_file() {
    // Define the heading for each row of the data
    var csv = 'Title,Url,Length,Seconds\n';

    // Merge the data with CSV
    videos.forEach(function (row) {
        csv += "\"" + row.title + "\"," + row.url + "," + row.videoLength + "," + row.seconds;
        csv += "\n";
    });

    // Display the created CSV data on the web browser
    document.write(csv);

    var hiddenElement = document.createElement('a');
    hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv);
    hiddenElement.target = '_blank';

    // Provide the name for the CSV file to be downloaded
    hiddenElement.download = 'YoutubePlayList.csv';
    hiddenElement.click();
}

var ytpT = convertS(time);
var show = 'YouTube Playlist \n --------------- \n Total Videos : ' + ytp.length + '\n Total Duration : ' + ytpT + '\n Avg. Duration  : ' + convertS(time / ytp.length);
download_csv_file();

@wongcyrus

Copy link
Copy Markdown
Author

Might have found a bug. It stops if it encounters a # in the title of one of the videos. Besides that: Thanks for a super useful script.

Pershaps something like this?

var ytp = document.querySelectorAll("ytd-playlist-video-list-renderer > #contents > ytd-playlist-video-renderer");
var time = 0;

function convertS(sec) {
    var hrs = Math.floor(sec / 3600);
    var min = Math.floor((sec - (hrs * 3600)) / 60);
    var seconds = sec - (hrs * 3600) - (min * 60);
    seconds = Math.round(seconds * 100) / 100;

    var result = (hrs < 10 ? "0" + hrs : hrs) + ":";
    result += (min < 10 ? "0" + min : min) + ":";
    result += (seconds < 10 ? "0" + seconds : seconds);
    return result;
}

var videos = [];
for (var i = 0; i < ytp.length; i++) {
    var a = ytp[i].getElementsByTagName('ytd-thumbnail-overlay-time-status-renderer')[0].innerText;
    var tx = a.split(':');
    var title = ytp[i].getElementsByTagName("a")[1].title;

    // Replace special characters in the title with safe characters (e.g., replace "#" with "-")
    title = title.replace(/#/g, '-');

    var url = ytp[i].getElementsByTagName("a")[1].href;
    if (url.includes("&t="))
        url = url.split("&t=")[0];
    if (tx.length < 3) {
        videoLength = Number(tx[0]) * 60 + Number(tx[1]);
        time = time + Number(tx[0]) * 60 + Number(tx[1]);
    } else if (tx.length = 3) {
        time = time + Number(tx[0]) * 60 * 60 + Number(tx[1]) * 60 + Number(tx[2]);
        videoLength = Number(tx[0]) * 60 * 60 + Number(tx[1]) * 60 + Number(tx[2]);
    }

    videos.push({ title, videoLength: convertS(videoLength), seconds: videoLength, url });
}

function download_csv_file() {
    // Define the heading for each row of the data
    var csv = 'Title,Url,Length,Seconds\n';

    // Merge the data with CSV
    videos.forEach(function (row) {
        csv += "\"" + row.title + "\"," + row.url + "," + row.videoLength + "," + row.seconds;
        csv += "\n";
    });

    // Display the created CSV data on the web browser
    document.write(csv);

    var hiddenElement = document.createElement('a');
    hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv);
    hiddenElement.target = '_blank';

    // Provide the name for the CSV file to be downloaded
    hiddenElement.download = 'YoutubePlayList.csv';
    hiddenElement.click();
}

var ytpT = convertS(time);
var show = 'YouTube Playlist \n --------------- \n Total Videos : ' + ytp.length + '\n Total Duration : ' + ytpT + '\n Avg. Duration  : ' + convertS(time / ytp.length);
download_csv_file();

Thank you for your code and it is good!

@SIG-Labo

Copy link
Copy Markdown

Might have found a bug. It stops if it encounters a # in the title of one of the videos. Besides that: Thanks for a super useful script.

Pershaps something like this?

var ytp = document.querySelectorAll("ytd-playlist-video-list-renderer > #contents > ytd-playlist-video-renderer");
var time = 0;

function convertS(sec) {
    var hrs = Math.floor(sec / 3600);
    var min = Math.floor((sec - (hrs * 3600)) / 60);
    var seconds = sec - (hrs * 3600) - (min * 60);
    seconds = Math.round(seconds * 100) / 100;

    var result = (hrs < 10 ? "0" + hrs : hrs) + ":";
    result += (min < 10 ? "0" + min : min) + ":";
    result += (seconds < 10 ? "0" + seconds : seconds);
    return result;
}

var videos = [];
for (var i = 0; i < ytp.length; i++) {
    var a = ytp[i].getElementsByTagName('ytd-thumbnail-overlay-time-status-renderer')[0].innerText;
    var tx = a.split(':');
    var title = ytp[i].getElementsByTagName("a")[1].title;

    // Replace special characters in the title with safe characters (e.g., replace "#" with "-")
    title = title.replace(/#/g, '-');

    var url = ytp[i].getElementsByTagName("a")[1].href;
    if (url.includes("&t="))
        url = url.split("&t=")[0];
    if (tx.length < 3) {
        videoLength = Number(tx[0]) * 60 + Number(tx[1]);
        time = time + Number(tx[0]) * 60 + Number(tx[1]);
    } else if (tx.length = 3) {
        time = time + Number(tx[0]) * 60 * 60 + Number(tx[1]) * 60 + Number(tx[2]);
        videoLength = Number(tx[0]) * 60 * 60 + Number(tx[1]) * 60 + Number(tx[2]);
    }

    videos.push({ title, videoLength: convertS(videoLength), seconds: videoLength, url });
}

function download_csv_file() {
    // Define the heading for each row of the data
    var csv = 'Title,Url,Length,Seconds\n';

    // Merge the data with CSV
    videos.forEach(function (row) {
        csv += "\"" + row.title + "\"," + row.url + "," + row.videoLength + "," + row.seconds;
        csv += "\n";
    });

    // Display the created CSV data on the web browser
    document.write(csv);

    var hiddenElement = document.createElement('a');
    hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv);
    hiddenElement.target = '_blank';

    // Provide the name for the CSV file to be downloaded
    hiddenElement.download = 'YoutubePlayList.csv';
    hiddenElement.click();
}

var ytpT = convertS(time);
var show = 'YouTube Playlist \n --------------- \n Total Videos : ' + ytp.length + '\n Total Duration : ' + ytpT + '\n Avg. Duration  : ' + convertS(time / ytp.length);
download_csv_file();

"Human Contact. The final frontier…" - Jeff Albertson , comic book guy
it seems this works better thanks

@rblaza

rblaza commented Mar 11, 2024

Copy link
Copy Markdown

Hello,
from your original script is it possible to upgrade it to export all details playlists from a youtube channel in one file ? by adding a column for the playliist name and export all details for each playlis from one channel.
It could be great! thanks for your help.

@ThatFella1

Copy link
Copy Markdown

Hello. This is excellent! Is it possible to also to add the Channel Name in the export? Thank you!

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