ultra-igdl 1.0.0 → 1.0.2

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