Instagram Downloader By: Fastdl.app
No comments yet. Be the first to comment!
1/**
2 * Instagram Downloader By: Fastdl.app
3 * Base : https://fastdl.app/
4 * Author : Gienetic
5 * Fitur : Download Video IG, Reels, Foto, IGTV & korsel IG
6 */
7
8
9import { gotScraping } from "got-scraping";
10import crypto from "crypto";
11
12const KUNCI = '792525efde6d921d6055a5d62dcebd39c8b5364e99fa87c5adf0e89391266d9c';
13const HOST = 'fastdl.app';
14const API = `https://api-wh.${HOST}/api/convert`;
15const DATA = { _ts: 1773148641059, _tsc: 0, _sv: 2 };
16
17const saring = (url) => {
18 let u = url.trim();
19 if (!u.includes("www.instagram.com") && !u.includes("instagr.am")) {
20 u = u.replace("instagram.com", "www.instagram.com");
21 }
22 return u;
23};
24
25const tandai = (teks) => {
26 const ts = Date.now();
27 const k = Buffer.from(KUNCI, 'hex');
28 const h = crypto.createHmac('sha256', k);
29 h.update(teks + String(ts));
30 return { ts, _s: h.digest('hex') };
31};
32
33const urai = (xml) => {
34 const v = [];
35 const a = [];
36 const blok = xml.match(/<Representation[^>]*>[\s\S]*?<\/Representation>/g) || [];
37 for (const b of blok) {
38 const mime = b.match(/mimeType="([^"]+)"/)?.[1] || '';
39 const bw = b.match(/bandwidth="(\d+)"/)?.[1];
40 const w = b.match(/bandwidth="\d+"[^>]*width="(\d+)"/)?.[1] || b.match(/width="(\d+)"/)?.[1];
41 const h = b.match(/height="(\d+)"/)?.[1];
42 const ql = b.match(/FBQualityLabel="([^"]+)"/)?.[1];
43 const url = b.match(/<BaseURL>([^<]+)<\/BaseURL>/)?.[1];
44 if (!url || !bw) continue;
45 const isi = { bandwidth: parseInt(bw), url: 'https://' + url.replace(/^https?:\/\//, '') };
46 if (mime.startsWith('video/')) {
47 isi.width = parseInt(w);
48 isi.height = parseInt(h);
49 isi.label = ql || (w ? w + 'p' : null);
50 v.push(isi);
51 } else if (mime.startsWith('audio/')) {
52 isi.rate = b.match(/audioSamplingRate="(\d+)"/)?.[1] ? parseInt(b.match(/audioSamplingRate="(\d+)"/)?.[1]) : null;
53 a.push(isi);
54 }
55 }
56 return { v, a };
57};
58
59export async function ambil(input) {
60 const link = saring(input);
61 const { ts, _s } = tandai(link);
62 const muatan = `sf_url=${encodeURIComponent(link)}&ts=${ts}&_ts=${DATA._ts}&_tsc=${DATA._tsc}&_sv=${DATA._sv}&_s=${_s}`;
63
64 const hasil = await gotScraping.post(API, {
65 headers: {
66 'Accept': 'application/json, text/plain, */*',
67 'Origin': `https://${HOST}`,
68 'Referer': `https://${HOST}/`,
69 '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)',
70 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
71 },
72 body: muatan
73 }).json();
74
75 if (hasil?.invalid_request) throw new Error("Format url tidak valid");
76 if (!hasil || (!hasil.url && !hasil.meta)) throw new Error("Konten tidak ditemukan");
77
78 const m = hasil.meta || {};
79 const t = hasil.thumb || null;
80 const list = [];
81
82 for (const i of (hasil.url || [])) {
83 const ext = (i.ext || i.type || "mp4").replace(/[^a-zA-Z0-9]/g, '');
84 const isV = /mp4|mov|mkv|webm|gif/i.test(ext);
85 const num = i.slide_number || 1;
86 let s = list.find(x => x.slide === num);
87 if (!s) {
88 s = { slide: num, jenis: isV ? 'video' : 'image', format: ext, daftar: [] };
89 list.push(s);
90 }
91 s.daftar.push({ label: i.quality || i.subname || "unknown", url: i.url, sumber: 'direct' });
92 }
93
94 if (m.dash_manifest) {
95 const p = urai(m.dash_manifest);
96 if (list.length === 0) list.push({ slide: 1, jenis: 'video', format: 'mp4', daftar: [] });
97 for (const v of p.v) {
98 if (!list[0].daftar.some(q => q.height === v.height)) {
99 list[0].daftar.push({ label: v.label, width: v.width, height: v.height, url: v.url, sumber: 'dash' });
100 }
101 }
102 }
103
104 return {
105 info: {
106 id: m.shortcode || null,
107 user: m.username || null,
108 judul: m.title || null,
109 durasi: m.duration || null,
110 like: m.like_count || 0,
111 komen: m.comment_count || 0,
112 thumb: t,
113 waktu: m.taken_at ? new Date(m.taken_at * 1000).toISOString() : null
114 },
115 media: list,
116 audio: m.dash_manifest ? urai(m.dash_manifest).a : []
117 };
118}
119
120const arg = process.argv[2];
121if (arg) {
122 ambil(arg)
123 .then(r => console.log(JSON.stringify(r, null, 2)))
124 .catch(e => console.error(JSON.stringify({ error: e.message }, null, 2)));
125}
126
127// node fastdl.js "https://www.instagram.com/reel/DZeY_j7vS9O/"