Pixeldrain DL Bypass

Adds direct-download buttons and links for Pixeldrain files using an alternate proxy — inspired by 'Pixeldrain Download Bypass' by hhoneeyy and MegaLime0

Fra 05.10.2025. Se den seneste versjonen.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Pixeldrain DL Bypass
// @namespace    https://greasyfork.org/users/821661
// @version      1.2
// @description  Adds direct-download buttons and links for Pixeldrain files using an alternate proxy — inspired by 'Pixeldrain Download Bypass' by hhoneeyy and MegaLime0
// @author       hdyzen
// @match        https://pixeldrain.com/*
// @match        https://pixeldrain.net/*
// @icon         https://www.google.com/s2/favicons?domain=pixeldrain.com/&sz=64
// @grant        GM_xmlhttpRequest
// @grant        GM_registerMenuCommand
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @license      GPL-3.0-only
// ==/UserScript==

const PDLB_CONFIG = {
    defaultBypassURL: "pd.1drv.eu.org",
    customBypassURL: GM_getValue("custom_proxy", ""),

    viewer_data: unsafeWindow.viewer_data,
    api_response: unsafeWindow.viewer_data.api_response,
    dataType: unsafeWindow.viewer_data.type,
};

function createElementWithListener(html, type, listener) {
    const div = document.createElement("div");
    div.style.setProperty("display", "contents", "important");
    div.innerHTML = html;
    div.addEventListener(type, listener);
    return div;
}

function createButtonHTML(iconName, title, text, extraClass = "") {
    return `
        <button class="toolbar_button svelte-jngqwx ${extraClass}" title="${title}">
            <i class="icon">${iconName}</i>
            <span class="svelte-jngqwx">${text}</span>
        </button>
    `;
}

function showModal(title, content) {
    const MODAL_HTML = `
        <div class="background svelte-1f8gt9n" style="z-index: 10001;" role="dialog">
            <div class="window svelte-1f8gt9n" role="dialog" aria-modal="true">
                <div class="header svelte-1f8gt9n">
                    <span class="title svelte-1f8gt9n" style="padding-inline: calc(2rem + 32px) 2rem;">${title}</span>
                    <button class="button svelte-1ef47mx round close-button">
                        <i class="icon">close</i>
                    </button>
                </div>
                <div class="body svelte-1f8gt9n" style="padding: 1rem;">
                    <div class="container svelte-1j8hfe6" style="display: flex; flex-direction: row;">
                        ${content}
                    </div>
                </div>
            </div>
        </div>
    `;

    const modalElement = createElementWithListener(MODAL_HTML, "click", (event) => {
        if (event.target.matches(".background") || event.target.closest(".close-button")) {
            modalElement.remove();
        }
    });

    document.body.insertAdjacentElement("afterbegin", modalElement);
}

function downloadFile(fileName, fileID, el) {
    return new Promise((resolve, reject) => {
        const selectedDomain = PDLB_CONFIG.customBypassURL || PDLB_CONFIG.defaultBypassURL;
        const url = `https://${selectedDomain}/${fileID}`;

        GM_xmlhttpRequest({
            url,
            responseType: "blob",
            onload(event) {
                resolve(event);
                if (event.status !== 200) {
                    showModal("Download error", "The server probably blocked this download.");
                    return;
                }
                const a = document.createElement("a");
                a.target = "_blank";
                a.href = URL.createObjectURL(event.response);
                a.download = fileName;
                a.click();
                el.style.setProperty("--loaded", "0");
            },
            onerror(event) {
                reject(event);
            },
            onprogress(event) {
                el.style.setProperty("--loaded", `${(event.loaded * el.clientWidth) / event.total}px`);
            },
        });
    });
}

async function massiveDownload(files, el) {
    for (const file of files) {
        try {
            await downloadFile(file.name, file.id, el);
        } catch (error) {
            console.error(`Failed to download ${file.name}:`, error);
            showModal("Download error", `Failed to download ${file.name}.`);
        }
    }
}

function copyBypassURL(fileID) {
    const selectedDomain = PDLB_CONFIG.customBypassURL || PDLB_CONFIG.defaultBypassURL;
    const url = `https://${selectedDomain}/${fileID}`;
    navigator.clipboard
        .writeText(url)
        .then(() => showModal("URL copied", "The bypass URL has been copied to your clipboard."))
        .catch(() => showModal("Copy failed", "Could not copy the URL. Please copy it manually."));
}

function handleSingleFile(separator, fileData) {
    const { name, id } = fileData;
    const downloadButtonHTML = createButtonHTML("download", "Bypass download", "Download bypass", "download-bypass");
    const copyButtonHTML = createButtonHTML("content_copy", "Copy bypass url", "Copy bypass URL");

    const downloadButton = createElementWithListener(downloadButtonHTML, "click", () => downloadFile(name, id, downloadButton.firstElementChild));
    const copyButton = createElementWithListener(copyButtonHTML, "click", () => copyBypassURL(id));

    separator.insertAdjacentElement("afterend", downloadButton);
    downloadButton.insertAdjacentElement("afterend", copyButton);
}

function handleFileList(separator, listData) {
    const selectedDomain = PDLB_CONFIG.customBypassURL || PDLB_CONFIG.defaultBypassURL;

    const availableFiles = listData.files.filter((file) => file.availability === "");
    const fileUrls = availableFiles.map((file) => `<a href="https://${selectedDomain}/${file.id}">${file.name}</a>`).join("<br>");
    const containerFileUrls = `<div class="indent" style="display: flex; flex-direction: column;justify-content: center;align-items: center;">${fileUrls}</div>`;
    const bypassUrls = availableFiles.map((file) => `https://${selectedDomain}/${file.id}`).join("\n");
    const containerBypassUrls = `<pre class="indent" style="padding-inline: .5rem;">${bypassUrls}</pre>`;

    const dlSelectedButtonHTML = createButtonHTML("download", "Bypass download selected file", "Download selected file");
    const dlAllButtonHTML = createButtonHTML("download", "Bypass download all files", "Download all files");
    const copyButtonHTML = createButtonHTML("content_copy", "Copy bypass url", "Copy bypass URL");
    const showUrlsButtonHTML = createButtonHTML("link", "Show bypass URLs", "Show bypass URLs");

    const dlAllButton = createElementWithListener(dlAllButtonHTML, "click", () => massiveDownload(availableFiles, dlAllButton.firstElementChild));
    const showUrlsButton = createElementWithListener(showUrlsButtonHTML, "click", () => showModal("Bypass URLs", containerFileUrls + containerBypassUrls));
    const copyButton = createElementWithListener(copyButtonHTML, "click", () => {
        const selectedFile = listData.files.find((file) => file.selected);
        copyBypassURL(selectedFile.id);
    });
    const dlSelectedButton = createElementWithListener(dlSelectedButtonHTML, "click", () => {
        const selectedFile = listData.files.find((file) => file.selected);
        if (selectedFile.availability !== "") {
            showModal(selectedFile.availability, selectedFile.availability_message);
            return;
        }
        downloadFile(selectedFile.name, selectedFile.id, dlSelectedButton.firstElementChild);
    });

    separator.insertAdjacentElement("afterend", dlSelectedButton);
    dlSelectedButton.insertAdjacentElement("afterend", dlAllButton);
    dlAllButton.insertAdjacentElement("afterend", copyButton);
    copyButton.insertAdjacentElement("afterend", showUrlsButton);
}

function registerCommands() {
    GM_registerMenuCommand(`[Current proxy]: ${PDLB_CONFIG.customBypassURL || PDLB_CONFIG.defaultBypassURL}`, () => {});
    GM_registerMenuCommand("Set custom proxy", () => {
        const proxyDomain = prompt("Set your custom proxy", GM_getValue("custom_proxy", ""));

        GM_setValue("custom_proxy", proxyDomain || "");

        unsafeWindow.location.reload();
    });
}

function init() {
    if (!PDLB_CONFIG.viewer_data) {
        console.warn("Viewer data not found. Script may not function correctly.");
        return;
    }

    const separator = document.querySelector(".toolbar > .separator.svelte-jngqwx");
    if (!separator) {
        console.warn("Toolbar separator not found. Cannot add buttons.");
        return;
    }

    GM_addStyle(`.file_preview_row:has(.gallery) :where([title="Bypass download selected file"], [title="Copy bypass url"]) { display: none !important; }`);

    switch (PDLB_CONFIG.dataType) {
        case "file":
            handleSingleFile(separator, PDLB_CONFIG.api_response);
            break;
        case "list":
            handleFileList(separator, PDLB_CONFIG.api_response);
            break;
        default:
            console.warn(`File type "${PDLB_CONFIG.dataType}" not supported.`);
    }

    registerCommands();
}

init();