Skip to content

Instantly share code, notes, and snippets.

@itswzyss
Last active May 14, 2024 10:42
Show Gist options
  • Save itswzyss/f92a72a8de705261ce46329fbe57d8c9 to your computer and use it in GitHub Desktop.
Save itswzyss/f92a72a8de705261ce46329fbe57d8c9 to your computer and use it in GitHub Desktop.
Bulk Download Gumroad Library
// In light of the TOS change at Gumroad, I've modified a script by @Fhurai that will categorize all the download links with their
// original asset page. In order to use this, navigate to https://app.gumroad.com/library and open your DevTools. Then paste the
// following code into the Console. See more info at https://blog.wzyss.dev/easily-archive-your-gumroad-library/
async function fetchUrls(link) {
// Fetch and process URLs from the given link
return fetch(link)
.then(res => res.text())
.then(text => {
let parser = new DOMParser();
let doc = parser.parseFromString(text, "text/html");
var script = doc.querySelector("script[data-component-name]");
var links = Array.from(JSON.parse(script.innerText).content.content_items).map((item) => { return "https://app.gumroad.com" + item.download_url });
// Return both the original link and the associated download URLs
return {link, downloads: links};
});
}
Promise.all(Array.from(document.querySelectorAll("article a"))
.filter((link) => link.href.includes("/d/"))
.map((a) => a.href)
.map((link) => {
// Fetch URLs and maintain their association with the original link
return fetchUrls(link);
}))
.then(function(results) {
// Process results to group downloads by their originating link
let groupedDownloads = results.reduce((acc, {link, downloads}) => {
acc[link] = downloads;
return acc;
}, {});
// Prepare data for export
let exportData = Object.entries(groupedDownloads).map(([page, downloads]) => {
return `${page}\n${downloads.join("\n")}`;
}).join("\n\n");
// Create a blob and download it
var blob = new Blob([exportData], {type: "text/plain;charset=utf-8"});
var url = window.URL || window.webkitURL;
var downloadLink = url.createObjectURL(blob);
var a = document.createElement("a");
a.download = "categorized_downloads_gumroad.txt";
document.body.appendChild(a);
a.href = downloadLink;
a.click();
a.remove();
});
@itswzyss
Copy link
Author

itswzyss commented Mar 17, 2024

It's important to note that this will generate extra links at the top of each "category" that helps you identify what assets belonged to what Gumroad post.

If you don't want this and instead just want to download everything one shot and you don't care how it ends up, use the following:

async function fetchUrls(link) {
    // Fetch and process URLs from the given link
    return fetch(link)
        .then(res => res.text())
        .then(text => {
            let parser = new DOMParser();
            let doc = parser.parseFromString(text, "text/html");
            var script = doc.querySelector("script[data-component-name]");
            // Extract just the download URLs
            var links = Array.from(JSON.parse(script.innerText).content.content_items)
                             .map(item => "https://app.gumroad.com" + item.download_url);
            return links;
        });
}

Promise.all(Array.from(document.querySelectorAll("article a"))
    .filter(link => link.href.includes("/d/"))
    .map(a => a.href)
    .map(fetchUrls))
    .then(function(allUrls) {
        // Flatten the array of arrays and prepare data for export
        let flatUrls = allUrls.flat();
        let exportData = flatUrls.join("\n");

        // Create a blob and download it
        var blob = new Blob([exportData], {type: "text/plain;charset=utf-8"});
        var url = window.URL || window.webkitURL;
        var downloadLink = url.createObjectURL(blob);
        var a = document.createElement("a");
        a.download = "downloads_gumroad.txt";
        document.body.appendChild(a);
        a.href = downloadLink;
        a.click();
        a.remove();
    });

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