// ==UserScript== // @name Instagram Media Downloader (HD) // @name:tr Instagram Medya İndirici (HD) // @name:zh-CN Instagram 媒体下载器 (高清) // @name:fr Instagram Téléchargeur de Médias (HD) // @name:ru Instagram Загрузчик медиа (HD) // @name:ar إنستغرام منزل الوسائط (HD) // @namespace https://tr-wp.com/ // @version 1.2.0 // @description Download all media from a profile (Photos, Videos, Reels) in high quality as Single, JSON, or ZIP. // @description:tr Profildeki tüm medyaları (Fotoğraf, Video, Reels) yüksek kalitede Tekli, JSON veya ZIP olarak indirir. // @description:zh-CN 以单个、JSON 或 ZIP 格式高清下载个人资料中的所有媒体(照片、视频、Reels)。 // @description:fr Téléchargez tous les médias d'un profil (Photos, Vidéos, Reels) en haute qualité au format Solo, JSON ou ZIP. // @description:ru Загружайте все медиафайлы из профиля (Фото, Видео, Reels) в высоком качестве в форматах Solo, JSON или ZIP. // @description:ar قم بتنزيل جميع الوسائط من الملف الشخصي (صور، مقاطع فيديو، ريلز) بجودة عالية بتنسيق فردي أو JSON أو ZIP. // @author Yoka - tr-wp.com // @match https://www.instagram.com/* // @exclude https://www.instagram.com/reels/* // @exclude https://www.instagram.com/p/* // @exclude https://www.instagram.com/explore/* // @grant GM_xmlhttpRequest // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js // @run-at document-idle // @license MIT // @icon https://www.google.com/s2/favicons?domain=instagram.com&sz=64 // @downloadURL https://update.greasyfork.icu/scripts/570765/Instagram%20Media%20Downloader%20%28HD%29.user.js // @updateURL https://update.greasyfork.icu/scripts/570765/Instagram%20Media%20Downloader%20%28HD%29.meta.js // ==/UserScript== (function () { 'use strict'; var IG_APP_ID = '936619743392459'; // --- Localization --- const i18n = { en: { media: "Media", json: "JSON", zip: "ZIP", loading: "Loading...", user: "User...", fetching: "Fetching ", zipPrep: "Preparing ZIP...", done: "Downloaded", error: "Error", noMedia: "No media found.", session: "Ensure you are logged in." }, tr: { media: "Medya", json: "JSON", zip: "ZIP", loading: "Yükleniyor...", user: "Kullanıcı...", fetching: "Yükleniyor ", zipPrep: "ZIP hazırlanıyor...", done: "indirildi", error: "Hata", noMedia: "Hiç medya bulunamadı.", session: "Instagram oturumunun açık olduğundan emin olun." }, zh: { media: "媒体", json: "JSON", zip: "ZIP", loading: "正在加载...", user: "用户...", fetching: "正在获取 ", zipPrep: "正在准备 ZIP...", done: "已下载", error: "错误", noMedia: "未找到媒体。", session: "确保您已登录。" }, fr: { media: "Médias", json: "JSON", zip: "ZIP", loading: "Chargement...", user: "Utilisateur...", fetching: "Récupération ", zipPrep: "Préparation du ZIP...", done: "téléchargé", error: "Erreur", noMedia: "Aucun média trouvé.", session: "Assurez-vous d'être connecté." }, ru: { media: "Медиа", json: "JSON", zip: "ZIP", loading: "Загрузка...", user: "Пользователь...", fetching: "Получение ", zipPrep: "Подготовка ZIP...", done: "скачано", error: "Ошибка", noMedia: "Медиа не найдено.", session: "Убедитесь, что вы вошли в систему." }, ar: { media: "وسائط", json: "JSON", zip: "ZIP", loading: "جاري التحميل...", user: "مستخدم...", fetching: "جاري جلب ", zipPrep: "جاري تحضير ZIP...", done: "تم التنزيل", error: "خطأ", noMedia: "لم يتم العثور على وسائط.", session: "تأكد من تسجيل الدخول." } }; const lang = i18n[navigator.language.split('-')[0]] || i18n.en; // ── Toast ───────────────────────────────────────────────── function toast(msg, type) { var el = document.createElement('div'); var bg = type === 'err' ? '#c0392b' : type === 'ok' ? '#27ae60' : '#2c3e50'; Object.assign(el.style, { position: 'fixed', bottom: '24px', right: '16px', zIndex: '2147483648', background: bg, color: '#fff', padding: '10px 16px', borderRadius: '8px', fontSize: '12px', fontFamily: 'sans-serif', maxWidth: '280px', lineHeight: '1.5', boxShadow: '0 4px 12px rgba(0,0,0,.4)', opacity: '0', transition: 'opacity .25s', whiteSpace: 'pre-line' }); el.textContent = msg; document.body.appendChild(el); requestAnimationFrame(function () { el.style.opacity = '1'; }); setTimeout(function () { el.style.opacity = '0'; setTimeout(function () { el.remove(); }, 300); }, type === 'err' ? 5000 : 3000); } // ── API ─────────────────────────────────────────────────── function apiGet(url) { return new Promise(function (resolve, reject) { GM_xmlhttpRequest({ method: 'GET', url: url, timeout: 20000, headers: { 'x-ig-app-id': IG_APP_ID, 'Accept': 'application/json', 'Accept-Language': 'tr-TR,tr;q=0.9', 'Referer': 'https://www.instagram.com/', 'X-Requested-With': 'XMLHttpRequest' }, onload: function (r) { if (r.status < 200 || r.status >= 300) return reject(new Error('HTTP ' + r.status)); try { resolve(JSON.parse(r.responseText)); } catch (e) { reject(new Error('JSON parse error')); } }, onerror: function () { reject(new Error(lang.error)); }, ontimeout: function () { reject(new Error('Timeout')); } }); }); } function getUserId(username) { return apiGet('https://www.instagram.com/api/v1/users/web_profile_info/?username=' + username) .then(function (d) { var pk = d && d.data && d.data.user && d.data.user.id; if (!pk) throw new Error(lang.user); return pk; }); } function fetchAllPosts(userId, btnId) { var posts = [], cursor = null; function nextPage() { var url = 'https://www.instagram.com/api/v1/feed/user/' + userId + '/?count=12'; if (cursor) url += '&max_id=' + encodeURIComponent(cursor); return apiGet(url).then(function (data) { var items = data.items || []; items.forEach(function (item) { var isVideo = item.media_type === 2; var sc = item.code || item.shortcode; var mediaUrl; if (isVideo) { mediaUrl = item.video_url || (item.video_versions && item.video_versions[0] && item.video_versions[0].url); } if (!mediaUrl) { var cands = item.image_versions2 && item.image_versions2.candidates; if (cands && cands[0]) mediaUrl = cands[0].url; } if (mediaUrl) posts.push({ shortcode: sc, type: isVideo ? 'video' : 'photo', url: mediaUrl }); }); setBtn(btnId, lang.fetching + posts.length); cursor = data.next_max_id || null; if (data.more_available && cursor && posts.length < 500) return sleep(800).then(nextPage); return posts; }); } return nextPage(); } // ── CRC-32 ─────────────────────────────────────────────── var CRC_TABLE = (function () { var t = new Uint32Array(256); for (var i = 0; i < 256; i++) { var c = i; for (var j = 0; j < 8; j++) c = (c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1); t[i] = c; } return t; })(); function crc32(u8) { var crc = 0xFFFFFFFF; for (var i = 0; i < u8.length; i++) crc = (crc >>> 8) ^ CRC_TABLE[(crc ^ u8[i]) & 0xFF]; return (crc ^ 0xFFFFFFFF) >>> 0; } // ── Manual ZIP (STORE) ─────────────────────────────────── function buildZip(files) { var enc = new TextEncoder(); var locals = [], central = [], offsets = [], pos = 0; var D = 0x5745, T = 0x0000; for (var fi = 0; fi < files.length; fi++) { var nb=enc.encode(files[fi].name), data=files[fi].data, crc=crc32(data), sz=data.length; var lh=new Uint8Array(30+nb.length), lv=new DataView(lh.buffer); lv.setUint32(0,0x04034b50,true);lv.setUint16(4,20,true);lv.setUint16(6,0,true); lv.setUint16(8,0,true);lv.setUint16(10,T,true);lv.setUint16(12,D,true); lv.setUint32(14,crc,true);lv.setUint32(18,sz,true);lv.setUint32(22,sz,true); lv.setUint16(26,nb.length,true);lv.setUint16(28,0,true);lh.set(nb,30); offsets.push(pos);locals.push(lh,data);pos+=lh.length+data.length; var ce=new Uint8Array(46+nb.length), cv=new DataView(ce.buffer); cv.setUint32(0,0x02014b50,true);cv.setUint16(4,20,true);cv.setUint16(6,20,true); cv.setUint16(8,0,true);cv.setUint16(10,0,true);cv.setUint16(12,T,true);cv.setUint16(14,D,true); cv.setUint32(16,crc,true);cv.setUint32(20,sz,true);cv.setUint32(24,sz,true); cv.setUint16(28,nb.length,true);cv.setUint16(30,0,true);cv.setUint16(32,0,true); cv.setUint16(34,0,true);cv.setUint16(36,0,true);cv.setUint32(38,0,true); cv.setUint32(42,offsets[fi],true);ce.set(nb,46);central.push(ce); } var cdOff=pos, cdSz=central.reduce(function(s,c){return s+c.length;},0); var eocd=new Uint8Array(22), ev=new DataView(eocd.buffer); ev.setUint32(0,0x06054b50,true);ev.setUint16(4,0,true);ev.setUint16(6,0,true); ev.setUint16(8,files.length,true);ev.setUint16(10,files.length,true); ev.setUint32(12,cdSz,true);ev.setUint32(16,cdOff,true);ev.setUint16(20,0,true); var all=locals.concat(central).concat([eocd]); var tot=all.reduce(function(s,a){return s+a.length;},0); var out=new Uint8Array(tot), cur=0; for(var i=0;i=300) return reject(new Error('HTTP '+r.status)); function read(blob){ var fr=new FileReader(); fr.onload=function(){resolve(fr.result.split(',')[1]);}; fr.onerror=function(){reject(new Error('FileReader error'));}; fr.readAsDataURL(blob); } var resp=r.response; if(resp&&typeof resp.then==='function') resp.then(read,reject); else read(resp); }, onerror:function(){reject(new Error('Network Error'));}, ontimeout:function(){reject(new Error('Timeout'));} }); }); } function b64ToU8(b64){ var raw=atob(b64),u8=new Uint8Array(raw.length); for(var i=0;i