ultra-igdl 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,269 +1,229 @@
1
1
  # ultra-igdl
2
2
 
3
- **Production-grade Instagram media extractor for Node.js 20+**
3
+ **Beginner-friendly Instagram media extractor for Node.js**
4
4
 
5
- Fetch direct CDN URLs for reels, posts, carousels, stories, and highlights. Built from scratch with a multi-layer HTML/JSON parser, optional logged-in session API, connection pooling, LRU cache, and a CLI — **no wrapper around other Instagram downloader packages**.
5
+ Get direct download links (images and videos) from Instagram posts, reels, carousels, stories, and highlights. Use it from the **command line** or inside your **JavaScript / TypeScript** app.
6
6
 
7
- ---
8
-
9
- ## Table of contents
7
+ [![npm version](https://img.shields.io/npm/v/ultra-igdl.svg)](https://www.npmjs.com/package/ultra-igdl)
10
8
 
11
- 1. [Who is this for?](#who-is-this-for)
12
- 2. [Requirements](#requirements)
13
- 3. [Installation](#installation)
14
- 4. [Quick start (beginner)](#quick-start-beginner)
15
- 5. [Instagram session (important)](#instagram-session-important)
16
- 6. [CLI guide](#cli-guide)
17
- 7. [Supported URLs](#supported-urls)
18
- 8. [Response format](#response-format)
19
- 9. [Content types explained](#content-types-explained)
20
- 10. [JavaScript / TypeScript API](#javascript--typescript-api)
21
- 11. [Configuration options](#configuration-options)
22
- 12. [Pro features](#pro-features)
23
- 13. [Error codes & troubleshooting](#error-codes--troubleshooting)
24
- 14. [Examples in this repo](#examples-in-this-repo)
25
- 15. [Architecture](#architecture)
26
- 16. [Development](#development)
27
- 17. [Publishing to npm](#publishing-to-npm)
28
- 18. [Legal & disclaimer](#legal--disclaimer)
29
- 19. [License](#license)
9
+ **Links:** [npm package](https://www.npmjs.com/package/ultra-igdl) · [GitHub](https://github.com/WH173-5P1D3R/ultra-igdl) · [Report issues](https://github.com/WH173-5P1D3R/ultra-igdl/issues)
30
10
 
31
11
  ---
32
12
 
33
- ## Who is this for?
13
+ ## Table of contents
34
14
 
35
- | Level | You can… |
36
- |--------|-----------|
37
- | **Beginner** | Install with npm, run `npx ultra-igdl <url> --json`, paste a browser cookie for full carousels |
38
- | **Intermediate** | Use `ultraigdl` in Express/Fastify bots, batch URLs, download files with `--download` |
39
- | **Pro** | Tune cache/Redis, `fastMode` + `prefetch`, `maxConcurrency`, integrate `DownloaderCore` |
15
+ 1. [What does this do?](#1-what-does-this-do)
16
+ 2. [Who is this for?](#2-who-is-this-for)
17
+ 3. [Before you start (requirements)](#3-before-you-start-requirements)
18
+ 4. [Install Node.js and the package](#4-install-nodejs-and-the-package)
19
+ 5. [Your first download (CLI)](#5-your-first-download-cli)
20
+ 6. [Your first download (code)](#6-your-first-download-code)
21
+ 7. [Understanding the JSON response](#7-understanding-the-json-response)
22
+ 8. [Instagram session — why and how](#8-instagram-session--why-and-how)
23
+ 9. [Content types (posts, reels, carousels, stories)](#9-content-types-posts-reels-carousels-stories)
24
+ 10. [Command line (CLI) — full guide](#10-command-line-cli--full-guide)
25
+ 11. [JavaScript / TypeScript API](#11-javascript--typescript-api)
26
+ 12. [Configuration options](#12-configuration-options)
27
+ 13. [Batch URLs and bots](#13-batch-urls-and-bots)
28
+ 14. [Error codes and fixes](#14-error-codes-and-fixes)
29
+ 15. [FAQ and troubleshooting](#15-faq-and-troubleshooting)
30
+ 16. [Examples in this repository](#16-examples-in-this-repository)
31
+ 17. [Legal and privacy](#17-legal-and-privacy)
32
+ 18. [License](#18-license)
40
33
 
41
34
  ---
42
35
 
43
- ## Requirements
36
+ ## 1. What does this do?
44
37
 
45
- - **Node.js** 20.18.1+ or 22 (LTS recommended)
46
- - **npm** 9+ (or pnpm/yarn)
47
- - Public Instagram URLs (no login required for basic post/reel preview)
48
- - **Optional:** Instagram `sessionid` cookie for carousels (all slides), reel MP4, stories, highlights
38
+ You give **ultra-igdl** an Instagram link. It returns:
49
39
 
50
- ---
40
+ - **Direct media URLs** (CDN links you can open or save)
41
+ - **Caption** and **username**
42
+ - Optional **likes / comments** counts when Instagram shows them
43
+ - Hints in `tags` (for example: carousel detected, session recommended)
51
44
 
52
- ## Installation
45
+ It works **without logging in** for many public posts and reels, but Instagram limits logged-out access. For **full carousels**, **reel video files**, **stories**, and **highlights**, you usually need a **browser session cookie** (explained in [section 8](#8-instagram-session--why-and-how)).
53
46
 
54
- ### npm (recommended)
47
+ ---
55
48
 
56
- ```bash
57
- npm install ultra-igdl
58
- ```
49
+ ## 2. Who is this for?
59
50
 
60
- [![npm version](https://img.shields.io/npm/v/ultra-igdl.svg)](https://www.npmjs.com/package/ultra-igdl)
51
+ | You are… | Start here |
52
+ |----------|------------|
53
+ | **Complete beginner** | [Section 4](#4-install-nodejs-and-the-package) → [Section 5](#5-your-first-download-cli) (CLI with `npx`) |
54
+ | **JavaScript developer** | [Section 6](#6-your-first-download-code) → [Section 11](#11-javascript--typescript-api) |
55
+ | **Bot builder** (Telegram, Discord, etc.) | [Section 8](#8-instagram-session--why-and-how) + [Section 13](#13-batch-urls-and-bots) |
56
+ | **TypeScript user** | [Section 11](#11-javascript--typescript-api) (types included) |
61
57
 
62
- ### GitHub Packages
58
+ No Instagram API key is required. You only need Node.js and a valid Instagram URL.
63
59
 
64
- Scoped package: `@wh173-5p1d3r/ultra-igdl` (published on release tags `v*`).
60
+ ---
65
61
 
66
- 1. Create a [GitHub PAT](https://github.com/settings/tokens) with `read:packages`.
67
- 2. Add `.npmrc` (see [`.npmrc.github.example`](./.npmrc.github.example)):
62
+ ## 3. Before you start (requirements)
68
63
 
69
- ```ini
70
- @wh173-5p1d3r:registry=https://npm.pkg.github.com
71
- //npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
72
- ```
64
+ | Requirement | Details |
65
+ |-------------|---------|
66
+ | **Node.js** | Version **20.18.1 or newer** (22 LTS is fine). Check with `node -v` |
67
+ | **npm** | Comes with Node. Check with `npm -v` |
68
+ | **Instagram URL** | A normal link you can open in a browser (post, reel, story, etc.) |
69
+ | **Session cookie** | Optional but strongly recommended for carousels, reel MP4, stories |
73
70
 
74
- 3. Install:
71
+ **Check Node version:**
75
72
 
76
73
  ```bash
77
- npm install @wh173-5p1d3r/ultra-igdl
74
+ node -v
75
+ # Should print v20.18.1 or higher (e.g. v22.x.x)
78
76
  ```
79
77
 
80
- ```js
81
- import { ultraigdl } from "@wh173-5p1d3r/ultra-igdl";
82
- ```
83
-
84
- Package page: https://github.com/WH173-5P1D3R/ultra-igdl/packages
85
-
86
- CLI only (no install into project):
87
-
88
- ```bash
89
- npx ultra-igdl --help
90
- ```
78
+ If Node is too old, install the latest LTS from [https://nodejs.org](https://nodejs.org).
91
79
 
92
80
  ---
93
81
 
94
- ## Quick start (beginner)
82
+ ## 4. Install Node.js and the package
95
83
 
96
- ### 1. Programmatic (ESM)
97
-
98
- ```js
99
- import { ultraigdl } from "ultra-igdl";
100
-
101
- const ig = new ultraigdl();
102
- const result = await ig.download("https://www.instagram.com/reel/SHORTCODE/");
84
+ ### Option A — Use without installing (fastest try)
103
85
 
104
- if (result.code === 200) {
105
- console.log("User:", result.username);
106
- console.log("Caption:", result.caption);
107
- console.log("Files:", result.media.length);
108
- result.media.forEach((m, i) => console.log(i + 1, m.type, m.url));
109
- } else {
110
- console.error(result.code, result.message);
111
- }
86
+ ```bash
87
+ npx ultra-igdl --help
112
88
  ```
113
89
 
114
- ### 2. CommonJS
90
+ `npx` downloads the tool temporarily and runs it. Good for a quick test.
115
91
 
116
- ```js
117
- const { ultraigdl } = require("ultra-igdl");
118
-
119
- (async () => {
120
- const ig = new ultraigdl();
121
- const result = await ig.download("https://www.instagram.com/p/SHORTCODE/");
122
- console.log(result);
123
- })();
124
- ```
125
-
126
- ### 3. CLI (JSON)
92
+ ### Option B — Add to your project (recommended for apps)
127
93
 
128
94
  ```bash
129
- npx ultra-igdl "https://www.instagram.com/p/SHORTCODE/" --json
95
+ mkdir my-ig-downloader
96
+ cd my-ig-downloader
97
+ npm init -y
98
+ npm install ultra-igdl
130
99
  ```
131
100
 
132
- On **Windows PowerShell**, always wrap URLs in **double quotes** (see [CLI guide](#cli-guide)).
101
+ You can then `import` or `require` it in your code (see [section 6](#6-your-first-download-code)).
133
102
 
134
103
  ---
135
104
 
136
- ## Instagram session (important)
105
+ ## 5. Your first download (CLI)
137
106
 
138
- Instagram limits what **logged-out** visitors see:
107
+ ### Step 1 Copy an Instagram URL
139
108
 
140
- | Feature | Without session | With session (`sessionId` / `cookies`) |
141
- |---------|-----------------|----------------------------------------|
142
- | Single post image | Usually yes | Yes (full resolution) |
143
- | **Carousel (2+ photos)** | Often **1 slide only** | **All slides** |
144
- | **Reel MP4** | Often thumbnail only | **Video URL** |
145
- | **Story** | Usually fails / preview | **Media URL** |
146
- | **Highlight** | Limited | **Video** when available |
109
+ Example (replace with a real public post):
147
110
 
148
- ### How to get cookies (browser)
111
+ ```text
112
+ https://www.instagram.com/p/SHORTCODE/
113
+ ```
149
114
 
150
- 1. Log in to [instagram.com](https://www.instagram.com) in Chrome/Edge/Firefox.
151
- 2. Open DevTools → **Application** → **Cookies** → `https://www.instagram.com`.
152
- 3. Copy:
153
- - `sessionid`
154
- - `csrftoken`
155
- - `ds_user_id`
115
+ ### Step 2 Run the CLI
156
116
 
157
- ### Option A full cookie string (recommended)
117
+ **Linux / macOS / Git Bash:**
158
118
 
159
- ```js
160
- const ig = new ultraigdl({
161
- cookies:
162
- "sessionid=YOUR_ID; csrftoken=YOUR_CSRF; ds_user_id=YOUR_USER_ID",
163
- });
119
+ ```bash
120
+ npx ultra-igdl "https://www.instagram.com/p/SHORTCODE/"
164
121
  ```
165
122
 
166
- ### Option B session id only
123
+ **Windows PowerShell**always put the URL in **double quotes**:
167
124
 
168
- ```js
169
- const ig = new ultraigdl({
170
- sessionId: "YOUR_SESSIONID_VALUE",
171
- });
125
+ ```powershell
126
+ npx ultra-igdl "https://www.instagram.com/p/SHORTCODE/"
172
127
  ```
173
128
 
174
- ### Environment variables (CLI)
129
+ ### Step 3 — Read the output
175
130
 
176
- The CLI auto-loads `.env` from the current directory or `../ultra-igdl-live-test/.env`.
131
+ Without `--json`, you get a short summary: username, caption preview, and a list of media items with type and URL.
132
+
133
+ For **machine-readable output** (scripts, bots):
177
134
 
178
135
  ```bash
179
- # Linux / macOS
180
- export INSTAGRAM_COOKIES="sessionid=...; csrftoken=...; ds_user_id=..."
181
136
  npx ultra-igdl "https://www.instagram.com/p/SHORTCODE/" --json
182
137
  ```
183
138
 
184
- ```powershell
185
- # Windows PowerShell — use TWO lines, or semicolon before npx
186
- $env:INSTAGRAM_COOKIES = "sessionid=...; csrftoken=...; ds_user_id=..."
187
- npx ultra-igdl "https://www.instagram.com/p/SHORTCODE/" --json
139
+ ### Step 4 — Save files to disk
140
+
141
+ ```bash
142
+ npx ultra-igdl "https://www.instagram.com/p/SHORTCODE/" --download --output ./downloads
188
143
  ```
189
144
 
190
- **Never commit real cookies to git.** Add `.env` to `.gitignore` (already included).
145
+ Files go under `./downloads/<username>/`.
191
146
 
192
147
  ---
193
148
 
194
- ## CLI guide
149
+ ## 6. Your first download (code)
195
150
 
196
- ```bash
197
- npx ultra-igdl <url> [options]
198
- npx ultra-igdl urls.txt # one URL per line
199
- ```
151
+ Create a file `test.mjs` in your project folder (after `npm install ultra-igdl`).
200
152
 
201
- | Flag | Short | Description |
202
- |------|-------|-------------|
203
- | `--json` | `-j` | Print full API response as JSON |
204
- | `--download` | `-d` | Save media files under `--output` |
205
- | `--output <dir>` | `-o` | Download folder (default: `./downloads`) |
206
- | `--verbose` | `-v` | Debug logging |
207
- | `--help` | `-h` | Show help |
153
+ ### ESM (modern Node `"type": "module"` in package.json, or `.mjs` file)
208
154
 
209
- ### PowerShell rules
155
+ ```js
156
+ import { ultraigdl } from "ultra-igdl";
210
157
 
211
- 1. Wrap URLs in `"quotes"` when the link contains `&` (e.g. `?igsh=...&...`).
212
- 2. Set env vars on **line 1**, run `npx` on **line 2**, **or** use `;` between them:
158
+ const ig = new ultraigdl();
159
+ const url = "https://www.instagram.com/reel/SHORTCODE/";
213
160
 
214
- ```powershell
215
- $env:INSTAGRAM_COOKIES = "sessionid=...; csrftoken=...; ds_user_id=..."; npx ultra-igdl "https://www.instagram.com/p/ABC/" --json
161
+ const result = await ig.download(url);
162
+
163
+ if (result.code === 200) {
164
+ console.log("Creator:", result.username);
165
+ console.log("Caption:", result.caption);
166
+ console.log("Number of files:", result.media.length);
167
+ for (const item of result.media) {
168
+ console.log(item.type, item.url);
169
+ }
170
+ } else {
171
+ console.log("Failed:", result.code, result.message);
172
+ }
216
173
  ```
217
174
 
218
- ### CLI examples
175
+ Run:
219
176
 
220
177
  ```bash
221
- # Human-readable summary
222
- npx ultra-igdl "https://www.instagram.com/reel/ABC123/"
178
+ node test.mjs
179
+ ```
223
180
 
224
- # JSON for scripts
225
- npx ultra-igdl "https://www.instagram.com/p/ABC123/" --json
181
+ ### CommonJS (`.cjs` file or no `"type": "module"`)
226
182
 
227
- # Download all carousel images
228
- npx ultra-igdl "https://www.instagram.com/p/ABC123/" --download -o ./downloads
183
+ ```js
184
+ const { ultraigdl } = require("ultra-igdl");
229
185
 
230
- # Batch file (urls.txt)
231
- npx ultra-igdl urls.txt --json
186
+ (async () => {
187
+ const ig = new ultraigdl();
188
+ const result = await ig.download("https://www.instagram.com/p/SHORTCODE/");
189
+ console.log(JSON.stringify(result, null, 2));
190
+ })();
232
191
  ```
233
192
 
234
- ---
193
+ ### Handle success vs error (important pattern)
235
194
 
236
- ## Supported URLs
195
+ Every call returns an object with a **`code`** field:
237
196
 
238
- | Type | Example pattern |
239
- |------|-----------------|
240
- | Post | `https://www.instagram.com/p/{shortcode}/` |
241
- | Reel | `https://www.instagram.com/reel/{shortcode}/` |
242
- | IGTV | `https://www.instagram.com/tv/{shortcode}/` |
243
- | Story | `https://www.instagram.com/stories/{username}/{storyId}/` |
244
- | Highlight (path) | `https://www.instagram.com/stories/highlights/{id}/` |
245
- | Highlight (share) | `https://www.instagram.com/s/{token}?story_media_id=...` |
246
-
247
- Validate before download:
197
+ - **`200`** success; use `media`, `caption`, `username`
198
+ - **Anything else** — error; read `message`
248
199
 
249
200
  ```js
250
- const { valid, type, normalized } = await ig.validate(url);
201
+ const result = await ig.download(url);
202
+ if (result.code !== 200) {
203
+ throw new Error(`${result.code}: ${result.message}`);
204
+ }
205
+ // TypeScript: narrow with if (result.code === 200) { ... result.media }
251
206
  ```
252
207
 
253
208
  ---
254
209
 
255
- ## Response format
210
+ ## 7. Understanding the JSON response
256
211
 
257
- ### Success (`code: 200`)
212
+ ### Successful response (`code: 200`)
258
213
 
259
214
  ```json
260
215
  {
261
216
  "code": 200,
262
- "meta": { "extractor": "ultra-igdl", "version": "1.0.0" },
217
+ "meta": {
218
+ "extractor": "ultra-igdl",
219
+ "version": "1.0.2"
220
+ },
221
+ "username": "creator",
222
+ "caption": "Post caption as one clean line",
263
223
  "media": [
264
224
  {
265
225
  "type": "image",
266
- "url": "https://...cdninstagram.../....jpg",
226
+ "url": "https://...cdninstagram.com/....jpg",
267
227
  "width": 1440,
268
228
  "height": 1800
269
229
  },
@@ -276,8 +236,6 @@ const { valid, type, normalized } = await ig.validate(url);
276
236
  "duration": 24
277
237
  }
278
238
  ],
279
- "caption": "Post caption as a single clean line for posts",
280
- "username": "creator",
281
239
  "engagement": {
282
240
  "likes": 1200,
283
241
  "comments": 45
@@ -286,190 +244,392 @@ const { valid, type, normalized } = await ig.validate(url);
286
244
  }
287
245
  ```
288
246
 
289
- ### Media object
247
+ ### Media object fields
290
248
 
291
- | Field | Type | Description |
292
- |-------|------|-------------|
293
- | `type` | `"image"` \| `"video"` | Primary media type |
294
- | `url` | `string` | Direct CDN URL (signed; do not edit query params) |
295
- | `thumbnail` | `string?` | Poster frame for video |
296
- | `width` / `height` | `number?` | Pixel dimensions when known |
297
- | `duration` | `number?` | Video length in seconds |
249
+ | Field | Meaning |
250
+ |-------|---------|
251
+ | `type` | `"image"` or `"video"` |
252
+ | `url` | Direct link to the file (use as-is; do not remove `?` parameters) |
253
+ | `thumbnail` | Preview image for videos |
254
+ | `width` / `height` | Pixel size when known |
255
+ | `duration` | Video length in seconds |
298
256
 
299
- ### Tags (`tags` array)
257
+ ### Tags (`tags` array) — what they mean for you
300
258
 
301
- | Tag | Meaning |
302
- |-----|---------|
303
- | `carousel` | Multi-slide post; `media.length` 2 |
304
- | `partial_carousel` | Carousel detected but only one slide returned |
305
- | `session_recommended` | Add `sessionId` / `cookies` for full carousel |
306
- | `likes_hidden` | Creator hid like counts |
307
- | `comments_hidden` | Comments disabled or hidden |
308
- | `engagement_hidden` | Both likes and comments hidden |
259
+ | Tag | Meaning | What you should do |
260
+ |-----|---------|-------------------|
261
+ | `carousel` | Multi-photo post; all slides returned | Nothing — you got the full carousel |
262
+ | `partial_carousel` | Carousel detected but only one image returned | Add session cookies ([section 8](#8-instagram-session--why-and-how)) |
263
+ | `session_recommended` | Logged-in session would improve results | Add `cookies` or `sessionId` |
264
+ | `likes_hidden` | Creator hid like counts | Normal — not an error |
265
+ | `comments_hidden` | Comments hidden or disabled | Normal — not an error |
266
+ | `engagement_hidden` | Both hidden | Normal not an error |
309
267
 
310
- ### Error (`code` 200)
268
+ ### Error response (`code` not 200)
311
269
 
312
270
  ```json
313
271
  {
314
272
  "code": 404,
315
273
  "message": "Media not found",
316
- "meta": { "extractor": "ultra-igdl", "version": "1.0.0" }
274
+ "meta": { "extractor": "ultra-igdl", "version": "1.0.2" }
317
275
  }
318
276
  ```
319
277
 
320
- Some responses include `retryAfterMs` when using `fastMode` / `responseBudgetMs` (background fetch still running).
278
+ Some responses include `retryAfterMs` when using fast-response mode ([section 13](#13-batch-urls-and-bots)).
321
279
 
322
280
  ---
323
281
 
324
- ## Content types explained
282
+ ## 8. Instagram session — why and how
283
+
284
+ Instagram shows **less content** to visitors who are not logged in.
325
285
 
326
- ### Posts (single image)
286
+ | Feature | Without session | With session (`cookies` / `sessionId`) |
287
+ |---------|-----------------|--------------------------------------|
288
+ | Single post image | Usually works | Works (often higher resolution) |
289
+ | **Carousel (2+ photos)** | Often **only 1 slide** | **All slides** |
290
+ | **Reel MP4 video** | Often thumbnail only | **Full video URL** |
291
+ | **Story** | Usually fails or preview only | **Works** (if story is still live) |
292
+ | **Highlight** | Limited | More reliable |
293
+
294
+ ### How to get cookies (Chrome / Edge / Firefox)
295
+
296
+ 1. Open [https://www.instagram.com](https://www.instagram.com) and **log in**.
297
+ 2. Press **F12** to open Developer Tools.
298
+ 3. Go to **Application** (Chrome) or **Storage** (Firefox) → **Cookies** → `https://www.instagram.com`.
299
+ 4. Copy these values:
300
+ - `sessionid`
301
+ - `csrftoken`
302
+ - `ds_user_id`
303
+
304
+ **Treat these like a password.** Never post them on GitHub, Discord, or screenshots.
305
+
306
+ ### Use in code — full cookie string (recommended)
307
+
308
+ ```js
309
+ const ig = new ultraigdl({
310
+ cookies:
311
+ "sessionid=YOUR_SESSIONID; csrftoken=YOUR_CSRF; ds_user_id=YOUR_USER_ID",
312
+ });
313
+ ```
314
+
315
+ ### Use in code — session id only
316
+
317
+ ```js
318
+ const ig = new ultraigdl({
319
+ sessionId: "YOUR_SESSIONID_VALUE",
320
+ });
321
+ ```
322
+
323
+ ### Use with environment variables (CLI and scripts)
324
+
325
+ Create a `.env` file in your project folder (add `.env` to `.gitignore`):
326
+
327
+ ```env
328
+ INSTAGRAM_COOKIES=sessionid=xxx; csrftoken=xxx; ds_user_id=xxx
329
+ ```
330
+
331
+ Or only:
332
+
333
+ ```env
334
+ INSTAGRAM_SESSION_ID=your_sessionid_value
335
+ ```
336
+
337
+ The CLI loads `.env` from the current directory automatically.
338
+
339
+ **Linux / macOS terminal:**
340
+
341
+ ```bash
342
+ export INSTAGRAM_COOKIES="sessionid=...; csrftoken=...; ds_user_id=..."
343
+ npx ultra-igdl "https://www.instagram.com/p/SHORTCODE/" --json
344
+ ```
345
+
346
+ **Windows PowerShell** — use **two lines** (or semicolon before `npx`):
347
+
348
+ ```powershell
349
+ $env:INSTAGRAM_COOKIES = "sessionid=...; csrftoken=...; ds_user_id=..."
350
+ npx ultra-igdl "https://www.instagram.com/p/SHORTCODE/" --json
351
+ ```
352
+
353
+ One-line PowerShell alternative:
354
+
355
+ ```powershell
356
+ $env:INSTAGRAM_COOKIES = "sessionid=...; csrftoken=...; ds_user_id=..."; npx ultra-igdl "https://www.instagram.com/p/SHORTCODE/" --json
357
+ ```
358
+
359
+ ### Load cookies from `process.env` in Node
360
+
361
+ ```js
362
+ const ig = new ultraigdl({
363
+ cookies: process.env.INSTAGRAM_COOKIES,
364
+ });
365
+ ```
366
+
367
+ ---
368
+
369
+ ## 9. Content types (posts, reels, carousels, stories)
370
+
371
+ ### Supported URL patterns
372
+
373
+ | Type | URL pattern |
374
+ |------|-------------|
375
+ | Post | `https://www.instagram.com/p/{shortcode}/` |
376
+ | Reel | `https://www.instagram.com/reel/{shortcode}/` |
377
+ | IGTV | `https://www.instagram.com/tv/{shortcode}/` |
378
+ | Story | `https://www.instagram.com/stories/{username}/{storyId}/` |
379
+ | Highlight | `https://www.instagram.com/stories/highlights/{id}/` |
380
+ | Highlight share link | `https://www.instagram.com/s/{token}?story_media_id=...` |
381
+
382
+ ### Single-image post
327
383
 
328
384
  ```js
329
385
  const result = await ig.download("https://www.instagram.com/p/SHORTCODE/");
330
- // result.media.length === 1 typically
386
+ // result.media.length is often 1
331
387
  ```
332
388
 
333
- ### Carousels (2+ photos)
389
+ ### Carousel (multiple photos)
334
390
 
335
- - **Auto-detected** from any `/p/` URLno special URL or env var.
336
- - Without session: often 1 image + tags `partial_carousel`, `session_recommended`.
337
- - With session: all slides, tag `carousel`.
391
+ Same URL as a normal post (`/p/...`). No special mode the library detects carousels automatically.
338
392
 
339
393
  ```js
340
394
  const ig = new ultraigdl({ cookies: process.env.INSTAGRAM_COOKIES });
341
395
  const result = await ig.download("https://www.instagram.com/p/SHORTCODE/");
342
- console.log(result.media.length); // e.g. 4
343
- console.log(result.tags); // ["carousel"]
396
+ console.log("Slides:", result.media.length);
397
+ console.log("Tags:", result.tags);
344
398
  ```
345
399
 
346
- ### Reels
400
+ If you see `partial_carousel` or `session_recommended`, add cookies from [section 8](#8-instagram-session--why-and-how).
401
+
402
+ ### Reel (video)
347
403
 
348
404
  ```js
349
405
  const ig = new ultraigdl({ sessionId: process.env.INSTAGRAM_SESSION_ID });
350
406
  const result = await ig.download("https://www.instagram.com/reel/SHORTCODE/");
351
407
  const video = result.media.find((m) => m.type === "video");
408
+ if (video) console.log("MP4:", video.url);
352
409
  ```
353
410
 
354
- ### Stories
411
+ ### Story
355
412
 
356
- Requires session. Story must still be live (not expired).
413
+ Requires session. The story must still be **live** (not expired after 24 hours).
357
414
 
358
415
  ```js
416
+ const ig = new ultraigdl({ cookies: process.env.INSTAGRAM_COOKIES });
359
417
  const result = await ig.download(
360
- "https://www.instagram.com/stories/username/1234567890/"
418
+ "https://www.instagram.com/stories/username/1234567890123456789/"
361
419
  );
362
420
  ```
363
421
 
364
- ### Highlights
422
+ ### Check a URL before downloading
423
+
424
+ ```js
425
+ const check = await ig.validate("https://www.instagram.com/p/SHORTCODE/");
426
+ console.log(check.valid, check.type, check.normalized);
427
+ ```
428
+
429
+ Or use the exported helper:
365
430
 
366
- Works with highlight URLs or `/s/` share links; session improves reliability.
431
+ ```js
432
+ import { validateUrl, parseInstagramUrl, isInstagramUrl } from "ultra-igdl";
433
+
434
+ console.log(isInstagramUrl(url));
435
+ console.log(parseInstagramUrl(url));
436
+ console.log(validateUrl(url));
437
+ ```
367
438
 
368
439
  ---
369
440
 
370
- ## JavaScript / TypeScript API
441
+ ## 10. Command line (CLI) — full guide
442
+
443
+ ### Basic usage
444
+
445
+ ```bash
446
+ npx ultra-igdl "<instagram-url>"
447
+ npx ultra-igdl "<instagram-url>" --json
448
+ npx ultra-igdl "<instagram-url>" --download
449
+ npx ultra-igdl "<instagram-url>" --download --output ./my-folder
450
+ npx ultra-igdl "<instagram-url>" --verbose
451
+ ```
452
+
453
+ ### Batch file (many URLs)
454
+
455
+ Create `urls.txt` — one URL per line. Lines starting with `#` are ignored.
456
+
457
+ ```text
458
+ https://www.instagram.com/p/ABC123/
459
+ https://www.instagram.com/reel/DEF456/
460
+ ```
461
+
462
+ Run:
463
+
464
+ ```bash
465
+ npx ultra-igdl urls.txt --json
466
+ ```
467
+
468
+ ### All CLI flags
469
+
470
+ | Flag | Short | Description |
471
+ |------|-------|-------------|
472
+ | `--json` | `-j` | Print full API JSON |
473
+ | `--download` | `-d` | Save media files to disk |
474
+ | `--output <dir>` | `-o` | Download folder (default: `./downloads`) |
475
+ | `--verbose` | `-v` | Debug logging |
476
+ | `--help` | `-h` | Show help |
477
+
478
+ ### Environment variables (CLI)
479
+
480
+ | Variable | Purpose |
481
+ |----------|---------|
482
+ | `INSTAGRAM_COOKIES` | Full cookie string (`sessionid=...; csrftoken=...; ...`) |
483
+ | `INSTAGRAM_SESSION_ID` | Just the `sessionid` value |
484
+
485
+ ### PowerShell tips (Windows)
486
+
487
+ 1. **Always quote URLs** that contain `&` (shared links with `?igsh=...&...`).
488
+ 2. Setting env vars and running `npx` on the **same line** requires a semicolon:
489
+
490
+ ```powershell
491
+ $env:INSTAGRAM_COOKIES = "sessionid=..."; npx ultra-igdl "https://www.instagram.com/p/ABC/" --json
492
+ ```
493
+
494
+ 3. If you see errors about `npx` or `Unexpected token`, run env and `npx` on **separate lines**.
495
+
496
+ ---
497
+
498
+ ## 11. JavaScript / TypeScript API
499
+
500
+ ### Create an instance
371
501
 
372
502
  ```ts
373
503
  import { ultraigdl, type ApiResponse, type DownloadResponse } from "ultra-igdl";
374
504
 
375
- const ig = new ultraigdl({ cache: true, retries: 2 });
505
+ const ig = new ultraigdl({
506
+ cache: true,
507
+ retries: 2,
508
+ cookies: process.env.INSTAGRAM_COOKIES,
509
+ });
376
510
  ```
377
511
 
378
- | Method | Returns | Description |
379
- |--------|---------|-------------|
380
- | `download(url)` | `Promise<ApiResponse>` | Full extraction (main method) |
381
- | `info(url)` | `Promise<ApiResponse>` | Alias of `download` |
382
- | `validate(url)` | `Promise<{ valid, type?, normalized? }>` | URL check + normalization |
383
- | `media(url)` | `Promise<Media[] \| ErrorResponse>` | Media array only |
384
- | `batch(urls)` | `Promise<BatchResult[]>` | Parallel downloads with per-URL timing |
385
- | `prefetch(url)` | `Promise<ApiResponse>` | Warm cache for `fastMode` |
386
- | `health()` | `Promise<HealthStatus>` | Cache stats, pool, version |
387
- | `clearCache()` | `void` | Clear in-memory LRU cache |
512
+ ### Methods
388
513
 
389
- ### TypeScript
514
+ | Method | Returns | When to use |
515
+ |--------|---------|-------------|
516
+ | `download(url)` | `Promise<ApiResponse>` | Main method — full result |
517
+ | `info(url)` | `Promise<ApiResponse>` | Same as `download` |
518
+ | `validate(url)` | `Promise<{ valid, type?, normalized? }>` | Check URL before processing |
519
+ | `media(url)` | `Promise<Media[] \| ErrorResponse>` | Only the `media` array |
520
+ | `batch(urls)` | `Promise<BatchResult[]>` | Many URLs at once |
521
+ | `prefetch(url)` | `Promise<ApiResponse>` | Warm cache before `download` (bots) |
522
+ | `health()` | `Promise<HealthStatus>` | Version, cache size, connection pool |
523
+ | `clearCache()` | `void` | Clear in-memory cache |
390
524
 
391
- Types are shipped in `dist/index.d.ts`. Narrow success responses:
525
+ ### TypeScript narrow success type
392
526
 
393
527
  ```ts
394
528
  const result = await ig.download(url);
395
529
  if (result.code === 200) {
396
- const data = result as DownloadResponse;
397
- data.media.forEach((m) => { /* ... */ });
530
+ const ok = result as DownloadResponse;
531
+ ok.media.forEach((m) => console.log(m.url));
398
532
  }
399
533
  ```
400
534
 
401
- ### Helpers (also exported)
535
+ ### Download files yourself (library)
536
+
537
+ Use `fetch` or any HTTP client on `media[].url`, or use the CLI `--download` flag which handles saving for you.
538
+
539
+ ```js
540
+ const res = await fetch(result.media[0].url);
541
+ const buf = Buffer.from(await res.arrayBuffer());
542
+ // write buf to disk with fs
543
+ ```
544
+
545
+ **Do not modify** the CDN URL query string — links are signed and may break if edited.
546
+
547
+ ### Exported utilities
402
548
 
403
549
  ```ts
404
- import { validateUrl, parseInstagramUrl, isInstagramUrl } from "ultra-igdl";
550
+ import {
551
+ ultraigdl,
552
+ validateUrl,
553
+ parseInstagramUrl,
554
+ isInstagramUrl,
555
+ PACKAGE_VERSION,
556
+ EXTRACTOR_NAME,
557
+ } from "ultra-igdl";
405
558
  ```
406
559
 
560
+ Advanced: `DownloaderCore` is exported for custom integrations.
561
+
407
562
  ---
408
563
 
409
- ## Configuration options
564
+ ## 12. Configuration options
410
565
 
411
- ```ts
566
+ Pass these to `new ultraigdl({ ... })`:
567
+
568
+ | Option | Default | Description |
569
+ |--------|---------|-------------|
570
+ | `cache` | `true` | Cache responses in memory |
571
+ | `cacheTtlMs` | `300000` (5 min) | Fresh cache lifetime |
572
+ | `staleCacheTtlMs` | `86400000` (24 h) | Serve stale while refreshing |
573
+ | `cacheMaxSize` | `500` | Max cached entries |
574
+ | `timeoutMs` | `8000` | HTTP timeout per request |
575
+ | `retries` | `2` | Retry count on failure |
576
+ | `maxConcurrency` | `100` | Parallel request limit |
577
+ | `userAgentRotation` | `true` | Rotate browser user-agents |
578
+ | `sessionId` | — | Instagram `sessionid` cookie value |
579
+ | `cookies` | — | Full cookie header string |
580
+ | `verbose` | `false` | Extra logging |
581
+ | `fastMode` | `false` | Target ~500 ms response; may return 503 + retry hint |
582
+ | `responseBudgetMs` | — | Max time for `download()` to return |
583
+ | `redis` | — | Custom `RedisAdapter` for shared cache |
584
+
585
+ Example — tuned for a small API server:
586
+
587
+ ```js
412
588
  const ig = new ultraigdl({
413
- // Cache
414
- cache: true, // default: true
415
- cacheTtlMs: 300_000, // 5 min fresh TTL
416
- staleCacheTtlMs: 86_400_000, // 24h stale-while-revalidate
417
- cacheMaxSize: 500,
418
-
419
- // Network
420
- maxConcurrency: 100,
589
+ cache: true,
590
+ cacheTtlMs: 600_000,
421
591
  timeoutMs: 15_000,
422
592
  retries: 3,
423
- userAgentRotation: true,
424
-
425
- // Session
426
- sessionId: "...",
427
- cookies: "sessionid=...; csrftoken=...; ds_user_id=...",
428
-
429
- // Low-latency mode (bots that reply in <500ms)
430
- fastMode: true, // sets responseBudgetMs: 500, retries: 0
431
- responseBudgetMs: 800,
593
+ cookies: process.env.INSTAGRAM_COOKIES,
594
+ });
595
+ ```
432
596
 
433
- // Optional Redis (implement RedisAdapter interface)
434
- redis: myRedisAdapter,
597
+ Example low-latency bot (may need retry on 503):
435
598
 
436
- verbose: false,
437
- });
599
+ ```js
600
+ const ig = new ultraigdl({ fastMode: true, cookies: process.env.INSTAGRAM_COOKIES });
601
+ await ig.prefetch(url);
602
+ let result = await ig.download(url);
603
+ if (result.code === 503 && result.retryAfterMs) {
604
+ await new Promise((r) => setTimeout(r, result.retryAfterMs));
605
+ result = await ig.download(url);
606
+ }
438
607
  ```
439
608
 
440
609
  ---
441
610
 
442
- ## Pro features
611
+ ## 13. Batch URLs and bots
443
612
 
444
- ### Batch processing
613
+ ### Batch in code
445
614
 
446
- ```ts
615
+ ```js
447
616
  const results = await ig.batch([
448
617
  "https://www.instagram.com/p/A/",
449
618
  "https://www.instagram.com/reel/B/",
450
619
  ]);
620
+
451
621
  for (const { url, result, durationMs } of results) {
452
622
  console.log(url, result.code, `${durationMs}ms`);
453
623
  }
454
624
  ```
455
625
 
456
- ### Fast mode + prefetch (Telegram/Discord bots)
626
+ ### Batch from CLI
457
627
 
458
- ```ts
459
- const ig = new ultraigdl({ fastMode: true, cookies: "..." });
628
+ Use a `.txt` file ([section 10](#10-command-line-cli--full-guide)).
460
629
 
461
- // Warm extraction while user types
462
- await ig.prefetch(url);
463
-
464
- // Often returns from cache within budget
465
- let result = await ig.download(url);
466
- if (result.code === 503 && result.retryAfterMs) {
467
- await new Promise((r) => setTimeout(r, result.retryAfterMs));
468
- result = await ig.download(url);
469
- }
470
- ```
630
+ ### Redis cache (optional, advanced)
471
631
 
472
- ### Redis cache adapter
632
+ If you run multiple server instances, implement `RedisAdapter`:
473
633
 
474
634
  ```ts
475
635
  import { ultraigdl, type RedisAdapter } from "ultra-igdl";
@@ -482,141 +642,86 @@ const redis: RedisAdapter = {
482
642
  const ig = new ultraigdl({ redis });
483
643
  ```
484
644
 
485
- ### Download files to disk (library)
486
-
487
- Use your own `fetch` on `media[].url`, or the CLI `--download` flag (uses built-in file downloader).
488
-
489
645
  ---
490
646
 
491
- ## Error codes & troubleshooting
647
+ ## 14. Error codes and fixes
492
648
 
493
- | Code | Typical cause | What to do |
494
- |------|---------------|------------|
495
- | **400** | Invalid URL | Use `validate()`; check link format |
496
- | **403** | Private account | Cannot extract without access |
497
- | **404** | Deleted / wrong id / expired story | Verify URL in browser |
498
- | **429** | Rate limited | Slow down; reduce concurrency; wait |
499
- | **500** | Parse/network failure | Retry; update package; report issue |
500
- | **503** | `fastMode` budget exceeded | Retry after `retryAfterMs` or disable fast mode |
649
+ | Code | Meaning | What to try |
650
+ |------|---------|-------------|
651
+ | **400** | Invalid URL | Run `validate()`; fix the link |
652
+ | **403** | Private or blocked | Cannot access without permission |
653
+ | **404** | Not found | Post deleted, wrong ID, or expired story |
654
+ | **429** | Rate limited | Wait and slow down; fewer parallel requests |
655
+ | **500** | Server / parse error | Retry; update package; open an issue |
656
+ | **503** | Fast mode: still fetching | Wait `retryAfterMs` and call `download` again |
501
657
  | **504** | Timeout | Increase `timeoutMs` |
502
658
 
503
- | Symptom | Fix |
504
- |---------|-----|
505
- | Carousel returns 1 image | Set `cookies` or `sessionId` |
506
- | Reel has no MP4 | Add session cookie |
507
- | CLI `Unexpected token 'npx'` | Use `;` or two lines in PowerShell |
508
- | `Invalid or unexpected token` on CLI | Run `npm run build`; use published version |
509
- | Caption has weird dots/lines | Post captions are flattened to one line by design |
510
- | 403 on CDN URL when downloading | Do not modify signed URL query string |
511
-
512
659
  ---
513
660
 
514
- ## Examples in this repo
515
-
516
- | File | Description |
517
- |------|-------------|
518
- | [`examples/basic.mjs`](./examples/basic.mjs) | Minimal JSON dump |
519
- | [`examples/bot-example.ts`](./examples/bot-example.ts) | Generic bot handler |
520
- | [`examples/express-api.ts`](./examples/express-api.ts) | REST API with Express |
521
- | [`examples/fastify-api.ts`](./examples/fastify-api.ts) | REST API with Fastify |
522
- | [`examples/telegram-bot.ts`](./examples/telegram-bot.ts) | Telegram-style handler |
523
- | [`examples/discord-bot.ts`](./examples/discord-bot.ts) | Discord-style handler |
524
- | [`examples/cookie-generator.mjs`](./examples/cookie-generator.mjs) | Cookie helper notes |
525
-
526
- Run locally after build:
661
+ ## 15. FAQ and troubleshooting
527
662
 
528
- ```bash
529
- npm run build
530
- node examples/basic.mjs "https://www.instagram.com/p/SHORTCODE/"
531
- ```
663
+ **Q: Carousel only returns one image.**
664
+ A: Add `INSTAGRAM_COOKIES` or `sessionId` ([section 8](#8-instagram-session--why-and-how)).
532
665
 
533
- **Live Instagram tests** are kept in a separate repo folder: `ultra-igdl-live-test` (not published to npm).
666
+ **Q: Reel has no video, only thumbnail.**
667
+ A: Same — use a logged-in session cookie.
534
668
 
535
- ---
669
+ **Q: Story returns 404.**
670
+ A: Stories expire after 24 hours, or the URL is wrong. Session is required.
536
671
 
537
- ## Architecture
672
+ **Q: CLI works on Mac but fails on PowerShell.**
673
+ A: Quote the URL; set env vars on a separate line or use `;` before `npx`.
538
674
 
539
- ```
540
- src/
541
- ├── core/ # downloader orchestration, cache, parser, extractor
542
- ├── extractors/ # post, reel, story, highlight
543
- ├── network/ # undici client, headers, retry, pool, Instagram API
544
- ├── utils/ # captions, carousel, media quality, URLs
545
- ├── cli/ # CLI entry (published as ultra-igdl bin)
546
- └── types/ # TypeScript definitions
547
- ```
675
+ **Q: Downloaded file from CDN is corrupt or 403.**
676
+ A: Copy the `url` exactly from the API response. Do not strip query parameters.
548
677
 
549
- **Extraction layers** (first useful result wins, posts scan multiple layers for carousels):
678
+ **Q: Caption looks like one long line.**
679
+ A: Post captions are normalized to a single clean line by design (engagement text is in `engagement`, not `caption`).
550
680
 
551
- 1. Open Graph / meta tags
552
- 2. Embedded `application/json` / script blobs
553
- 3. `window.__additionalDataLoaded` / `_sharedData`
554
- 4. Next.js `__NEXT_DATA__`
555
- 5. GraphQL / CDN discovery in HTML
556
- 6. Regex fallback
681
+ **Q: How do I update?**
682
+ A: `npm update ultra-igdl` or bump version in `package.json` and run `npm install`.
557
683
 
558
- With **session**: parallel `media/info` API for posts (carousels), reels, stories, highlights.
684
+ **Q: Does this need an Instagram API key?**
685
+ A: No. It uses the same kind of page parsing and optional session API as a logged-in browser.
559
686
 
560
687
  ---
561
688
 
562
- ## Development
689
+ ## 16. Examples in this repository
563
690
 
564
- ```bash
565
- git clone https://github.com/your-username/ultra-igdl.git
566
- cd ultra-igdl
567
- npm install
568
- npm run build
569
- npm test
570
- npm run test:coverage
571
- npm run test:stress
572
- ```
573
-
574
- | Script | Purpose |
575
- |--------|---------|
576
- | `npm run build` | Compile ESM + CJS + CLI to `dist/` |
577
- | `npm test` | Unit + integration tests (mocked HTTP; excludes stress) |
578
- | `npm run cli -- "<url>" --json` | Run CLI from source tree |
579
- | `npm run lint` | Typecheck |
691
+ After cloning, build once: `npm run build`.
580
692
 
581
- ---
582
-
583
- ## Publishing to npm
693
+ | File | What it shows |
694
+ |------|----------------|
695
+ | [`examples/basic.mjs`](./examples/basic.mjs) | Minimal JSON output |
696
+ | [`examples/bot-example.ts`](./examples/bot-example.ts) | Generic bot handler |
697
+ | [`examples/express-api.ts`](./examples/express-api.ts) | REST API with Express |
698
+ | [`examples/fastify-api.ts`](./examples/fastify-api.ts) | REST API with Fastify |
699
+ | [`examples/telegram-bot.ts`](./examples/telegram-bot.ts) | Telegram-style flow |
700
+ | [`examples/discord-bot.ts`](./examples/discord-bot.ts) | Discord-style flow |
701
+ | [`examples/cookie-generator.mjs`](./examples/cookie-generator.mjs) | Cookie setup notes |
584
702
 
585
- Maintainers:
703
+ Run basic example:
586
704
 
587
705
  ```bash
588
- # 1. Login
589
- npm login
590
-
591
- # 2. Set author/repository in package.json (your GitHub username)
592
-
593
- # 3. Dry run — only dist/, README, LICENSE should be listed
594
- npm pack --dry-run
595
-
596
- # 4. Publish (runs build + tests via prepublishOnly)
597
- npm publish
706
+ npm run build
707
+ node examples/basic.mjs "https://www.instagram.com/p/SHORTCODE/"
598
708
  ```
599
709
 
600
- Consumers install with:
710
+ ---
601
711
 
602
- ```bash
603
- npm install ultra-igdl
604
- ```
712
+ ## 17. Legal and privacy
605
713
 
606
- **Before first publish:** change `repository`, `bugs`, and `homepage` in `package.json` from `your-username` to your real GitHub path.
714
+ - **Not affiliated** with Instagram or Meta.
715
+ - You must follow **Instagram’s Terms of Use** and your local laws. Only download content you are allowed to use.
716
+ - **Session cookies are credentials** — never commit them, share them publicly, or log them in production.
717
+ - CDN URLs are **temporary signed links** — download soon; do not alter the URL.
607
718
 
608
719
  ---
609
720
 
610
- ## Legal & disclaimer
721
+ ## 18. License
611
722
 
612
- - This project is **not affiliated with Instagram / Meta**.
613
- - You are responsible for complying with Instagram's Terms of Use and applicable laws.
614
- - Only download content you have the right to access and use.
615
- - Session cookies are credentials — treat them like passwords.
616
- - CDN URLs are **signed** and expire; download promptly and do not strip query parameters.
723
+ [MIT](./LICENSE) free to use with attribution.
617
724
 
618
725
  ---
619
726
 
620
- ## License
621
-
622
- [MIT](./LICENSE) © 2026 ultra-igdl contributors
727
+ **Need help?** Open an issue: [github.com/WH173-5P1D3R/ultra-igdl/issues](https://github.com/WH173-5P1D3R/ultra-igdl/issues)