Displays image dimensions (eg. "1920 × 1080") for each thumbnail on the Google Image Search results page.
// ==UserScript==
// @name Google Image Search - Show Image Dimensions
// @name:de Google Bildersuche - Bildabmessungen anzeigen
// @name:fr Google Image Search - Afficher les dimensions de l'image
// @name:es Búsqueda de imágenes de Google - Mostrar las dimensiones de la imagen
// @name:it Ricerca immagini su Google - Mostra le dimensioni delle immagini
// @name:pl Wyszukiwanie obrazów Google - Pokaż wymiary obrazu
// @name:ru Поиск изображений Google - Показать размеры изображений
// @description Displays image dimensions (eg. "1920 × 1080") for each thumbnail on the Google Image Search results page.
// @description:de Zeigt die Bildabmessungen (z. B. "1920 × 1080") für jedes Vorschaubild auf der Ergebnisseite der Google-Bildsuche an.
// @description:fr Affiche les dimensions de l'image (par exemple, "1920 × 1080") pour chaque miniature sur la page de résultats de Google Image Search.
// @description:es Muestra las dimensiones de la imagen (p. ej., "1920 × 1080") para cada miniatura de la página de resultados de Google Image Search.
// @description:it Visualizza le dimensioni dell'immagine (ad es. "1920 × 1080") per ogni miniatura nella pagina dei risultati della ricerca immagini di Google.
// @description:pl Wyświetla wymiary obrazu (np. "1920 × 1080") dla każdej miniaturki na stronie wyników wyszukiwania obrazów Google.
// @description:ru Отображает размеры изображения (например, "1920 × 1080") для каждой миниатюры на странице результатов поиска изображений Google.
// @namespace https://github.com/tadwohlrapp
// @author Tad Wohlrapp
// @version 1.5.0
// @license MIT
// @homepageURL https://github.com/tadwohlrapp/google-image-search-show-image-dimensions-userscript
// @supportURL https://github.com/tadwohlrapp/google-image-search-show-image-dimensions-userscript/issues
// @icon https://github.com/tadwohlrapp/google-image-search-show-image-dimensions-userscript/raw/main/icon.png
// @grant unsafeWindow
// @include https://*.google.tld/*tbm=isch*
// @include https://*.google.tld/*udm=2*
// @compatible firefox Tested on Firefox v146 with Violentmonkey v2.31.0, Tampermonkey v5.4.1 and Greasemonkey v4.13.0
// @compatible chrome Tested on Chrome v143 with Violentmonkey v2.31.0 and Tampermonkey v5.4.1
// @compatible edge Tested on Edge v143 with Violentmonkey v2.31.0 and Tampermonkey v5.4.0
// @compatible opera Tested on Opera v125 with Tampermonkey v5.3.6222
// ==/UserScript==
(function () {
'use strict';
const DELAY_TIME = 500;
function showDims() {
setTimeout(() => {
// Find all results & exclude the "already handled" class we set below
const results = document.querySelectorAll('div[data-attrid="images universal"]:not(.img-dims)');
// Loop through all results
results.forEach((result) => {
try {
// Get result ID from jsdata attribute
const jsdata = result.getAttribute('jsdata');
const resultId = jsdata.split(';')[2];
// Access "W_jd" in window object
const W_jd = unsafeWindow.W_jd;
const rawResultData = W_jd[resultId];
const symbols = Object.getOwnPropertySymbols(rawResultData);
// Traverse down to the data we want
const level0 = rawResultData[symbols[0]];
if (!level0) return;
const level1 = Object.values(level0)[0]?.[1];
if (!level1) return;
const level2 = Object.values(level1)[0]?.[3];
if (!level2) return;
// Extract full res URL, width and height. Abort if not found
const [imgurl, height, width] = level2;
if (!width || !height || !imgurl) return;
// Filter out Meta sites & TikTok which prevent direct full res linking. It's brainrot anyways
const hn = (new URL(imgurl)).hostname;
const goodUrl = !hn.startsWith('lookaside') && !hn.startsWith('www.tiktok.com');
// Create svg icon for full res lightbox
const icon = createSVG('svg', { viewBox: '0 0 24 24', width: '16', height: '16' }, [
createSVG('path', { d: 'M19 21H5l-2-2V5l2-2h7v2H5v14h14v-7h2v7l-2 2z' }),
createSVG('path', { d: 'M21 10h-2V5h-5V3h7z' }),
createSVG('path', { d: 'M8 14 19 3l2 2-11 11z' })
]);
// Create element for dimensions text
const dimensionsElement = document.createElement(goodUrl ? 'a' : 'p');
dimensionsElement.textContent = '';
if (goodUrl) dimensionsElement.append(icon);
dimensionsElement.append(`${width} × ${height}`);
dimensionsElement.classList.add('dims');
// Create full res link
if (goodUrl) {
dimensionsElement.href = imgurl;
dimensionsElement.onclick = (e) => {
if (!isKeyPressed) {
e.preventDefault();
showLightbox(imgurl);
}
};
}
// Append everything to the thumbnail
const thumbnail = result.querySelector('h3');
thumbnail.append(dimensionsElement);
// Add CSS class to result
result.classList.add('img-dims');
} catch (error) {
console.warn('Show Image Dimensions UserScript:', error);
}
});
}, DELAY_TIME);
}
// Run script once on document ready
showDims();
// Initialize new MutationObserver
const mutationObserver = new MutationObserver(showDims);
// Let MutationObserver target the grid containing all results
const targetNode = document.querySelector('div#rso');
// Run MutationObserver
mutationObserver.observe(targetNode, { childList: true, subtree: true });
// Create lightbox for full res images
const lightboxBackdrop = document.createElement('div');
lightboxBackdrop.classList.add('img-backdrop');
const lightboxWrap = document.createElement('div');
lightboxWrap.classList.add('img-wrap');
const lightboxImg = document.createElement('img');
lightboxWrap.append(lightboxImg);
lightboxBackdrop.append(lightboxWrap);
document.body.append(lightboxBackdrop);
let isKeyPressed = false;
document.addEventListener('keydown', () => isKeyPressed = true);
document.addEventListener('keyup', () => isKeyPressed = false);
// Show full res image
const showLightbox = imgurl => {
lightboxBackdrop.classList.add('show');
lightboxImg.src = imgurl;
lightboxImg.onload = () => {
lightboxWrap.classList.add('show');
}
lightboxBackdrop.onclick = (e) => {
hideLightbox(e);
};
lightboxImg.onclick = (e) => {
window.open(imgurl, '_blank');
};
document.addEventListener('keydown', closeOnEsc);
}
// Hide full res image
const hideLightbox = () => {
lightboxBackdrop.classList.remove('show');
lightboxWrap.classList.remove('show');
lightboxImg.removeAttribute('src');
delete lightboxImg.dataset.ilt;
document.removeEventListener('keydown', closeOnEsc);
}
const closeOnEsc = (e) => {
if (e.key === 'Escape') hideLightbox(e);
};
// Helper function to generate small svg icon
const createSVG = (type, attrs = {}, children = []) => {
const el = document.createElementNS('http://www.w3.org/2000/svg', type);
for (const [key, value] of Object.entries(attrs)) {
el.setAttribute(key, value);
}
if (children.length > 0) el.append(...children);
return el;
}
// Add CSS function
const addStyles = css => {
const style = document.createElement('style');
style.textContent = css;
document.head.appendChild(style);
}
// Styles for dimensions and full res lightbox
addStyles(`
.img-dims .dims {
display: flex;
gap: 3px;
position: absolute;
bottom: 0;
right: 0;
margin: 0;
padding: 4px;
color: #f1f3f4;
background-color: rgba(0, 0, 0, 0.6);
border-radius: 2px 0 12px 0;
font-family: Roboto-Medium, Roboto, Arial, sans-serif;
font-size: 10px;
line-height: 12px;
text-decoration: none;
}
.img-dims .dims svg {
fill: #f1f3f4;
height: 12px;
width: 12px;
opacity: 0.4;
}
.img-dims .dims:hover svg {
opacity: 1;
}
.img-backdrop {
position: fixed;
display: flex;
pointer-events: none;
opacity: 0;
transition: all 0.2s ease-in-out;
top: 0;
left: 0;
z-index: 1010;
justify-content: center;
align-items: center;
}
.img-backdrop.show {
pointer-events: all;
bottom: 0;
right: 0;
opacity: 1;
background-color: rgba(0, 0, 0, 0.6);
}
.img-backdrop.show .img-wrap {
z-index: 1011;
border-radius: 12px;
cursor: pointer;
display: block;
position: relative;
overflow: hidden;
transition: all 0.2s ease-in-out;
background-color: rgba(255, 255, 255, 0.33);
box-shadow: inset 0px 0px 50px 10px rgba(0, 0, 0, 0.66);
}
.img-backdrop.show .img-wrap img {
position: relative;
display: block;
z-index: 1012;
max-width: 95vw;
max-height: 95vh;
opacity: 0;
transition: all 0.2s ease-in-out;
}
.img-backdrop.show .img-wrap.show {
background-color: #fff;
box-shadow: 0px 0px 100px 20px rgba(0, 0, 0, 0.66);
}
.img-backdrop.show .img-wrap.show img {
opacity: 1;
}
`);
})();