├── config.json ├── package.json ├── lib └── ig.js ├── README.md └── index.js /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "X-Ig-App-Id": "936619743392459", 3 | "ds_user_id": "", 4 | "sessionid": "" 5 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "colors": "^1.4.0", 4 | "node-fetch": "^2.7.0", 5 | "readline-sync": "^1.4.10" 6 | }, 7 | "name": "igstory", 8 | "version": "1.1.1", 9 | "description": "Downloader story from instagram", 10 | "main": "index.js", 11 | "directories": { 12 | "lib": "lib" 13 | }, 14 | "devDependencies": {}, 15 | "scripts": { 16 | "start": "node index.js", 17 | "test": "node index.js" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "github.com/bintang73/igstory" 22 | }, 23 | "keywords": [ 24 | "igstory" 25 | ], 26 | "author": "bintang73", 27 | "license": "ISC" 28 | } 29 | -------------------------------------------------------------------------------- /lib/ig.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | 3 | class InstagramScraper { 4 | constructor(appId, userId, sessionId) { 5 | this.headers = { 6 | accept: '*/*', 7 | 'content-type': 'application/x-www-form-urlencoded', 8 | 'sec-fetch-site': 'same-site', 9 | 'x-ig-app-id': appId, 10 | cookie: `ds_user_id=${userId}; sessionid=${sessionId};`, 11 | }; 12 | this.instagramApiBaseUrl = 'https://i.instagram.com/api/v1'; 13 | } 14 | 15 | async getUserID(username) { 16 | try { 17 | const response = await fetch(this.instagramApiBaseUrl + '/users/web_profile_info/?username=' + username, { headers: this.headers }); 18 | const json = await response.json(); 19 | if (json.status === 'ok') { 20 | return json.data.user.id; 21 | } else { 22 | console.log(`[+] Failed to get User-ID for ${username}`); 23 | return 0; 24 | } 25 | } catch (error) { 26 | console.log(`[+] Error in loading user-id from ${username}. Maybe the user doesn't exist!`); 27 | return 0; 28 | } 29 | } 30 | 31 | async getStory(userID) { 32 | try { 33 | const response = await fetch(`https://www.instagram.com/api/v1/feed/reels_media/?reel_ids=${userID}`, { headers: this.headers }); 34 | return await response.json(); 35 | } catch (error) { 36 | console.log(`[+] Error in fetching story for user with ID ${userID}`); 37 | throw error; 38 | } 39 | } 40 | } 41 | 42 | module.exports = InstagramScraper; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # igstory 2 | Download public and private ig stories anonymously 3 | 4 | ## INSTALL FOR TERMUX/UBUNTU/SSH USER 5 | 6 | ```bash 7 | apt update && apt upgrade 8 | apt install git -y 9 | apt install nodejs -y 10 | git clone https://github.com/Bintang73/igstory 11 | cd igstoy 12 | npm install 13 | npm start 14 | ``` 15 | 16 | ## INSTALL FOR WINDOWS/VPS/RDP USER 17 | 18 | * Download And Install Git [`Click Here`](https://git-scm.com/downloads) 19 | * Download And Install NodeJS [`Click Here`](https://nodejs.org/en/download) 20 | 21 | ```bash 22 | git clone https://github.com/Bintang73/igstory 23 | cd igstory 24 | npm install 25 | npm start 26 | ``` 27 | 28 | --------- 29 | 30 | ## HOW TO GET COOKIE AND SET TO CONFIG.JSON? 31 | * Go to Instagram website (login via pc) [`Click Here`](https://instagram.com) 32 | * Login with your account instagram 33 | * Right click on the mouse and select inspect like image bellow 34 | ![3](https://github.com/Bintang73/igstory/assets/42708989/100550ac-26c8-467d-bcab-fbcfd03a2a91) 35 | 36 | * Refresh the browser 37 | * Search for "graphql" in the search field below 38 | ![4](https://github.com/Bintang73/igstory/assets/42708989/71135258-65cc-4dd0-850a-1426ee087631) 39 | * Click on the one "graphql" 40 | * Scroll down and find the "X-Ig-App-Id", copy the value and paste on config.json file 41 | ![5](https://github.com/Bintang73/igstory/assets/42708989/1b95367d-36c1-48d7-b82a-a785428e5a2d) 42 | * Scroll up until cookie form, find the "ds_user_id" and "sessionid" copy value between "=" and ";" and paste on config.json file 43 | ![6](https://github.com/Bintang73/igstory/assets/42708989/aaf4ceb0-ed8c-4ebc-9dcc-0fccca90ba9d) 44 | * Save file config.json 45 | * And run the file "npm start" 46 | 47 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const fs = require('fs'); 3 | const colors = require("colors"); 4 | const readline = require("readline-sync"); 5 | const InstagramScraper = require('./lib/ig'); 6 | const config = JSON.parse(fs.readFileSync("config.json", "utf8")); 7 | const instagramScraper = new InstagramScraper(config["X-Ig-App-Id"], config["ds_user_id"], config["sessionid"]); 8 | 9 | (async () => { 10 | const date = () => new Date().toLocaleTimeString({ 11 | timeZone: "Asia/Jakarta", 12 | }); 13 | 14 | const namaig = readline.question("[+] Instagram Username: "); 15 | 16 | const userID = await instagramScraper.getUserID(namaig); 17 | 18 | if (userID !== 0) { 19 | try { 20 | const elements = []; 21 | const storyJson = await instagramScraper.getStory(userID); 22 | 23 | if (storyJson.reels_media[0]?.items) { 24 | storyJson.reels_media[0].items.forEach(item => { 25 | delete item.url; 26 | delete item.video_dash_manifest; 27 | if (item.video_versions) { 28 | elements.push({ 29 | type: 'video', 30 | data: item.video_versions[0] 31 | }); 32 | } else { 33 | elements.push({ 34 | type: 'image', 35 | data: item.image_versions2.candidates[0] 36 | }); 37 | } 38 | }); 39 | } 40 | if (elements.length > 0) { 41 | try { 42 | const foldername = './temp/story/' + namaig 43 | if (!fs.existsSync(foldername)) { 44 | fs.mkdirSync(foldername, { recursive: true }); 45 | } 46 | console.log(`[+] [${date()}] ${colors.yellow(`Start Downloading story from ${namaig}...`)}`); 47 | let i = 0; 48 | for (let x of elements) { 49 | const currentTime = new Date(); 50 | const datenow = currentTime.toLocaleDateString().replace(/\//g, '-'); 51 | const time = `${currentTime.getHours()}-${currentTime.getMinutes()}-${currentTime.getSeconds()}-${currentTime.getMilliseconds()}`; 52 | const rnd = Math.floor(Math.random() * (9999 - 1111 + 1)) + 1111; 53 | const filePath = `./${foldername}/${datenow}-${time}-${rnd}`; 54 | 55 | if (x.type === 'video') { 56 | fetch(x.data.url) 57 | .then(response => response.buffer()) 58 | .then(buffer => { 59 | i++ 60 | console.log(`[+] [${date()}] ${colors.green(`Downloading story ${colors.yellow('video')} from ${colors.cyan(namaig)} ${i} of ${elements.length}`)}`); 61 | fs.writeFileSync(`${filePath}.mp4`, buffer); 62 | }) 63 | .catch(error => { 64 | console.log(`[+] [${date()}] ${colors.red(`Error fetching video content: ${error}`)}`); 65 | }); 66 | } else { 67 | fetch(x.data.url) 68 | .then(response => response.buffer()) 69 | .then(buffer => { 70 | i++ 71 | console.log(`[+] [${date()}] ${colors.green(`Downloading story ${colors.yellow('image')} from ${colors.cyan(namaig)} ${i} of ${elements.length}`)}`); 72 | fs.writeFileSync(`${filePath}.jpg`, buffer); 73 | }) 74 | .catch(error => { 75 | console.log(`[+] [${date()}] ${colors.red(`Error fetching video content: ${error}`)}`); 76 | }); 77 | } 78 | } 79 | } catch (err) { 80 | console.log(`[+] [${date()}] ${colors.red(`Error creating/checking folder: ${err}`)}`); 81 | } 82 | 83 | } else { 84 | console.log(`[+] [${date()}] ${colors.red(`Username of ${colors.yellow(namaig)} its not found or not have story or account its private.`)}`); 85 | } 86 | } catch (e) { 87 | console.log(`[+] [${date()}] ${colors.red(`Cookie its not valid, please check again your config.json file.`)}`); 88 | } 89 | } 90 | })() --------------------------------------------------------------------------------