Download Gif Button for GIPHY (working in 2025)

Adds a download button for gif download

// ==UserScript==
// @name            Download Gif Button for GIPHY (working in 2025)
// @namespace       com.giphy
// @version         1.0.2
// @description     Adds a download button for gif download
// @author          Thomas R.
// @license          MIT
// @match           http*://giphy.com/*
// @icon            https://www.google.com/s2/favicons?sz=64&domain=giphy.com
// @require         https://greasyfork.org/scripts/374849-library-onelementready-es6/code/Library%20%7C%20onElementReady%20ES6.js
// @grant           GM.addStyle
// @grant           GM.download
// @run-at          document-end
// ==/UserScript==

const slugify = (string) => {
    return string
        .toString()
        .toLowerCase()
        .normalize('NFD')
        .replace(/[\u0300-\u036f]/g, '')
        .replace(/[^a-z0-9\s-]/g, '')
        .replace(/\s+/g, '-')
        .replace(/-+/g, '-')
        .replace(/^-+|-+$/g, '');
}

const downloadFile = (url, filename) => {
    GM.download({
        url: url,
        name: filename,
        saveAs: true
    });
}

const handleDownload = () => {
    // not present on client side navigation
    // const imageData = JSON.parse(document.querySelectorAll('script[type="application/ld+json"]')[1].text);
    // const urlArray = imageData.image.url.split('/');
    // const gifId = urlArray[urlArray.length - 2];

    const pageUrlArray = window.location.pathname.split('/');
    const gifNameArray = pageUrlArray[pageUrlArray.length - 1].split('-');;
    const gifId = gifNameArray[gifNameArray.length - 1];

    const gifURL = `https://i.giphy.com/${gifId}.gif`;

    downloadFile(gifURL, `${slugify(document.title.split('-')[0])}.gif`);
}


const addMenuItem = (menu) => {
    const lastMenuItem = menu.querySelector(':first-child');
    const newMenuItem = lastMenuItem.cloneNode(true);

    const svg = newMenuItem.querySelector('svg');
    svg.innerHTML = '<path d="M19 9h-4V3H9v6H5l7 7l7-7zM5 18v2h14v-2H5z"/>';
    svg.setAttribute("style","margin-top: -6px;margin-right: 6px;");
    svg.setAttribute('width', '33.3');
    svg.setAttribute('height', '33.3');

    const textElement = newMenuItem.querySelector('label');
    textElement.textContent = 'Download';

    newMenuItem.addEventListener("click",handleDownload);

    menu.appendChild(newMenuItem);
}

const init = () => {
    onElementReady('figure > div:nth-child(2) > div:nth-child(2) >div:nth-child(1)', false, (element) => {
        addMenuItem(element);
    });
}

init();