PAPAZ Google Direct Image Links (2026)

Βελτιωμένη εξαγωγή direct URLs σε Google Images. Δουλεύει καλύτερα με hover/middle-click. Διατηρεί side preview στο left-click.

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        PAPAZ Google Direct Image Links (2026)
// @version     3.0
// @description Βελτιωμένη εξαγωγή direct URLs σε Google Images. Δουλεύει καλύτερα με hover/middle-click. Διατηρεί side preview στο left-click.
// @author      DoctorEye
// @namespace   DoctorEye
// @match       https://www.google.com/search?*
// @match       https://www.google.gr/search?*
// @match       https://www.google.com/*/search?*
// @match       https://www.google.gr/*/search?*
// @match       https://images.google.com/*
// @match       https://images.google.gr/*
// @grant       none
// @license     Proprietary
// @run-at      document-end
// ==/UserScript==

(function() {
    'use strict';

    // Βοηθητική: βρίσκει το πιθανότερο direct URL από το link ή τα παιδιά του
    function extractDirectUrl(element) {
        if (!element) return null;

        const candidates = [];

        // 1. Κλασικό imgurl (παλιό αλλά ακόμα σε μερικά)
        let href = element.href || '';
        if (href.includes('/imgres?')) {
            try {
                const params = new URLSearchParams(new URL(href, location.origin).search);
                if (params.has('imgurl')) candidates.push(decodeURIComponent(params.get('imgurl')));
            } catch {}
        }

        // 2. Data attributes (συχνά κρυμμένα JSON ή encoded URLs)
        ['data-afm', 'data-ved', 'jsdata', 'data-ou', 'data-original', 'data-src-full', 'data-lt'].forEach(attr => {
            const val = element.getAttribute(attr);
            if (val) {
                // Αναζήτηση URL pattern
                const match = val.match(/(https?:\/\/[^"'<>\s)]+\.(jpe?g|png|webp|gif|bmp|svg)(?::[^"'<>\s)]*)?)/gi);
                if (match) candidates.push(...match);
                // Προσπάθεια decode base64 αν είναι encoded
                try {
                    const decoded = atob(val.replace(/[^A-Za-z0-9+/=]/g, ''));
                    const subMatch = decoded.match(/(https?:\/\/[^"'<>\s)]+\.(jpe?g|png|webp|gif|bmp|svg)(?::[^"'<>\s)]*)?)/gi);
                    if (subMatch) candidates.push(...subMatch);
                } catch {}
            }
        });

        // 3. Το img src/data-src (μετά hover συνήθως γίνεται μεγαλύτερο)
        const img = element.querySelector('img');
        if (img) {
            ['src', 'data-src', 'data-lt-src'].forEach(key => {
                let s = img.getAttribute(key);
                if (s && s.startsWith('https://') && !s.includes('googleusercontent.com') && s.length > 200) {
                    candidates.push(s.split('?')[0]); // καθαρό URL χωρίς params μεγέθους
                }
            });
        }

        // Επιστροφή του μεγαλύτερου/καθαρότερου candidate (συνήθως το καλύτερο είναι το πιο μακρύ)
        if (candidates.length === 0) return null;
        return candidates.sort((a,b) => b.length - a.length)[0] || null;
    }

    function processElement(el) {
        if (el.dataset.directFixed === 'yes') return;
        const url = extractDirectUrl(el);
        if (url) {
            el.href = url;
            el.dataset.directFixed = 'yes';
            // Προαιρετικό tooltip
            el.title = (el.title || '') + ' → Direct: ' + url.split('/').pop();
            console.log('[DirectFix] Applied:', url);
        }
    }

    // Βρες όλα τα πιθανά links εικόνων (ευρύ φάσμα selectors)
    function scanPage() {
        const selectors = [
            'a[jsname][role="link"]',
            'a[href*="/imgres"]',
            'a[aria-label*="Image result"]',
            'div[data-id] > a',
            '.wXeWr a', '.iPVvYb a', '.islrc a', '.rg_i a', // συχνές κλάσεις
            'div[role="listitem"] a',
            'a > div > img' // parent του img
        ].join(', ');

        document.querySelectorAll(selectors).forEach(el => {
            let link = el.closest('a') || el;
            if (link && link.tagName === 'A') processElement(link);
        });
    }

    // Αρχική εκτέλεση
    window.addEventListener('load', scanPage);
    setTimeout(scanPage, 1500); // extra για late loads

    // MutationObserver → νέα αποτελέσματα από scroll
    new MutationObserver(muts => {
        if (muts.some(m => m.addedNodes.length > 0)) {
            setTimeout(scanPage, 400);
        }
    }).observe(document.body, { childList: true, subtree: true });

    // Κρίσιμο: hover & focus → Google φορτώνει data εκεί
    ['mouseover', 'focusin'].forEach(ev => {
        document.addEventListener(ev, e => {
            let link = e.target.closest('a');
            if (link) {
                setTimeout(() => processElement(link), 250); // δίνουμε χρόνο στο Google JS
            }
        }, true);
    });

    // Periodic refresh (κάθε ~4 δευτ. για safety)
    setInterval(scanPage, 4000);

    // Bonus: Middle-click override (προαιρετικό – ανοίγει direct χωρίς side panel αν θες)
    // Αφαίρεσε τα σχόλια αν το θες ενεργό
    /*
    document.addEventListener('auxclick', e => {
        if (e.button === 1) { // middle click
            let link = e.target.closest('a');
            if (link && link.dataset.directFixed === 'yes') {
                e.preventDefault();
                e.stopPropagation();
                window.open(link.href, '_blank');
            }
        }
    }, true);
    */
})();