Greasy Fork is available in English.
以单个、JSON 或 ZIP 格式高清下载个人资料中的所有媒体(照片、视频、Reels)。
// ==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
// ==/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<all.length;i++){out.set(all[i],cur);cur+=all[i].length;}
return out;
}
function strToU8(str) {
return new TextEncoder().encode(str);
}
// ── UI ───────────────────────────────────────────────────
function buildUI() {
if (document.getElementById('igmt-bar')) return;
var bar = document.createElement('div'); bar.id = 'igmt-bar';
Object.assign(bar.style, {
position: 'fixed', top: '60px', right: '16px', zIndex: '2147483647',
display: 'flex', flexDirection: 'column', alignItems: 'stretch', gap: '5px',
background: 'rgba(15,15,15,0.96)', padding: '8px',
borderRadius: '10px', border: '1px solid #3a3a3a',
backdropFilter: 'blur(6px)', fontFamily: 'sans-serif'
});
[{id:'igmt-media',text:lang.media,bg:'#d62976'},
{id:'igmt-json', text:lang.json, bg:'#0095f6'},
{id:'igmt-zip', text:lang.zip, bg:'#28a745'}
].forEach(function (b) {
var btn = document.createElement('button');
btn.id = b.id; btn.textContent = b.text; btn.dataset.def = b.text;
Object.assign(btn.style, {
padding: '6px 14px', background: b.bg, color: '#fff',
border: 'none', borderRadius: '6px', cursor: 'pointer',
fontSize: '11px', fontWeight: '700', width: '100%',
textAlign: 'center'
});
btn.addEventListener('click', function () { run(b.id); });
bar.appendChild(btn);
});
var prog = document.createElement('div'); prog.id = 'igmt-prog';
Object.assign(prog.style, { height: '3px', background: '#333', borderRadius: '2px', marginTop: '2px', overflow: 'hidden', display: 'none' });
var fill = document.createElement('div'); fill.id = 'igmt-fill';
Object.assign(fill.style, { height: '100%', width: '0%', background: '#0095f6', transition: 'width .3s', borderRadius: '2px' });
prog.appendChild(fill); bar.appendChild(prog);
var st = document.createElement('div'); st.id = 'igmt-status';
Object.assign(st.style, { color: '#666', fontSize: '9px', textAlign: 'center', marginTop: '2px', maxWidth: '100px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' });
bar.appendChild(st);
document.body.appendChild(bar);
}
function setBtn(id,t){var e=document.getElementById(id);if(e)e.textContent=t;}
function setStatus(t){var e=document.getElementById('igmt-status');if(e)e.textContent=t;}
function setProgress(p){
var pg=document.getElementById('igmt-prog'),f=document.getElementById('igmt-fill');
if(!pg||!f)return;
if(p===null){pg.style.display='none';f.style.width='0%';return;}
pg.style.display='block';f.style.width=Math.round(p)+'%';
}
function lockAll(on){
['igmt-media','igmt-json','igmt-zip'].forEach(function(id){
var e=document.getElementById(id);if(!e)return;
e.disabled=on;e.style.opacity=on?'0.5':'1';e.style.cursor=on?'not-allowed':'pointer';
});
}
// ── İndirme ──────────────────────────────────────────────
function fetchBase64(url) {
return new Promise(function(resolve,reject){
GM_xmlhttpRequest({
method:'GET',url:url,responseType:'blob',timeout:30000,
headers:{'Referer':'https://www.instagram.com/','Accept':'image/webp,image/*,video/*,*/*'},
onload:function(r){
if(r.status<200||r.status>=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<raw.length;i++) u8[i]=raw.charCodeAt(i);
return u8;
}
// ── Ana Akış ─────────────────────────────────────────────
async function run(btnId) {
if (window._igmtBusy) return;
window._igmtBusy = true;
lockAll(true); setProgress(0); setStatus('');
var defLabel = document.getElementById(btnId).dataset.def;
var username = window.location.pathname.replace(/\//g,'').trim();
try {
if (!username) throw new Error('Username not found');
setBtn(btnId, lang.user);
var userId = await getUserId(username);
setBtn(btnId, lang.loading);
var posts = await fetchAllPosts(userId, btnId);
if (!posts.length) { toast(lang.noMedia, 'err'); return; }
// JSON modu
if (btnId === 'igmt-json') {
saveAs(new Blob([JSON.stringify(posts,null,2)],{type:'application/json'}), username+'.json');
toast('✓ ' + posts.length + ' ' + lang.done, 'ok');
return;
}
var isZip = btnId === 'igmt-zip';
var zipFiles = [], errors = 0;
var videoTotal = posts.filter(function(p){return p.type==='video';}).length;
var videoHit = 0;
for (var i = 0; i < posts.length; i++) {
var post = posts[i];
var idx = String(i+1).padStart(4,'0');
var isVideo = post.type === 'video';
var ext = isVideo ? 'mp4' : 'jpg';
var mime = isVideo ? 'video/mp4' : 'image/jpeg';
var name = username + '_' + idx + '.' + ext;
if (isVideo) videoHit++;
setBtn(btnId, (i+1)+'/'+posts.length);
setStatus((isVideo?'▶ ':'🖼 ')+name);
setProgress(Math.round(((i+1)/posts.length)*100));
try {
var b64 = await fetchBase64(post.url);
var u8 = b64ToU8(b64);
if (isZip) { zipFiles.push({name:name, data:u8}); }
else { saveAs(new Blob([u8],{type:mime}), name); await sleep(150); }
} catch(e) {
console.warn('[IGMT] Skip ('+(i+1)+'): '+e.message);
errors++;
}
}
if (isZip) {
var jsonU8 = strToU8(JSON.stringify(posts, null, 2));
zipFiles.push({ name: username + '.json', data: jsonU8 });
setBtn(btnId, lang.zipPrep); setStatus(''); setProgress(99);
var zipU8 = buildZip(zipFiles);
saveAs(new Blob([zipU8],{type:'application/zip'}), username+'.zip');
}
var msg = (errors ? '✓ '+(posts.length-errors)+' success ✗ '+errors+' error\n' : '✓ '+posts.length+' ' + lang.done + '\n')
+ '📹 '+videoHit+'/'+videoTotal+' video';
toast(msg, errors ? 'err' : 'ok');
} catch(err) {
console.error('[IGMT] Error:',err);
toast('✗ ' + err.message + '\n' + lang.session, 'err');
} finally {
setBtn(btnId,defLabel); setStatus(''); setProgress(null);
lockAll(false); window._igmtBusy = false;
}
}
function sleep(ms){return new Promise(function(r){setTimeout(r,ms);});}
setTimeout(buildUI, 1000);
})();