├── .gitignore ├── .env.example ├── fonts └── instagram.otf ├── icon ├── instagram_128.png ├── instagram_16.png ├── instagram_256.png ├── instagram_32.png └── instagram_64.png ├── composer.json ├── js ├── main.js └── script.js ├── test.php ├── css └── styles.css ├── .github └── dependabot.yml ├── proxy.php ├── Instagram ├── Uri.php ├── Login.php └── InstagramAPI.php ├── sw.js ├── manifest.json ├── ReadMe.md ├── index.php ├── instagram.php └── image └── instagram.svg /.gitignore: -------------------------------------------------------------------------------- 1 | cookies.txt 2 | vendor/ 3 | composer.lock 4 | .env -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | PROXY_HOST="" 2 | PROXY_PORT="" 3 | username="" 4 | password="" -------------------------------------------------------------------------------- /fonts/instagram.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Incognito-Coder/Instagram-Tools/HEAD/fonts/instagram.otf -------------------------------------------------------------------------------- /icon/instagram_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Incognito-Coder/Instagram-Tools/HEAD/icon/instagram_128.png -------------------------------------------------------------------------------- /icon/instagram_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Incognito-Coder/Instagram-Tools/HEAD/icon/instagram_16.png -------------------------------------------------------------------------------- /icon/instagram_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Incognito-Coder/Instagram-Tools/HEAD/icon/instagram_256.png -------------------------------------------------------------------------------- /icon/instagram_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Incognito-Coder/Instagram-Tools/HEAD/icon/instagram_32.png -------------------------------------------------------------------------------- /icon/instagram_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Incognito-Coder/Instagram-Tools/HEAD/icon/instagram_64.png -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "guzzlehttp/guzzle": "^7.9.2", 4 | "vlucas/phpdotenv": "^5.6" 5 | }, 6 | "autoload": { 7 | "psr-4": { 8 | "InstagramPHP\\": "Instagram/" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | window.addEventListener('load', () => { 2 | if ('serviceWorker' in navigator) { 3 | navigator.serviceWorker.register('/sw.js', { scope: '/' }) 4 | .then(reg => { 5 | 6 | reg.update(); 7 | 8 | }).catch(err => console.log('SW registration FAIL:', err)); 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /test.php: -------------------------------------------------------------------------------- 1 | safeLoad(); 9 | 10 | if (file_exists('cookies.txt')) { 11 | unlink('cookies.txt'); 12 | } 13 | //$session = new InstagramPHPLogin(new Client(), 'user', 'pass'); 14 | $session = new InstagramPHPLogin(new Client(), $_ENV['username'], $_ENV['password']); 15 | $session->SessionLogin(); 16 | -------------------------------------------------------------------------------- /css/styles.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: Instagram; 3 | src: url("../fonts/instagram.otf") format("opentype"); 4 | } 5 | .gradient-custom { 6 | /* fallback for old browsers */ 7 | background: #e27228; 8 | /* Chrome 10-25, Safari 5.1-6 */ 9 | background: -webkit-linear-gradient(to right, rgba(226, 114, 40, 1), rgba(231, 35, 129, 1)); 10 | /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ 11 | background: linear-gradient(to right, rgba(226, 114, 40, 1), rgba(231, 35, 129, 1)) 12 | } -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "composer" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /proxy.php: -------------------------------------------------------------------------------- 1 | 'temp/' . ExtractFileName($file)]); 18 | } 19 | 20 | MediaProxy($media); 21 | -------------------------------------------------------------------------------- /Instagram/Uri.php: -------------------------------------------------------------------------------- 1 | { 12 | 13 | self.skipWaiting(); 14 | 15 | e.waitUntil( 16 | caches.open(cacheName).then(cache => { 17 | return cache.addAll(includeToCache); 18 | }) 19 | ); 20 | }); 21 | 22 | /* Serve cached content when offline */ 23 | self.addEventListener('fetch', e => { 24 | e.respondWith( 25 | caches.match(e.request).then(response => { 26 | return response || fetch(e.request); 27 | }) 28 | ); 29 | }); 30 | 31 | self.addEventListener('activate', event => { 32 | // delete any caches that aren't in cacheName 33 | // which will get rid of version 34 | event.waitUntil( 35 | caches.keys().then(keys => Promise.all( 36 | keys.map(key => { 37 | if (cacheName !== key) { 38 | return caches.delete(key); 39 | } 40 | }) 41 | )).then(() => { 42 | console.log(cacheName + ' now ready to handle fetches!'); 43 | }) 44 | ); 45 | }); 46 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "insta down", 3 | "short_name": "IGT", 4 | "start_url": "/", 5 | "background_color": "#6777ef", 6 | "description": "دانلود از اینستا", 7 | "display": "fullscreen", 8 | "theme_color": "#6777ef", 9 | "icons": [ 10 | { 11 | "src": "icon/instagram_16.png", 12 | "sizes": "16x16", 13 | "type": "image/png", 14 | "purpose": "any" 15 | }, 16 | { 17 | "src": "icon/instagram_32.png", 18 | "sizes": "32x32", 19 | "type": "image/png", 20 | "purpose": "any" 21 | }, 22 | { 23 | "src": "icon/instagram_64.png", 24 | "sizes": "64x64", 25 | "type": "image/png", 26 | "purpose": "any" 27 | }, 28 | { 29 | "src": "icon/instagram_128.png", 30 | "sizes": "128x128", 31 | "type": "image/png", 32 | "purpose": "any" 33 | }, 34 | { 35 | "src": "icon/instagram_256.png", 36 | "sizes": "256x256", 37 | "type": "image/png", 38 | "purpose": "any" 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | # Instagram Basic Tools 2 | Little php class for Instagram Scrapping.\ 3 | Telegram Bot Demo [@InstaTakerBot](https://t.me/InstaTakerBot) \ 4 | **Note** : \ 5 | _Don't forgot to set your own Coockie in Script._ [ **Deprecated** ] 6 | 7 | ```php 8 | $_COOKIE = ''; 9 | ``` 10 | ### Great News 11 | Since version 3.0 release you don't need to manually set cookies data, just login or run test.php file 12 | ```php 13 | SessionLogin(); 21 | ``` 22 | In version 4.0 you can set variables in `.env` file instead of php source code. \ 23 | Here is your environment variable table: 24 | 25 | | Variable | Example Value | Description | 26 | | ---------- | ------------- | --------------------- | 27 | | PROXY_HOST | 127.0.0.1 | Proxy server hostname | 28 | | PROXY_PORT | 8080 | Proxy server port | 29 | | username | your_username | Instagram username | 30 | | password | your_password | Instagram password | 31 | ## Local Deploy 32 | First install [composer](https://getcomposer.org/) on your system,then run: 33 | ```bash 34 | composer install 35 | ``` 36 | ```bash 37 | cd Instagram-Tools && php -S localhost:8000 38 | ``` 39 | then open http://localhost:8000/ in browser,now you can use PWA in your local webserver. 40 | ## Main Features : 41 | * Return Account Info (Profile) 42 | * Download Media 43 | * Download Highlights 44 | * Download Reels 45 | * Download Story 46 | # Changes 47 | 48 |
49 | Click to see changelogs. 50 | 51 | ### v2.2 52 | * Now is be PWA 53 | ### v2.5 54 | * Sadly instagram fully closed previous ( **__a=1** ) method, so i used a newer one. 55 | ### v3.0 56 | * Completely object oriented 57 | * Codes rewrited from scratch 58 | * All requests are now handled over Guzzle 59 | * Fixed Highlight detection 60 | ### v3.2 61 | * Now PWA can play carousel photos and videos 62 | * some javascript bugs fixed 63 | ### v3.5 64 | Note: *this is final build for 2023* 65 | * Changed UserAgent somewhere 66 | * Fixed login CSRF data 67 | * Updated login ajax url 68 | * New regex pattern for getting **media id** 69 | * Bumped guzzle version to 7.8.1 70 | ### v3.6 71 | * Fixed story scapping 72 | * Some changes in Highlights regex pattern 73 | ### v3.7 74 | * Returning post play count 75 | * Bumped guzzle version to 7.9.2 76 | ### v3.8 77 | * Fix of regex in getReelsID func 78 | * Updated UserAgents 79 | ### v3.9 80 | * Update Instagram android useragent 81 | ### v4.0 82 | * Add proxy support and environment configuration for Instagram API 83 | * Some code improvments. 84 |
85 | 86 | ## Credits 87 | Developer : Incognito Coder & Arash Ariaye \ 88 | if you enjoy my content, consider to buy me a coffee here: 89 | 1. Donate [ZarinPal](https://zarinp.al/@incognito) 90 | 2. USDT(**TRC20**) : `TD5XNhZPuVoc6ZnadbrQenuur3WWKwkFqV` 91 | 3. TRON(**TRX**) : `TD5XNhZPuVoc6ZnadbrQenuur3WWKwkFqV` 92 | 4. TON(**TON**) : `UQBAL2lkifBy7H8-3M7khJXu8w2TqjvJ8tSbhFRkNAR_7mQJ` 93 | -------------------------------------------------------------------------------- /Instagram/Login.php: -------------------------------------------------------------------------------- 1 | safeLoad(); 14 | 15 | class Login 16 | { 17 | private $client; 18 | private $username; 19 | private $password; 20 | private $host; 21 | private $port; 22 | function __construct(ClientInterface $client, string $username, string $password) 23 | { 24 | $this->client = $client; 25 | $this->password = $password; 26 | $this->username = $username; 27 | $this->host = $_ENV['PROXY_HOST'] ?? getenv('PROXY_HOST') ?? ''; 28 | $this->port = $_ENV['PROXY_PORT'] ?? getenv('PROXY_PORT') ?? ''; 29 | } 30 | public function SessionLogin() 31 | { 32 | $Request = $this->client->request('GET', Uri::BASE_URL, [ 33 | 'headers' => [ 34 | 'user-agent' => Uri::UA_LINUX, 35 | ], 36 | 'proxy' => (!empty($this->host) && !empty($this->port)) ? "http://{$this->host}:{$this->port}" : null 37 | ]); 38 | preg_match('/"csrf_token":"(.*?)"/', $Request->getBody(), $matches); 39 | if (!isset($matches[1])) { 40 | throw new Exception('Unable to extract CSRF token from Instagram response.'); 41 | } 42 | 43 | $csrfToken = $matches[1]; 44 | $cookieJar = new FileCookieJar('cookies.txt', true); 45 | $query = null; 46 | try { 47 | $query = $this->client->request('POST', Uri::AUTH_URL, [ 48 | 'form_params' => [ 49 | 'username' => $this->username, 50 | 'enc_password' => '#PWD_INSTAGRAM_BROWSER:0:' . time() . ':' . $this->password, 51 | ], 52 | 'headers' => [ 53 | 'cookie' => 'ig_cb=1; csrftoken=' . $csrfToken, 54 | 'referer' => Uri::BASE_URL, 55 | 'x-csrftoken' => $csrfToken, 56 | 'user-agent' => Uri::UA_LINUX, 57 | ], 58 | 'cookies' => $cookieJar, 59 | 'proxy' => (!empty($this->host) && !empty($this->port)) ? "http://{$this->host}:{$this->port}" : null 60 | ]); 61 | } catch (ClientException $exception) { 62 | $data = json_decode((string) $exception->getResponse()->getBody()); 63 | if ($data && isset($data->message) && $data->message === 'checkpoint_required') { 64 | throw new Exception('Instagram requires checkpoint verification (possible 2FA or suspicious login). ' . $exception->getMessage()); 65 | } 66 | throw new Exception('Login request failed: ' . $exception->getMessage()); 67 | } 68 | 69 | if (!$query) { 70 | throw new Exception('No response from Instagram login request.'); 71 | } 72 | 73 | $response = json_decode((string) $query->getBody()); 74 | 75 | if (property_exists($response, 'authenticated') && $response->authenticated == true) { 76 | return true; 77 | } else if (property_exists($response, 'error_type') && $response->error_type === 'generic_request_error') { 78 | throw new Exception('Generic error / Your IP may be blocked by Instagram. You should consider using a proxy.'); 79 | } else { 80 | throw new Exception('Wrong login / password'); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /js/script.js: -------------------------------------------------------------------------------- 1 | function Run() { 2 | var xmlhttp = new XMLHttpRequest(); 3 | xmlhttp.onreadystatechange = function () { 4 | if (this.readyState == 4 && this.status == 200) { 5 | var JData = JSON.parse(this.responseText); 6 | document.getElementById("files").hidden = false; 7 | if (JData.caption !== null) { 8 | document.getElementById("caption").innerHTML = JData.caption.replace('\n', '
'); 9 | document.getElementById("caption").hidden = false; 10 | if (isUnicode(document.getElementById('caption').textContent)) { 11 | document.getElementById('caption').style.direction = 'rtl'; 12 | } 13 | else { 14 | document.getElementById('caption').style.direction = 'ltr'; 15 | } 16 | } 17 | var data = new FormData(); 18 | data.append("file", JData.file); 19 | var xhr = new XMLHttpRequest(); 20 | xhr.addEventListener("readystatechange", function () { 21 | if (this.readyState === 4) { 22 | var json = JSON.parse(this.responseText); 23 | if (JData.type == 'image') { 24 | document.getElementById("thumb").hidden = false; 25 | document.getElementById("thumb").src = json.path; 26 | } 27 | } 28 | }); 29 | xhr.open("POST", "proxy.php"); 30 | xhr.send(data); 31 | if (JData.type == 'side') { 32 | var count = 0; 33 | document.getElementById("thumb").hidden = true; 34 | document.getElementById('carouselExampleControls').hidden = false; 35 | JData.data.forEach((element, index) => { 36 | let slide = document.createElement("div"); 37 | if (index == 0) { 38 | slide.className = "carousel-item active"; 39 | } else { 40 | slide.className = "carousel-item"; 41 | } 42 | var data = new FormData(); 43 | data.append("file", element.file); 44 | var xhr = new XMLHttpRequest(); 45 | xhr.open("POST", "proxy.php"); 46 | xhr.send(data); 47 | xhr.addEventListener("readystatechange", function () { 48 | if (this.readyState === 4) { 49 | var json = JSON.parse(this.responseText); 50 | if (element.type == "image") { 51 | slide.innerHTML = ""; 52 | } else if (element.type == "video") { 53 | slide.innerHTML = ""; 54 | } 55 | } 56 | }); 57 | document.getElementById('carousel-child').appendChild(slide); 58 | let btn = document.createElement("a"); 59 | btn.className = "btn p-1 m-1"; 60 | btn.style.backgroundColor = "#00b0ff"; 61 | btn.style.color = 'white'; 62 | btn.innerHTML = " " + count++; 63 | btn.href = element.file; 64 | btn.target = '_blank'; 65 | document.getElementById('files').appendChild(btn); 66 | }); 67 | } else { 68 | let btn = document.createElement("a"); 69 | btn.className = "btn p-1 m-1"; 70 | btn.style.backgroundColor = "#00b0ff"; 71 | btn.style.color = 'white'; 72 | btn.innerHTML = " Save"; 73 | btn.href = JData.file; 74 | btn.target = '_blank'; 75 | document.getElementById('files').appendChild(btn); 76 | } 77 | } 78 | }; 79 | xmlhttp.open("GET", "instagram.php?link=" + document.getElementById("url-field").value, true); 80 | xmlhttp.send(); 81 | } 82 | function isUnicode(str) { 83 | var letters = []; 84 | for (var i = 0; i <= str.length; i++) { 85 | letters[i] = str.substring((i - 1), i); 86 | if (letters[i].charCodeAt() > 255) { return true; } 87 | } 88 | return false; 89 | } -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | InsDown - Instagram Downloader 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 |
Instagram Downloader

33 |
34 | 35 | 36 |
37 |
38 | 51 | 52 | 53 | 55 |
56 | 64 | 65 | 66 | 67 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /Instagram/InstagramAPI.php: -------------------------------------------------------------------------------- 1 | safeLoad(); 12 | 13 | class InstagramAPI 14 | { 15 | private $cookie; 16 | private $host; 17 | private $port; 18 | private $proxy; 19 | 20 | public function __construct( 21 | mixed $cookie, 22 | ) { 23 | $this->cookie = $cookie; 24 | $this->host = $_ENV['PROXY_HOST'] ?? getenv('PROXY_HOST') ?? ''; 25 | $this->port = $_ENV['PROXY_PORT'] ?? getenv('PROXY_PORT') ?? ''; 26 | $this->proxy = (!empty($this->host) && !empty($this->port)) ? "http://{$this->host}:{$this->port}" : null; 27 | } 28 | function SendRequest(string $method, string $url, array $opts) 29 | { 30 | if ($this->proxy) { 31 | $opts['proxy'] = $this->proxy; 32 | } 33 | $client = new Client(); 34 | $request = $client->request($method, $url, $opts); 35 | return $request->getBody(); 36 | } 37 | public function getMediaID($url) 38 | { 39 | $options = [ 40 | 'headers' => [ 41 | 'authority' => 'www.instagram.com', 42 | 'accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 43 | 'accept-language' => 'en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7', 44 | 'cache-control' => 'max-age=0', 45 | 'sec-ch-prefers-color-scheme' => 'light', 46 | 'sec-ch-ua' => '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"', 47 | 'sec-ch-ua-mobile' => '?0', 48 | 'sec-ch-ua-platform' => '"Windows"', 49 | 'sec-fetch-dest' => 'document', 50 | 'sec-fetch-mode' => 'navigate', 51 | 'sec-fetch-site' => 'same-origin', 52 | 'sec-fetch-user' => '?1', 53 | 'upgrade-insecure-requests' => '1', 54 | 'user-agent' => Uri::UA_LINUX, 55 | 'viewport-width' => '1920' 56 | ], 57 | 'cookies' => $this->cookie 58 | ]; 59 | preg_match('/{"media_id":"(.*?)"/', $this->SendRequest('GET', $url, $options), $matches); 60 | return $matches[1] ?? null; 61 | } 62 | public function getReelsID($url) 63 | { 64 | $options = [ 65 | 'headers' => [ 66 | 'authority' => 'www.instagram.com', 67 | 'accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 68 | 'accept-language' => 'en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7', 69 | 'cache-control' => 'max-age=0', 70 | 'sec-ch-prefers-color-scheme' => 'light', 71 | 'sec-ch-ua' => '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"', 72 | 'sec-ch-ua-mobile' => '?0', 73 | 'sec-ch-ua-platform' => '"Windows"', 74 | 'sec-fetch-dest' => 'document', 75 | 'sec-fetch-mode' => 'navigate', 76 | 'sec-fetch-site' => 'same-origin', 77 | 'sec-fetch-user' => '?1', 78 | 'upgrade-insecure-requests' => '1', 79 | 'user-agent' => Uri::UA_LINUX, 80 | 'viewport-width' => '1920' 81 | ], 82 | 'cookies' => $this->cookie 83 | ]; 84 | preg_match('/"user_id":"(.*?)"/', $this->SendRequest('GET', $url, $options), $matches); 85 | return $matches[1] ?? null; 86 | } 87 | public function fetchStory($user_id) 88 | { 89 | $options = [ 90 | 'headers' => [ 91 | 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 92 | 'User-Agent' => Uri::UA_IG_ANDROID 93 | ], 94 | 'cookies' => $this->cookie 95 | ]; 96 | return $this->SendRequest('GET', "https://i.instagram.com/api/v1/feed/user/$user_id/reel_media/", $options); 97 | } 98 | public function fetchData($media_id) 99 | { 100 | $options = [ 101 | 'headers' => [ 102 | 'accept' => '*/*', 103 | 'accept-language' => 'en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7', 104 | 'user-agent' => Uri::UA_LINUX, 105 | 'x-ig-app-id' => '936619743392459' 106 | ], 107 | 'cookies' => $this->cookie 108 | ]; 109 | return $this->SendRequest('GET', "https://i.instagram.com/api/v1/media/$media_id/info/", $options); 110 | } 111 | public function fetchProfile($username) 112 | { 113 | $options = [ 114 | 'headers' => [ 115 | 'accept' => '*/*', 116 | 'accept-language' => 'en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7', 117 | 'user-agent' => Uri::UA_LINUX, 118 | 'x-ig-app-id' => '936619743392459' 119 | ], 120 | 'cookies' => $this->cookie 121 | ]; 122 | return $this->SendRequest('GET', Uri::USER_PROFILE_URL . $username, $options); 123 | } 124 | public function fetchHighlight($url, $opt = 'first_response') 125 | { 126 | $fetch = $this->SendRequest('GET', $url, ['cookies' => $this->cookie]); 127 | preg_match('/"highlight:(.*?)","page_logging"/', $fetch, $matches); 128 | switch ($opt) { 129 | case 'second_response': 130 | $options = [ 131 | 'headers' => [ 132 | 'accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 133 | 'accept-language' => 'en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7', 134 | 'user-agent' => Uri::UA_IG_ANDROID, 135 | 'Cache-Control' => 'max-age=0' 136 | ], 137 | 'cookies' => $this->cookie 138 | ]; 139 | try { 140 | $result = json_decode($this->SendRequest('GET', Uri::REELS_URL . 'highlight%3A' . $matches[1], $options)); 141 | } catch (Exception $e) { 142 | preg_match('/www.instagram.com\/s\/(.+)[?]/', $url, $matches2); 143 | $result = json_decode($this->SendRequest('GET', Uri::REELS_URL . base64_decode($matches2[1]), $options)); 144 | } 145 | break; 146 | default: 147 | $result = $matches[1] ?? null; 148 | break; 149 | } 150 | return $result; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /instagram.php: -------------------------------------------------------------------------------- 1 | safeLoad(); 12 | 13 | $_COOKIE = new FileCookieJar('cookies.txt'); 14 | class Instagram 15 | { 16 | 17 | function igInfo($user) 18 | { 19 | $ig = new InstagramAPI($_COOKIE); 20 | $response = $ig->fetchProfile($user); 21 | if ($response != '{}') { 22 | $jayson = json_decode($response); 23 | $user = $jayson->data->user; 24 | $json = [ 25 | "status" => true, 26 | "name" => $user->full_name, 27 | "id" => $user->id, 28 | "bio" => $user->biography, 29 | "website" => $user->external_url, 30 | "account" => ["business" => $user->is_business_account, "professional" => $user->is_professional_account, "category" => $user->category_name], 31 | "profile_hd" => $user->profile_pic_url_hd, 32 | "followers" => $user->edge_followed_by->count, 33 | "following" => $user->edge_follow->count 34 | ]; 35 | return json_encode($json, 128); 36 | } else { 37 | return json_encode(['status' => false], 128); 38 | } 39 | } 40 | 41 | function igSave($url) 42 | { 43 | $ig = new InstagramAPI($_COOKIE); 44 | $response = $ig->fetchData($ig->getMediaID($url)); 45 | if ($response != '{}') { 46 | $jayson = json_decode($response); 47 | $data = $jayson->items[0]; 48 | if ($data->media_type == 2) { 49 | if (empty($data->caption->text)) 50 | return json_encode(['status' => true, 'type' => 'video', 'caption' => null, 'like' => $data->like_count, 'comment' => $data->comment_count, 'view' => $data->play_count, 'file' => $data->video_versions[0]->url], 128); 51 | else 52 | return json_encode(['status' => true, 'type' => 'video', 'caption' => $data->caption->text, 'like' => $data->like_count, 'comment' => $data->comment_count, 'view' => $data->play_count, 'file' => $data->video_versions[0]->url], 128); 53 | } elseif ($data->media_type == 1) { 54 | if (empty($data->caption->text)) 55 | return json_encode(['status' => true, 'type' => 'image', 'caption' => null, 'like' => $data->like_count, 'comment' => $data->comment_count, 'view' => $data->play_count, 'file' => $data->image_versions2->candidates[0]->url], 128); 56 | else 57 | return json_encode(['status' => true, 'type' => 'image', 'caption' => $data->caption->text, 'like' => $data->like_count, 'comment' => $data->comment_count, 'view' => $data->play_count, 'file' => $data->image_versions2->candidates[0]->url], 128); 58 | } elseif ($data->media_type == 8) { 59 | $childrens = []; 60 | foreach ($data->carousel_media as $child) { 61 | if ($child->media_type == 2) { 62 | array_push($childrens, ['type' => 'video', 'file' => $child->video_versions[0]->url]); 63 | } else { 64 | array_push($childrens, ['type' => 'image', 'file' => $child->image_versions2->candidates[0]->url]); 65 | } 66 | } 67 | if (empty($data->caption->text)) 68 | return json_encode(['status' => true, 'type' => 'side', 'caption' => null, 'like' => $data->like_count, 'comment' => $data->comment_count, 'view' => $data->play_count, 'data' => $childrens], 128); 69 | else 70 | return json_encode(['status' => true, 'type' => 'side', 'caption' => $data->caption->text, 'like' => $data->like_count, 'comment' => $data->comment_count, 'view' => $data->play_count, 'data' => $childrens], 128); 71 | } 72 | } else { 73 | return json_encode(['status' => false], 128); 74 | } 75 | } 76 | public $highlight_url; 77 | function isHighlight($url) 78 | { 79 | if (str_contains($url, 'highlight')) { 80 | $this->highlight_url = $url; 81 | return true; 82 | } else { 83 | preg_match('/www.instagram.com\/s\/(.+)[?]/', $url, $matches); 84 | if (str_contains(base64_decode($matches[1]), 'highlight')) { 85 | $this->highlight_url = $url; 86 | return true; 87 | } else { 88 | return false; 89 | } 90 | } 91 | } 92 | function igHighlight($url) 93 | { 94 | $ig = new InstagramAPI($_COOKIE); 95 | $response = $ig->fetchHighlight($url); 96 | $response2 = $ig->fetchHighlight($url, 'second_response'); 97 | $childrens = []; 98 | $hid = 'highlight:' . $response; 99 | foreach ($response2->reels->$hid->items as $child) { 100 | if ($child->media_type == 2) { 101 | array_push($childrens, ['type' => 'video', 'file' => $child->video_versions[0]->url]); 102 | } else { 103 | array_push($childrens, ['type' => 'image', 'file' => $child->image_versions2->candidates[0]->url]); 104 | } 105 | } 106 | return json_encode(['status' => true, 'type' => 'side', 'caption' => null, 'like' => null, 'comment' => null, 'data' => $childrens], 128); 107 | } 108 | function igStory($url) 109 | { 110 | preg_match('/.*([?].*)/', $url, $match); 111 | $urlnew = str_replace($match[1], '/', $url); 112 | preg_match('/\/stories\/(.*?)\/(.*?)\//', $urlnew, $matches); 113 | $ig = new InstagramAPI($_COOKIE); 114 | $response = $ig->fetchStory($ig->getReelsID($urlnew)); 115 | $jayson = json_decode($response); 116 | foreach ($jayson->items as $items) { 117 | if ($items->pk == $matches[2]) { 118 | if ($items->media_type == 2) { 119 | return json_encode(['status' => true, 'type' => 'video', 'caption' => null, 'file' => $items->video_versions[0]->url], 128); 120 | } elseif ($items->media_type == 1) { 121 | return json_encode(['status' => true, 'type' => 'image', 'caption' => null, 'file' => $items->image_versions2->candidates[0]->url], 128); 122 | } 123 | } 124 | } 125 | } 126 | } 127 | $instagram = new Instagram(); 128 | if (isset($_GET['user']) && !empty($_GET['user'])) { 129 | echo $instagram->igInfo($_GET['user']); 130 | } elseif (isset($_GET['link']) && !empty($_GET['link'])) { 131 | if (str_contains($_GET['link'], 'stories') && !str_contains($_GET['link'], 'highlight')) { 132 | echo $instagram->igStory($_GET['link']); 133 | } elseif ($instagram->isHighlight($_GET['link'])) { 134 | echo $instagram->igHighlight($instagram->highlight_url); 135 | } else { 136 | echo $instagram->igSave($_GET['link']); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /image/instagram.svg: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------