-
-
Save virgiliu/eefbadef4de9d2ecb2e01020ae471892 to your computer and use it in GitHub Desktop.
| // Run this in the content download page and it will trigger download for everything | |
| var sleep = (milliseconds) => { | |
| return new Promise(resolve => setTimeout(resolve, milliseconds)) | |
| } | |
| var waitTime = 1500; //ms | |
| var x = $( "button:contains('Download')" ); | |
| for(var i = 0; i < x.length ; i++) | |
| { | |
| (function(idx) { | |
| // Wait needed because browser blocks network calls if you make too many too fast | |
| sleep(i * waitTime).then(() => { | |
| x[idx].click(); | |
| }); | |
| })(i) | |
| } | |
Can anyone please help me to download from the beginning and how to code it please.. that'd be great help thankyou
Hi all! I've update https://github.com/obsessedcake/gumroad-utils. If anyone interested, take a look ๐
I've tried using the library but can't download any files via the URL I'm getting an error

What is this error and is there any way to fix it
@itswzyss Good idea. Went through little tests with my file. Once a number of links attained, Gumroad decide to cut the flow and stop the connexion. So, I decided to reduce the file in multiple files, once per artist (even if you have multiple purchases). ๐คฃ One thing more. Content creator can use external links to host their files instead of gumroad. I alert of that in the files & console.
let promises = await Promise.all(Array.from(document.querySelectorAll("article a.stretched-link")) // Get promises with purchases download links. .map((link) => { return link.href }) .map((link) => { return fetch(link) // Get link from purchase link. .then(res => res.text()) .then(text => { let parser = new DOMParser(); // Create DOMContent from fetch content with download links. let doc = parser.parseFromString(text, "text/html"); var script = doc.querySelector("script[data-component-name]");// Get script in which the download content JS is. if(JSON.parse(script.innerText).content.content_items.length === 0) console.log(JSON.parse(script.innerText).creator.name + " use an external hosting service. Please watch their files to get the purchased download links"); // Alert in console for external hosting services. return { artist: JSON.parse(script.innerText).creator.name, links: (JSON.parse(script.innerText).content.content_items.length > 0 ? JSON.parse(script.innerText).content.content_items.map((item) => { return "https://app.gumroad.com" + item.download_url }) : ["external link in following page : " + link]) };// Return both the artist and the associated download URLs (if content is in external website from gumroad, the page will be alerted). }); })); let timer = 0; // Timer to delay the download (to avoid download throttle). promises // Need the promises to be resolved from here. .reduce((acc, d) => { const found = acc.find(a => a.artist === d.artist); const value = d.links.flat(Infinity); if (!found) acc.push({ artist: d.artist, links: [value] }) else found.links.push(value); return acc; }, [])// Regroup links per artist. .sort(function (a, b) { return a.artist.localeCompare(b.artist); })// Sort artist per name. .forEach((data) => { setTimeout(function () { var blob = new Blob([data.links.flat(Infinity).join("\n")], { type: "text/plain;charset=utf-8" }); var url = window.URL || window.webkitURL; var link = url.createObjectURL(blob);// Creation of download link. var a = document.createElement("a"); a.download = "downloads_" + data.artist + "_gumroad.txt"; document.body.appendChild(a); a.href = link;// Creation of the download button. a.click(); // Click to begin download. a.remove(); // Remove the download button. }, timer += 1500);// Delay to avoid download throttle. });// From this, download ```
Small problem found, the element selector for the JSON wasn't correct anymore. Here is an updated version:
let promises = await Promise.all(Array.from(document.querySelectorAll("article a.stretched-link")) // Get promises with purchases download links.
.map((link) => { return link.href })
.map((link) => {
return fetch(link) // Get link from purchase link.
.then(res => res.text())
.then(text => {
let parser = new DOMParser(); // Create DOMContent from fetch content with download links.
let doc = parser.parseFromString(text, "text/html");
var script = doc.querySelector("script[data-component-name=\"DownloadPageWithContent\"]");// Get script in which the download content JS is.
if(JSON.parse(script.innerText).content.content_items.length === 0)
console.log(JSON.parse(script.innerText).creator.name + " use an external hosting service. Please watch their files to get the purchased download links"); // Alert in console for external hosting services.
return {
artist: JSON.parse(script.innerText).creator.name,
links: (JSON.parse(script.innerText).content.content_items.length > 0 ?
JSON.parse(script.innerText).content.content_items.map((item) => { return "https://app.gumroad.com" + item.download_url }) :
["external link in following page : " + link])
};// Return both the artist and the associated download URLs (if content is in external website from gumroad, the page will be alerted).
});
}));
let timer = 0; // Timer to delay the download (to avoid download throttle).
promises // Need the promises to be resolved from here.
.reduce((acc, d) => {
const found = acc.find(a => a.artist === d.artist);
const value = d.links.flat(Infinity);
if (!found) acc.push({ artist: d.artist, links: [value] })
else found.links.push(value);
return acc;
}, [])// Regroup links per artist.
.sort(function (a, b) {
return a.artist.localeCompare(b.artist);
})// Sort artist per name.
.forEach((data) => {
setTimeout(function () {
var blob = new Blob([data.links.flat(Infinity).join("\n")], { type: "text/plain;charset=utf-8" });
var url = window.URL || window.webkitURL;
var link = url.createObjectURL(blob);// Creation of download link.
var a = document.createElement("a");
a.download = "downloads_" + data.artist + "_gumroad.txt";
document.body.appendChild(a);
a.href = link;// Creation of the download button.
a.click(); // Click to begin download.
a.remove(); // Remove the download button.
}, timer += 1500);// Delay to avoid download throttle.
});// From this, downloadhi sorry am I missing something? I've put the code in developer tools same with the download page, It just shows an error or does nothing apart from says undefined. Do I need to put the code somewhere else?
hi sorry am I missing something? I've put the code in developer tools same with the download page, It just shows an error or does nothing apart from says undefined. Do I need to put the code somewhere else?
Try replacing button:contains('Download') with a:contains('Download')
I had to modify the script for it to work. I'm using the "href" attribute, and simply adding http://gumroad.com in front of that variable. The previous script was using the "data-resource-id" which is empty / undefined.
Also I had some problems using console download managers to download the urls, since gumroad asks for confirmation before starting the file download. But I was able to use the Chrono Chrome extension. Just simply press the "new" button and paste in the list of URLs with each URL in a new line.
var x = $("a.button:contains('Download')");
var result = [];
for (var i = 0; i < x.length; i++) {
result.push(x[i].getAttribute("href"));
}
var currentUrl = window.location.href;
var newBaseUrl = currentUrl.replace("/d/", "/r/");
var newUrls = [];
result.forEach(function (resourceId) {
newUrls.push("https://gumroad.com" + resourceId);
});
var blob = new Blob([newUrls.join("\n")], { type: "text/plain" });
var a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = "urls.txt";
a.style.display = "none";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(a.href);
Something updated that worked for me in 02.2026.
Just copy & paste into your browser console while being on the Gurmoad downloads page
/**
* Gumroad Bulk Downloader
*
* A simple script to download all files from a Gumroad purchase page at once.
* Useful when you've purchased a bundle with many files and don't want to
* click each download link individually.
*
* Usage:
* 1. Open the Gumroad page with your purchased content
* 2. Open Developer Tools (F12 or right-click > Inspect)
* 3. Go to the "Console" tab
* 4. Paste this entire script and press Enter
* 5. Files will download with a delay between each to avoid rate limiting
*
* License: MIT
*/
(async function() {
'use strict';
// --- Configuration ---
const BASE_URL = 'https://app.gumroad.com';
const DELAY_SECONDS = 5; // Delay between downloads to avoid rate limiting
// --- Helper Functions ---
const sleep = (seconds) => new Promise(resolve => setTimeout(resolve, seconds * 1000));
const downloadFile = (url) => {
const link = document.createElement('a');
link.href = url;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
// --- Main Logic ---
console.log('%c๐ Gumroad Bulk Downloader', 'color: #4CAF50; font-size: 18px; font-weight: bold;');
console.log('โ'.repeat(50));
// Find all download links
const links = document.querySelectorAll('a[href*="/r/"][href*="product_files"]');
const seen = new Set();
const downloads = [];
links.forEach(link => {
const href = link.getAttribute('href');
if (href && href.includes('product_file_ids') && !seen.has(href)) {
seen.add(href);
// Try to get the filename
const container = link.closest('.embed') || link.closest('[role="treeitem"]') || link.parentElement;
const h4 = container?.querySelector('h4');
const fileName = h4?.textContent.trim() || `File ${downloads.length + 1}`;
downloads.push({ url: href, name: fileName });
}
});
// Report findings
console.log(`%c๐ Found ${downloads.length} files to download`, 'color: #2196F3; font-size: 14px;');
downloads.forEach((d, i) => console.log(` ${i + 1}. ${d.name}`));
if (downloads.length === 0) {
console.log('%cโ No download links found. Are you on a Gumroad purchase page?', 'color: #f44336;');
return;
}
console.log('โ'.repeat(50));
console.log(`%cโฑ๏ธ Starting downloads (${DELAY_SECONDS}s delay between each)...`, 'color: #FF9800;');
// Download each file
for (let i = 0; i < downloads.length; i++) {
const { url, name } = downloads[i];
const fullUrl = url.startsWith('http') ? url : BASE_URL + url;
console.log(`%c\n[${i + 1}/${downloads.length}] ${name}`, 'color: #4CAF50; font-weight: bold;');
downloadFile(fullUrl);
if (i < downloads.length - 1) {
console.log(` Waiting ${DELAY_SECONDS}s...`);
await sleep(DELAY_SECONDS);
}
}
// Done!
console.log('\n' + 'โ'.repeat(50));
console.log('%cโ
All downloads started!', 'color: #4CAF50; font-size: 16px; font-weight: bold;');
console.log('%c๐ Check your browser downloads folder.', 'color: #2196F3;');
})();
Something updated that worked for me in 02.2026.
Just copy & paste into your browser console while being on the Gurmoad downloads page
worked like a charm thanks!(08/03/2026)
I am a bit puzzled how there is no bulk zip download available on gumroad for each Bundle of purchased Files
@obsessedcake Thanks for building and sharing that. For me the original script was a one-time thing which I made public by mistake, but since people started talking I decided to leave it up even though I don't have the time to maintain it ๐