Greasy Fork is available in English.
Creates a scrollable wall of full-size images from any user's instagram page, "tagged" page, or the instagram homepage. Just click the "Load Images" button at the top of the list of images/posts.
// ==UserScript== // @name Instagram full-size media scroll wall // @namespace driver8.net // @author driver8 // @license GNU AGPLv3 // @description Creates a scrollable wall of full-size images from any user's instagram page, "tagged" page, or the instagram homepage. Just click the "Load Images" button at the top of the list of images/posts. // @match *://*.instagram.com/* // @version 0.2.4.4 // @grant none // @run-at document-start // ==/UserScript== (function() { 'use strict'; console.log('hi insta scroll'); // https://www.instagram.com/graphql/query/?query_hash=<hash>&variables={%22shortcode%22:%22<shortcode>%22} // https://i.instagram.com/api/v1/usertags/0000000000/feed/?count=12&max_id=0000000000000000000 const IMAGES_PER_QUERY = 12; const NTH_TO_LAST_IMAGE = 3; const HEIGHT_PCT = .8; const WIDTH_PCT = .49; const VID_VOLUME = 0.02; var MODE = 'profile'; const win = window; var userId = win.userId; var notLoaded = true; const tempDiv = document.createElement('div'); if (win.trustedTypes && win.trustedTypes.createPolicy) { // Feature testing win.trustedTypes.createPolicy('default', { createHTML: (str) => str }); } function pickMode() { console.log('picking mode'); if (document.location.href.match(/https:\/\/(www\.)?instagram.com\/?(\?|$|#)/)) { MODE = 'home'; getQueryHash(); } else if (document.location.href.match(/\/tagged\//)) { MODE = 'tagged'; getUserId(); } else if (document.location.href.match(/\/explore\//)) { MODE = 'explore'; console.log('"Explore" loading not implemented yet!'); //getQueryHash(); } else if (document.location.href.match(/https:\/\/(www\.)?instagram.com\/p\//)) { MODE = 'post'; } else { MODE = 'profile'; getUserId(); } console.log('MODE', MODE); } function getUserId() { //console.log('getUserId'); userId = userId || document.body.innerHTML.match(/profilePage_(\d+)/)?.[1]; userId = userId || document.body.innerHTML.match(/<a author_id="(\d+)" class="heKAw"/)?.[1]; if (userId) { console.log('userId', userId); getQueryHash(); } else { let req = indexedDB.open('redux'); req.onsuccess = function(evt) { console.log('req evt', evt); let db = req.r###lt; let os = db.transaction("paths")?.objectStore("paths"); let req2 = db.transaction("paths")?.objectStore("paths")?.get('users.usernameToId'); req2.onsuccess = function(evt) { console.log('db evt', evt); let r###lt = req2?.r###lt; let userName = document.location.href.match(/https:\/\/(?:www\.)?instagram.com\/([^\/]{3,})/)?.[1]; console.log('userName', userName); userId = r###lt?.[userName]; if (userId) { getQueryHash(); } else { requestUserId(); console.log("Couldn't find user ID!"); return; } }; }; } } function requestUserId() { let loc = document.location.href; if (loc.match(/https:\/\/(?:www\.)?instagram.com\/([^\/]{3,})\/?$/)) { loc += '?__a=1'; fetch(loc) .then(resp => { return resp.json(); }) .then(json => { console.log('userId json', json); userId = json?.graphql?.user?.id; if (userId) { getQueryHash(); } else { console.log("Couldn't find user ID!"); return; } }); } else { console.log("URL doesn't match a profile page"); return; } } function getQueryHash() { console.log('getQueryHash'); let allScripts = Array.from(document.getElementsByTagName('script')); let PostPageContainer = allScripts.find(el => el.src && el.src.match(/ProfilePageContainer.js/)); let ConsumerLibCommons = allScripts.find(el => el.src && el.src.match(/ConsumerLibCommons.js/)); let Consumer = allScripts.find(el => el.src && el.src.match(/Consumer.js/)); let randomJs = allScripts.find(el => el.src && el.src.match(/miOdM842jTv\.js/)); randomJs = null; let y8 = '';//allScripts.find(el => el.src && el.src.match(/\/v3iNkn4\/|ODje2xQc3d4\.js|\/y8\//))?.src; var query_hash = false, query_id = false, doc_id = false; if (ConsumerLibCommons) { fetch(ConsumerLibCommons.src) .then(resp => { console.log('resp 1', resp); return resp.text(); }) .then(text => { query_id = text.match(/profilePosts\.byUserId\.get.*?queryId:"([a-f0-9]+)"/)?.[1]; //profilePosts.byUserId.get(n))||void 0===s?void 0:s.pagination},queryId:"e5555555555555555555555555555508" let app_id = text.match(/instagramWebDesktopFBAppId='(\d+)'/)?.[1]; let asbd_id = text.match(/ASBD_ID='(\d+)'/)?.[1]; query_id && notLoaded && loadImages(query_id, query_hash, doc_id, app_id, asbd_id); }); } if (PostPageContainer) { fetch(PostPageContainer.src) .then(resp => { console.log('resp 2', resp); return resp.text(); }) .then(text => { query_id = text.match(/profilePosts\.byUserId\.get.*?queryId:"([a-f0-9]+)"/)?.[1]; //profilePosts.byUserId.get(n))||void 0===s?void 0:s.pagination},queryId:"e5555555555555555555555555555508" let app_id = text.match(/instagramWebDesktopFBAppId='(\d+)'/)?.[1]; let asbd_id = text.match(/ASBD_ID='(\d+)'/)?.[1]; query_id && notLoaded && loadImages(query_id, query_hash, doc_id, app_id, asbd_id); }); } // l.pagination},queryId:"15b55555555555555555555555555551" if (Consumer) { fetch(Consumer.src) .then(resp => { console.log('resp 3', resp); return resp.text(); }) .then(text => { query_id = text.match(/profilePosts\.byUserId\.get[^;]+queryId:\s*"([a-f0-9]+)"/)?.[1]; //text.match(/l\.pagination\},queryId:"([a-f0-9]+)"/); //const s="05555555555555555555555555555554",E=" let app_id = text.match(/instagramWebDesktopFBAppId='(\d+)'/)?.[1]; let asbd_id = text.match(/ASBD_ID='(\d+)'/)?.[1]; query_id && notLoaded && loadImages(query_id, query_hash, doc_id, app_id, asbd_id); }); } if (randomJs) { fetch(randomJs.src) .then(resp => { console.log('resp 4', resp); return resp.text(); }) .then(text => { doc_id = text.match(/,"polarisUnexpected"\],\(function\(a,b,c,d,e,f,g\)\{"use strict";e=0;f="(\d+)";var h="/)?.[1]; //text.match(/l\.pagination\},queryId:"([a-f0-9]+)"/); //const s="05555555555555555555555555555554",E=" let app_id = text.match(/instagramWebDesktopFBAppId='(\d+)'/)?.[1]; app_id = app_id || text.match(/;\s*([a-z])\s*=\s*(['"])(\d+)\2;[^}]*f\.instagramWebDesktopFBAppId\s*=\s*\1;/)?.[3]; let asbd_id = text.match(/ASBD_ID='(\d+)'/)?.[1]; asbd_id = asbd_id || text.match(/([a-z]+)="(\d+)";f.ASBD_ID=\1/)?.[2]; console.log('app_id, asbd_id, doc_id', app_id, asbd_id, doc_id); doc_id && notLoaded && loadImages(query_id, query_hash, doc_id, app_id, asbd_id); }); } //let fberror = win?.require?.('PolarisAPI')?.fetchFBInfo('foo'); let fberror = null; (function checkError() { if (fberror?._state == 2) { //console.log(typeof fberror?._value, '_value', fberror?._value); console.log(fberror); y8 = fberror?._value?.fileName; y8 = y8 || fberror?._value?.stack?.match(/\((https[^\)]+)\)/)?.[1]; y8 = y8 || Object.values(Object.values(win.pldmp)?.[0]).find(o => o.refs.length === 4 && o.url.match(/rsrc\.php.*\/[a-z]{2,3}_[A-Z]{2,3}\/[^\/.]{9,15}\.js/)); if (y8) { console.log('y8', y8); fetch(y8) .then(resp => { console.log('resp 1', resp); return resp.text(); }) .then(text => { query_id = text.match(/,"regeneratorRuntime"\],\(function\(a,b,c,d,e,f,g\)\{f=0;var h="([a-f0-9]+)"/)?.[1]; query_id = query_id || text.match(/,"regeneratorRuntime"\],\(function\(a,b,c,d,e,f,g\)\{"use strict";f=0;var h="([a-f0-9]+)"/)?.[1]; query_id = query_id || text.match(/,"regeneratorRuntime"\],\(function\(a,b,c,d,e,f,g\)\{"use strict";e=0;f="([a-f0-9]+)"/)?.[1]; //query_id = query_id || text.match(/([a-z]{1,2})="([a-f0-9]{32})".*queryId:\1/)?.[2]; if (query_id && notLoaded) { loadImages(query_id); } else if (notLoaded) { loadImages(-1); } }); } } else { //window.setTimeout(checkError, 20); if (notLoaded) { loadImages(-1); } } })(); } // https://www.instagram.com/graphql/query/?query_hash=<queryhash>&variables=%7B%22id%22%3A%22<profle_id>%22%2C%22first%22%3A12%2C%22after%22%3A%22<after_code>%3D%3D%22%7D // https://www.instagram.com/graphql/query/?doc_id=<doc_id>&variables={"id":"<profile_id>","after":"<after_code>","first":12} function loadImages(query_id=0, query_hash=0, doc_id=0, app_id=936619743392459, asbd_id=129477, after=null) { // asbd_id=198387 notLoaded = false; console.log('MODE', MODE, 'query_id', query_id, 'query_hash', query_hash); app_id = app_id || 936619743392459; asbd_id = asbd_id || 129477; // let userId = document.querySelector('head > meta[property="instapp:owner_user_id"]')?.content; let imageListQueryUrl; let init = { responseType: 'json', credentials: 'include', referrerPolicy: 'no-referrer'}; // if (MODE == 'profile') { // if (!userId) { // console.log("Couldn't find user ID!", userId); // return; // } // let queryVariables = {"id": userId, "first": IMAGES_PER_QUERY}; // if (after) queryVariables.after = after; // let queryVariablesString = encodeURIComponent(JSON.stringify(queryVariables)); // imageListQueryUrl = `https://www.instagram.com/graphql/query/?query_hash=${query_id}&variables=${queryVariablesString}`; if (MODE == 'profile') { if (!userId) { console.log("Couldn't find user ID!", userId); return; } let queryVariables = {"id": userId, "first": IMAGES_PER_QUERY}; if (after) queryVariables.after = after; let queryVariablesString = encodeURIComponent(JSON.stringify(queryVariables)); //https://i.instagram.com/api/v1/feed/user/696969696/?count=12&max_id=0000000000000000000_696969696 imageListQueryUrl = `https://i.instagram.com/api/v1/feed/user/${userId}/?count=12`; if (after) { imageListQueryUrl += `&max_id=${after}`; } init.headers = { 'X-IG-App-ID': app_id, 'X-ASBD-ID': asbd_id, 'X-CSRFToken': win._sharedData?.config?.csrf_token }; console.log(imageListQueryUrl, queryVariablesString, init); } if (MODE == 'tagged') { if (!userId) { console.log("Couldn't find user ID!", userId); return; } imageListQueryUrl = `https://i.instagram.com/api/v1/usertags/${userId}/feed/?count=${IMAGES_PER_QUERY}`; if (after) { imageListQueryUrl += `&max_id=${after}`; } init.headers = { 'X-IG-App-ID': app_id, 'X-ASBD-ID': asbd_id, 'X-CSRFToken': win._sharedData?.config.csrf_token } } if (MODE == 'home') { imageListQueryUrl = 'https://i.instagram.com/api/v1/feed/timeline/'; //let fd = new FormData(); let fd = new URLSearchParams(); fd.set('is_async_ads_rti', 0); fd.set('is_async_ads_double_request', 0); fd.set('rti_delivery_backend', 0); fd.set('is_async_ads_in_headload_enabled', 0); fd.set('devide_id', win._sharedData?.device_id); if (after) { fd.set('max_id', after); } init.body = fd; init.method = 'POST'; init.headers = { 'X-IG-App-ID': app_id, 'X-ASBD-ID': asbd_id, 'X-CSRFToken': win._sharedData?.config.csrf_token } } fetch(imageListQueryUrl, init) .then(resp => { console.log('json resp', resp); return resp.json(); }) .then(json => { console.log('json', json); let timelineMedia, end_cursor, mediaList; timelineMedia = json.data?.user.edge_owner_to_timeline_media; end_cursor = timelineMedia?.page_info.end_cursor || json.next_max_id; mediaList = timelineMedia?.edges.map(n => n.node) || json.items || json.feed_items?.map(n => n.media_or_ad).filter(n => n); console.log('end_cursor', end_cursor, 'media list', mediaList); let bigContainer = document.querySelector('#igBigContainer'); // Create the main container if it doesn't exist if (!bigContainer) { tempDiv.innerHTML = `<div id="igBigContainer" style="background-color: #112;width: 100%;height: 100%;z-index: 999;position: fixed;top: 0;left: 0;overflow: scroll;"> <div id="igAllImages" style="display:block; text-align:center;"></div></div>`; bigContainer = tempDiv.firstElementChild; let newBody = document.createElement('body'); document.body = newBody; document.body.appendChild(bigContainer); XMLHttpRequest.prototype.send = (evt) => { //console.log('No send!'); }; let imgStyle = document.createElement('style'); imgStyle.type = 'text/css'; setMaxSize(imgStyle); document.body.appendChild(imgStyle); window.addEventListener('resize', evt => setMaxSize(imgStyle)); styleIt(); } let innerContainer = bigContainer.firstElementChild; console.log(mediaList); for (let media of mediaList) { addMedia(media, innerContainer); } if (end_cursor) { //console.log('end_cursor', end_cursor); let triggerImage = document.querySelector('#igAllImages a:nth-last-of-type(3)') || document.querySelector('#igAllImages a:last-of-type'); bigContainer.onscroll = (evt) => { let vh = document.documentElement.clientHeight || window.innerHeight || 0; if (triggerImage.getBoundingClientRect().top - 800 < vh) { bigContainer.onscroll = null; console.log('loading next set of images'); loadImages(query_id, query_hash, doc_id, app_id, asbd_id, end_cursor); } } } }); } function getBestImage(media) { let bestUrl = null; let bestSize = 0; let list = media?.display_resources || media?.image_versions2?.candidates;; for (let m of list) { let w = m?.width || m?.config_width || 0; let h = m?.height || m?.config_height || 0; let size = Math.max(w, h); //console.log('size', size, m); if (size > bestSize) { bestSize = size; bestUrl = m?.url || m?.src; } } //best = media?.display_resources?.reduce((a, b) => Math.max(a.width, a.height) > Math.max(b.width, b.height) ? a : b).src; return bestUrl; } function addMedia(media, container) { //console.log('media', media); let shortcode = media?.shortcode || media?.code; let medias = media?.edge_sidecar_to_children?.edges?.map(n => n.node) || media?.carousel_media || [ media ]; for (let i = 0; i < medias.length; i++) { let m = medias[i]; let a = document.createElement('a'); a.href = `https://www.instagram.com/p/${shortcode}/`; let un = media?.user?.username || media?.owner?.username; let caption = media?.caption?.text || media?.edge_media_to_caption?.edges?.[0]?.node?.text; a.title = `${media?.user?.full_name || ''} (${un}) ${caption} [${i+1}]`; //console.log('m', m); if (m?.is_video || m?.is_unified_video || m?.video_duration) { tempDiv.innerHTML = `<div class="vidDiv"></div>`; let vidDiv = tempDiv.firstElementChild; let vid = document.createElement('video'); vid.src = m?.video_url || m?.video_versions?.reduce((a, b) => Math.max(a.width, a.height) > Math.max(b.width, b.height) ? a : b)?.url; vid.controls = true; vid.volume = VID_VOLUME; a.textContent = 'Link'; vidDiv.appendChild(vid); vidDiv.appendChild(a); container.appendChild(vidDiv); } else if (m?.ad_id || m?.label === 'Sponsored') { console.log('Skipping ad', m); return; } else { a.innerHTML += `<img src="${getBestImage(m)}">`; container.appendChild(a); } } } function setMaxSize(userStyle) { let vw = document.documentElement.clientWidth || window.innerWidth || 0; let vh = document.documentElement.clientHeight || window.innerHeight || 0; userStyle.innerHTML = ` #igAllImages img, #igAllImages video { max-height: ${vh * HEIGHT_PCT}px; max-width: ${vw * WIDTH_PCT}px; } `; } function styleIt() { let userStyle = document.createElement('style'); userStyle.type = 'text/css'; userStyle.innerHTML = ` #igAllImages video { border: green solid 2px; } #igAllImages .vidDiv { display: inline-block; } #igAllImages .vidDiv a { display: block; text-decoration: none; margin-top: -5px; } /*#loadallbutton { padding-top: 40px; }*/ `; document.body.appendChild(userStyle); console.log('styled'); } function startUp() { (function insertButton() { let loadButton = document.querySelector("#loadallbutton"); let insAt = null; if (!loadButton && !document.location.href.includes('instagram.com/p/')) { insAt = document.querySelector('div.fx7hk, div[role*=tablist]'); //, .ENC4C, .ZcHy5, ._47KiJ'); if (insAt) { styleIt(); tempDiv.innerHTML = profileButton; loadButton = tempDiv.firstElementChild; loadButton.onclick = pickMode; insAt.appendChild(loadButton); } else { //insAt = document.querySelector('article._8Rm4L, article[role="presentation"]')?.parentNode; insAt = document.querySelector('._aac4._aac5._aac6._aac7, ._aac4._aac5._aac6'); insAt = document.querySelector('._aam1._aam2._aam5'); insAt = document.querySelector('._ab6o._ab6q'); insAt = document.querySelector('._aalv._aalx._aalz'); insAt = document.querySelector('._aak6'); insAt = insAt || document.querySelector('main > div.MxEZm'); if (insAt) { styleIt(); tempDiv.innerHTML = homeButton; loadButton = tempDiv.firstElementChild; loadButton.onclick = pickMode; insAt.prepend(loadButton); //insAt.before(loadButton); //insAt.after(loadButton); //insAt.appendChild(loadButton); } } } if (!insAt) { window.setTimeout(insertButton, 50); } })(); } const profileButton = `<a aria-selected="false" class="_9VEo1 oajrlxb2 g5ia77u1 qu0x051f esr5mh6w e9989ue4 r7d6kgcz rq0escxv nhd2j8a9 nc684nl6 p7hjln8o kvgmc6g5 cxmmr5t8 oygrvhab hcukyx3x jb3vyjys rz4wbd8a qt6c0cv9 a8nywdso i1ao9s8h ###yzwwr f1sip0of lzcic4wl _aa-z _a6hd" role="tab" tabindex="0" id="loadallbutton"><span class="qzihg"><span class="_08DtY">Load Images</span></span></a>`; const homeButton = `<article class="_ab6k _ab6l _ab6m _aatb _aatc _aate _aatf _aath _aati _8Rm4L bLWKA M9sTE _1gNme L_LMM SgTZ1 Tgarh ePUX4" role="presentation" tabindex="-1" style="cursor: pointer;" id="loadallbutton"> <div class="_ab8w _ab94 _ab99 _ab9h _ab9m _ab9p qF0y9 Igw0E IwRSH YBx95 _4EzTm" style="max-height: inherit; max-width: inherit;"> <div class="_aasi _aasj UE9AK"> <div class="_ab8w _ab94 _ab97 _ab9i _ab9k _ab9p qF0y9 Igw0E rBNOH CcYR1 ybXk5 _4EzTm"> <header class="_aaqw _aaqx Ppjfr"> <div class="_aap6 _aap7 _aapa Jv7Aj mArmR pZp3x"> <div class="_aarf _aarg _aaqq RR-M- mrq0Z" aria-disabled="true" role="button" tabindex="-1"> <svg aria-label="" class="_8-yf5" color="#262626" fill="#262626" role="img" width="22" height="22" viewBox="0 0 24 20"> <rect fill="none" height="18" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" width="18" x="3" y="3"></rect> <line fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="9.015" x2="9.015" y1="3" y2="21"></line> <line fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="14.985" x2="14.985" y1="3" y2="21"></line> <line fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="21" x2="3" y1="9.015" y2="9.015"></line> <line fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="21" x2="3" y1="14.985" y2="14.985"></line> </svg> </div> </div> <div class="_aaqy _aaq- o-MQd z8cbW"> <div class=" _aar1 RqtMr"> <div class="_aaqt e1e1d"> <div class="_aacl _aaco _aacw _aacx _aad6 _aade"> <span class="_aap6 _aap7 _aap8 Jv7Aj mArmR MqpiF"><a class="oajrlxb2 g5ia77u1 qu0x051f esr5mh6w e9989ue4 r7d6kgcz rq0escxv nhd2j8a9 nc684nl6 p7hjln8o kvgmc6g5 cxmmr5t8 oygrvhab hcukyx3x jb3vyjys rz4wbd8a qt6c0cv9 a8nywdso i1ao9s8h ###yzwwr f1sip0of lzcic4wl _acan _acao _acat _acaw _a6hd sqdOP yWX7d _8A5w5 ZIAjV" tabindex="0">Load Images</a></span> </div> </div> </div> </div> </header> </div> </div> </div> </article> `; startUp(); })();