/** * Instagram Downloader By: Fastdl.app * Base : https://fastdl.app/ * Author : Gienetic * Fitur : Download Video IG, Reels, Foto, IGTV & korsel IG */ import { gotScraping } from "got-scraping"; import crypto from "crypto"; const KUNCI = '792525efde6d921d6055a5d62dcebd39c8b5364e99fa87c5adf0e89391266d9c'; const HOST = 'fastdl.app'; const API = `https://api-wh.${HOST}/api/convert`; const DATA = { _ts: 1773148641059, _tsc: 0, _sv: 2 }; const saring = (url) => { let u = url.trim(); if (!u.includes("www.instagram.com") && !u.includes("instagr.am")) { u = u.replace("instagram.com", "www.instagram.com"); } return u; }; const tandai = (teks) => { const ts = Date.now(); const k = Buffer.from(KUNCI, 'hex'); const h = crypto.createHmac('sha256', k); h.update(teks + String(ts)); return { ts, _s: h.digest('hex') }; }; const urai = (xml) => { const v = []; const a = []; const blok = xml.match(/]*>[\s\S]*?<\/Representation>/g) || []; for (const b of blok) { const mime = b.match(/mimeType="([^"]+)"/)?.[1] || ''; const bw = b.match(/bandwidth="(\d+)"/)?.[1]; const w = b.match(/bandwidth="\d+"[^>]*width="(\d+)"/)?.[1] || b.match(/width="(\d+)"/)?.[1]; const h = b.match(/height="(\d+)"/)?.[1]; const ql = b.match(/FBQualityLabel="([^"]+)"/)?.[1]; const url = b.match(/([^<]+)<\/BaseURL>/)?.[1]; if (!url || !bw) continue; const isi = { bandwidth: parseInt(bw), url: 'https://' + url.replace(/^https?:\/\//, '') }; if (mime.startsWith('video/')) { isi.width = parseInt(w); isi.height = parseInt(h); isi.label = ql || (w ? w + 'p' : null); v.push(isi); } else if (mime.startsWith('audio/')) { isi.rate = b.match(/audioSamplingRate="(\d+)"/)?.[1] ? parseInt(b.match(/audioSamplingRate="(\d+)"/)?.[1]) : null; a.push(isi); } } return { v, a }; }; export async function ambil(input) { const link = saring(input); const { ts, _s } = tandai(link); const muatan = `sf_url=${encodeURIComponent(link)}&ts=${ts}&_ts=${DATA._ts}&_tsc=${DATA._tsc}&_sv=${DATA._sv}&_s=${_s}`; const hasil = await gotScraping.post(API, { headers: { 'Accept': 'application/json, text/plain, */*', 'Origin': `https://${HOST}`, 'Referer': `https://${HOST}/`, 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 (Gienetic)', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' }, body: muatan }).json(); if (hasil?.invalid_request) throw new Error("Format url tidak valid"); if (!hasil || (!hasil.url && !hasil.meta)) throw new Error("Konten tidak ditemukan"); const m = hasil.meta || {}; const t = hasil.thumb || null; const list = []; for (const i of (hasil.url || [])) { const ext = (i.ext || i.type || "mp4").replace(/[^a-zA-Z0-9]/g, ''); const isV = /mp4|mov|mkv|webm|gif/i.test(ext); const num = i.slide_number || 1; let s = list.find(x => x.slide === num); if (!s) { s = { slide: num, jenis: isV ? 'video' : 'image', format: ext, daftar: [] }; list.push(s); } s.daftar.push({ label: i.quality || i.subname || "unknown", url: i.url, sumber: 'direct' }); } if (m.dash_manifest) { const p = urai(m.dash_manifest); if (list.length === 0) list.push({ slide: 1, jenis: 'video', format: 'mp4', daftar: [] }); for (const v of p.v) { if (!list[0].daftar.some(q => q.height === v.height)) { list[0].daftar.push({ label: v.label, width: v.width, height: v.height, url: v.url, sumber: 'dash' }); } } } return { info: { id: m.shortcode || null, user: m.username || null, judul: m.title || null, durasi: m.duration || null, like: m.like_count || 0, komen: m.comment_count || 0, thumb: t, waktu: m.taken_at ? new Date(m.taken_at * 1000).toISOString() : null }, media: list, audio: m.dash_manifest ? urai(m.dash_manifest).a : [] }; } const arg = process.argv[2]; if (arg) { ambil(arg) .then(r => console.log(JSON.stringify(r, null, 2))) .catch(e => console.error(JSON.stringify({ error: e.message }, null, 2))); } // node fastdl.js "https://www.instagram.com/reel/DZeY_j7vS9O/"