/** * Stalker Instagram * Source: https://igwatcher.com/ * * Ngambil Info Akun Instagram Reels, Postingan, Story * Khusus Akun Instagram Public No Privat */ /** * Credit By Zx * Sumber Kode: https://whatsapp.com/channel/0029VbDLqe7EquiSF4STU13o * Note: Kalau Mau Di sher Lagi Minimal Credit atau sumber jangan di hapus dong * Website React WhatsApp Gratis: * https://react.v1.zfile.web.id/ */ /** Yang Mau Beli Akun Netflix, Top-Up game, Sunt1k S0Smed Bisa Ke Zix Store. https://zixstore.kiospremium.site/ Terimakasih 😍👀 */ const https = require('https'); const crypto = require('crypto'); const zlib = require('zlib'); const BASE = 'https://igwatcher.com'; const UA = 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/154.0.0.0 Mobile Safari/537.36'; const SIG_JS_VERSION = 478; let IGW_PT = ''; function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } function normalizeUsername(raw) { let s = String(raw || '').trim(); try { if (/^https?:\/\//i.test(s)) { const u = new URL(s); if ((u.hostname || '').includes('instagram.com')) { const parts = u.pathname.replace(/^\/+|\/+$/g, '').split('/'); if (parts[0] && parts[0].toLowerCase() === 'stories') { s = parts[1] || ''; } else { s = parts[0] || ''; } } } } catch (err) { } if (s.startsWith('@')) s = s.slice(1); s = s.toLowerCase().replace(/\/+$/g, ''); if (!/^[a-z0-9._]{1,30}$/.test(s) || /^[._]+$/.test(s)) { throw new Error('Username tidak valid: ' + raw); } return s; } function canonicalize(urlObj) { const ps = []; for (const [k, v] of urlObj.searchParams.entries()) { ps.push([k, v]); } ps.sort(function (a, b) { if (a[0] === b[0]) { if (a[1] < b[1]) return -1; if (a[1] > b[1]) return 1; return 0; } if (a[0] < b[0]) return -1; if (a[0] > b[0]) return 1; return 0; }); const query = ps .map((p) => { return encodeURIComponent(p[0]) + '=' + encodeURIComponent(p[1]); }) .join('&'); return urlObj.pathname + '?' + query; } function buildSignature(urlObj) { if (!IGW_PT) { throw new Error('IGW_PT belum di-set. Jalankan initToken() dulu.'); } const ts = String(Date.now()); const canon = canonicalize(urlObj); const payload = IGW_PT + '\n' + ts + '\n' + canon; const s = crypto .createHash('sha256') .update(payload, 'utf8') .digest('hex'); return `v=1;j=${SIG_JS_VERSION};t=${ts};p=${IGW_PT};s=${s}`; } function httpRequest(url, options, redirectCount) { options = options || {}; redirectCount = redirectCount || 0; return new Promise((resolve, reject) => { let parsed; try { parsed = new URL(url); } catch (err) { reject(new Error('URL tidak valid: ' + url)); return; } const headers = Object.assign( { 'User-Agent': UA, 'Accept': '*/*', 'Accept-Language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7', 'Accept-Encoding': 'identity', 'Referer': BASE + '/', }, options.headers || {} ); const reqOptions = { protocol: parsed.protocol || 'https:', hostname: parsed.hostname, port: parsed.port || 443, path: parsed.pathname + parsed.search, method: options.method || 'GET', headers: headers, }; const req = https.request(reqOptions, function (res) { if ( [301, 302, 303, 307, 308].includes(res.statusCode) && res.headers.location && redirectCount < 5 ) { res.resume(); const nextUrl = new URL(res.headers.location, url).toString(); resolve(httpRequest(nextUrl, options, redirectCount + 1)); return; } const chunks = []; res.on('data', function (chunk) { chunks.push(chunk); }); res.on('end', function () { let buf = Buffer.concat(chunks); const encoding = String( res.headers['content-encoding'] || '' ).toLowerCase(); try { if (buf.length > 0) { if (encoding.includes('gzip')) { buf = zlib.gunzipSync(buf); } else if (encoding.includes('br')) { buf = zlib.brotliDecompressSync(buf); } else if (encoding.includes('deflate')) { try { buf = zlib.inflateSync(buf); } catch (err) { buf = zlib.inflateRawSync(buf); } } else if (encoding.includes('zstd')) { reject( new Error( 'Response memakai zstd. Node bawaan belum tentu bisa decode zstd. Coba jalankan di Node versi lebih baru atau gunakan library HTTP lain.' ) ); return; } } } catch (err) { reject(new Error('Gagal decode response: ' + err.message)); return; } resolve({ statusCode: res.statusCode, headers: res.headers, body: buf.toString('utf8'), }); }); }); req.on('error', function (err) { reject(err); }); req.setTimeout(60000, function () { req.destroy(new Error('Request timeout 60 detik')); }); if (options.body) { req.write(options.body); } req.end(); }); } async function initToken(force) { if (IGW_PT && !force) return IGW_PT; const res = await httpRequest(BASE + '/', { headers: { Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', }, }); if (res.statusCode !== 200) { throw new Error('Gagal membuka homepage igwatcher.com: HTTP ' + res.statusCode); } const m = res.body.match(/data-igw-pt\s*=\s*"([^"]+)"/i); if (!m || !m[1]) { throw new Error('data-igw-pt tidak ditemukan di HTML homepage.'); } const pt = m[1]; // /^1\.\d{9,11}\.[0-9a-f]{32}$/ if (!/^1\.\d{9,11}\.[0-9a-f]{32}$/.test(pt)) { throw new Error('Format data-igw-pt tidak dikenali: ' + pt); } IGW_PT = pt; return IGW_PT; } async function apiGet(pathname, params) { await initToken(false); const url = new URL(pathname, BASE); const keys = Object.keys(params || {}).sort(); for (const key of keys) { const val = params[key]; if (val === undefined || val === null) continue; url.searchParams.append(key, String(val)); } const sig = buildSignature(url); const res = await httpRequest(url.toString(), { headers: { 'X-IGW-Sig': sig, 'X-IGW-TS': 'e=timeout', Accept: 'application/json, text/plain, */*', }, }); let json = null; try { json = JSON.parse(res.body); } catch (err) { json = null; } if (res.statusCode !== 200) { let msg = 'HTTP ' + res.statusCode; if (json && json.message) { msg += ' | ' + json.message; } else if (json && json.note) { msg += ' | ' + json.note; } else { msg += ' | ' + res.body.slice(0, 300); } throw new Error(msg); } if (!json) { throw new Error( 'Response bukan JSON dari ' + pathname + ': ' + res.body.slice(0, 300) ); } if (json.status && json.status !== 'success') { throw new Error( 'API error: ' + (json.message || json.note || JSON.stringify(json).slice(0, 300)) ); } return json; } function getItems(resp) { if (!resp) return []; return resp.data || resp.items || resp.reels || []; } async function stalkerig(username) { username = normalizeUsername(username); await initToken(false); const errors = []; async function safeCall(type, fn) { try { return await fn(); } catch (err) { errors.push({ type: type, message: err.message, }); return null; } } const search = await safeCall('search', function () { return apiGet('/wp-json/igw/v1/search', { username: username, }); }); if (!search) { const errMsg = errors.find((e) => e.type === 'search')?.message || 'Gagal mengambil data profil.'; throw new Error(errMsg); } const user = search && search.data && search.data.user ? search.data.user : null; if (!user || !user.username) { throw new Error( 'Profil tidak ditemukan atau unavailable. note=' + (search.note || 'unknown') ); } const result = { username: user.username || username, full_name: user.full_name || '', is_private: Boolean(user.is_private), is_verified: Boolean(user.is_verified), biography: user.biography || '', external_url: user.external_url || '', profile_pic_url: user.profile_pic_url || '', followers: user.follower_count != null ? user.follower_count : user.edge_followed_by && user.edge_followed_by.count != null ? user.edge_followed_by.count : null, following: user.following_count != null ? user.following_count : user.edge_follow && user.edge_follow.count != null ? user.edge_follow.count : null, posts_count: user.edge_owner_to_timeline_media && user.edge_owner_to_timeline_media.count != null ? user.edge_owner_to_timeline_media.count : null, latest_reel_media: user.latest_reel_media || null, scraped_at: new Date().toISOString(), media: { stories: [], reels: [], posts: [], highlights: [], tagged: [], }, meta: { stories_total: null, reels_total: null, posts_total: null, highlights_total: null, tagged_total: null, posts_has_more: false, reels_has_more: false, tagged_has_more: false, }, profile_raw: user, errors: errors, }; if (result.is_private) { result.errors.push({ type: 'private', message: 'Akun private. Media tidak diambil.', }); return result; } await sleep(1200); const stories = await safeCall('stories', function () { return apiGet('/wp-json/igw/v1/stories', { username: username, }); }); if (stories) { result.media.stories = getItems(stories); result.meta.stories_total = stories.total != null ? stories.total : result.media.stories.length; } await sleep(1200); const reels = await safeCall('reels', function () { return apiGet('/api/reels', { username: username, limit: 24, lazy: 1, }); }); if (reels) { result.media.reels = getItems(reels); result.meta.reels_total = reels.total != null ? reels.total : result.media.reels.length; result.meta.reels_has_more = Boolean(reels.has_more); } await sleep(1200); const posts = await safeCall('posts', function () { return apiGet('/wp-json/igw/v1/posts', { username: username, limit: 24, lazy: 1, }); }); if (posts) { result.media.posts = getItems(posts); result.meta.posts_total = posts.total != null ? posts.total : result.media.posts.length; result.meta.posts_has_more = Boolean(posts.has_more); } await sleep(1200); const highlights = await safeCall('highlights', function () { return apiGet('/wp-json/igw/v1/highlights', { username: username, }); }); if (highlights) { result.media.highlights = getItems(highlights); result.meta.highlights_total = highlights.total != null ? highlights.total : result.media.highlights.length; } await sleep(1200); const tagged = await safeCall('tagged', function () { return apiGet('/wp-json/igw/v1/tagged', { username: username, limit: 24, }); }); if (tagged) { result.media.tagged = getItems(tagged); result.meta.tagged_total = tagged.total != null ? tagged.total : result.media.tagged.length; result.meta.tagged_has_more = Boolean(tagged.has_more); } return result; } module.exports = stalkerig; module.exports.stalkerig = stalkerig; /** * CLI: * node index.js username */ /** if (require.main === module) { const username = process.argv[2]; if (!username) { console.error('Usage: node index.js '); console.error('Example: node index.js iniipasya__'); process.exit(1); } stalkerig(username) .then((data) => { console.log(JSON.stringify(data, null, 2)); }) .catch((err) => { console.error('ERROR:', err.message); process.exit(1); }); } **/