@kartikk-k/instadl
v1.0.0
Published
Download Instagram reels & posts (images + videos) from the command line — no login, no API keys. Reuses an existing Chrome/Chromium instead of bundling one.
Downloads
81
Maintainers
Readme
instadl
Download Instagram reels & posts (images + videos) from the command line — no login, no API keys, no paid services. Runs entirely on your machine.
Small on purpose: it ships no bundled browser. It reuses a Chrome/Chromium you already have (your regular Google Chrome, or Playwright's cached Chromium). One tiny dependency (playwright-core); the whole package is ~10 kB.
How it works
Instagram serves a login wall to plain HTTP requests, so this drives a real downloader site in a headless browser and intercepts the JSON its own front-end receives — a direct CDN URL + metadata. The site does the anti-bot signing; we just read the result. Two independent providers (sssinstagram, fastvideosave) are tried with fallback + retry, so if one is throttled the other takes over.
- Reels → the video (720p — see Quality below).
- Carousel posts → all images/videos, numbered in order.
Install
npm install -g @kartikk-k/instadlThe package is scoped, but the command you run is just instadl.
Requires Node ≥ 18 and a Chromium-based browser on the machine. If none is found, instadl tells you exactly how to fix it. To install a clean one:
npx playwright install chromiumOr point at any Chrome/Chromium yourself:
export INSTADL_BROWSER="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"CLI usage
# Download everything (default). Reel → 1 file, carousel → all items.
instadl https://www.instagram.com/reel/DbUuKZEBmyE/
instadl https://www.instagram.com/p/DbZiJnLmhRk/ --out ~/Desktop/pics
# Just get the media URLs + metadata, don't download:
instadl resolve https://www.instagram.com/reel/DbUuKZEBmyE/ --jsonCommands
| Command | Description |
|---|---|
| instadl <url> [opts] | download all media (shorthand for download) |
| instadl download <url> [opts] | download media to disk |
| instadl resolve <url> [--json] | print media URLs + metadata only |
Options
| Option | Description |
|---|---|
| -o, --out <dir> | output directory (default ~/Downloads/insta-downloads, or $INSTADL_OUT) |
| -i, --index <n> | only item n (0-based) of a carousel |
| --first | only the first item |
| --json | machine-readable JSON on stdout (progress goes to stderr) |
| -q, --quiet | no progress logging |
| -h, --help / -v, --version | help / version |
Accepts /reel/, /reels/, /p/, /tv/ URLs or a bare shortcode.
Carousel files are saved as <shortcode>_1.jpg, <shortcode>_2.jpg, …, keeping each slide's position (a video slide stays e.g. <shortcode>_13.mp4).
Using it from another app (e.g. a Mac menu-bar app)
instadl is built to be consumed programmatically. Run it with --json; parse stdout (all logging is on stderr, so stdout is always clean JSON). Exit codes let you branch on failure.
// instadl resolve <url> --json
{
"provider": "sssinstagram",
"username": "baza_vse.svoi",
"shortcode": "DbUuKZEBmyE",
"title": "…caption…",
"is_carousel": false,
"count": 1,
"medias": [
{ "url": "https://…mp4", "type": "mp4", "ext": "mp4", "quality": 720, "label": "720p", "index": null }
]
}// instadl download <url> --json
{ "ok": true, "provider": "sssinstagram", "username": "…", "shortcode": "…",
"is_carousel": true, "outDir": "/…", "count": 15,
"files": [ { "path": "/…/DbZiJnLmhRk_1.jpg", "filename": "DbZiJnLmhRk_1.jpg", "type": "jpg" } ] }// any failure, with --json
{ "ok": false, "error": "The download link not found.", "code": "FAIL" }Exit codes
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | usage error (bad/missing arguments) |
| 2 | resolve/download failed (private, removed, invalid URL, or all providers failed) |
| 3 | no usable browser found / browser failed to launch |
Or import it directly (Node)
import { resolve } from '@kartikk-k/instadl';
const data = await resolve('https://www.instagram.com/p/DbZiJnLmhRk/');
console.log(data.count, data.medias.map(m => m.url));Quality
- Images: highest the CDN serves (full-resolution JPEG).
- Videos: 720p. Instagram encodes 1080p too, but only as signature-gated DASH streams that the free downloader services don't expose — the one-click link is 720p. True 1080p would need a yt-dlp-style path (often requires login cookies).
Notes & limits
- Depends on third-party downloader sites staying roughly the same. If both break, the selectors / intercepted URL patterns in
src/engine.mjsmay need a tweak; adding a provider is ~30 lines. - Only download content you have the right to. It never logs into your account.
Files
src/engine.mjs— headless resolver, multi-provider fallback, retry.src/browser.mjs— finds/launches an existing Chrome/Chromium (no bundled browser).src/cli.mjs— theinstadlcommand.
