Download Instagram media β reels, carousels (all images), photos β via sessionid (instagrapi, recommended), Playwright setup wizard, or Apify dataset fallback. No password sharing required.
β 2026-07-07:
--loginmode is BROKEN. Meta deprecated the instagrapi login endpoint server-side. Use--setup(Playwright) or a manual--sessionidcookie instead.
Your AI agent already knows how to use this tool. Just install:
# Install the skill + CLI (recommended)
npx skills add cripterhack/ig-downloader-skillOr choose your platform:
| Platform | Command |
|---|---|
| Linux / macOS / Git Bash | curl -fsSL https://raw.githubusercontent.com/cripterhack/ig-downloader-skill/main/install.sh | bash |
| Windows PowerShell | iex (iwr -Uri https://raw.githubusercontent.com/cripterhack/ig-downloader-skill/main/install.ps1).Content |
| npx (Skills.sh) β | npx skills add cripterhack/ig-downloader-skill |
| From cloned repo | git clone https://github.com/cripterhack/ig-downloader-skill.git && cd ig-downloader-skill && ./install.sh |
Each installer will:
- β
Install the Python package (
ig-downloaderCLI viapip) - β Detect your AI agent (OpenCode, Claude Code, Codex CLI, Cursor)
- β
Copy the skill files (
SKILL.md+AGENTS.md) to your agent's skills directory - β Verify everything works
Zero configuration. No need to manually copy SKILL.md files or install dependencies one-by-one.
- Why This Tool Exists
- Quick Start
- Operation Modes
- Getting the Sessionid Cookie
- Installation
- Usage Guide
- Examples
- Output Structure
- Troubleshooting
- FAQ
- Contributing
- License
Traditional Instagram downloaders (instaloader, gallery-dl) fail with 403/NotFound errors because Instagram aggressively blocks scraping. The web page no longer embeds JSON data (__INITIAL_STATE__ removed). Solutions exist but each has tradeoffs:
| Approach | Issue |
|---|---|
instaloader |
403 on all GraphQL queries |
gallery-dl |
403 on direct URLs |
| Apify Actors | β Carousels: only 1st image. Old posts: GQL fails. Cost: ~$0.03/run. |
instagrapi GQL (no login) |
β Free, but only recent posts (<4 weeks) |
v2.2 solution: Two working authentication paths + one fallback:
- Sessionid (recommended) π₯: Cookie-only access via
instagrapi(no password, no 2FA). Full access to ALL posts, ALL carousel images, ANY date. - Apify (fallback): Dataset-based when no sessionid is available.
--setup: Playwright browser auto-extracts sessionid and saves to config.
--loginmode removed: Meta deprecated the underlying endpoint. Login via password no longer works.
flowchart LR
subgraph Auth[Authentication Layer]
direction TB
C1[config.json] -->|auto-loads| SID[sessionid]
CLI[--sessionid flag] --> SID
ENV[SESSIONID env var] --> SID
SETUP[--setup wizard] -->|Playwright| SID
CHROME[Chrome cookies] -->|fallback| SID
end
subgraph Download[Download Engine]
direction TB
SID --> instagrapi{instagrapi}
instagrapi -->|Sessionid| FULL[user_medias β ALL posts]
FULL --> CARR{media_type}
CARR -->|Photo| PHOTO[photo_download β .jpg]
CARR -->|Reel| REEL[video_download β .mp4]
CARR -->|Carousel| CAR[media_info β _01.jpg ... _0N.jpg]
end
subgraph Fallback[Apify Fallback]
direction TB
DATASET[Apify Dataset] --> TOON[toon-file / API]
TOON --> GQL{GQL β€4w?}
GQL -->|Yes| GOK[All images]
GQL -->|No| GFALL[Single thumbnail]
end
Download --> OUT[π YYYY-MM-DD/shortcode/]
Fallback --> OUT
# Option A β Universal installer (recommended)
curl -fsSL https://raw.githubusercontent.com/cripterhack/ig-downloader-skill/main/install.sh | bash
# Option B β From source
git clone https://github.com/cripterhack/ig-downloader-skill.git
cd ig-downloader-skill
./install.shThe installer auto-detects your AI agent (OpenCode, Claude Code, etc.), copies
the skill files, and installs the ig-downloader CLI globally.
ig-downloader --setupA browser opens. Log into Instagram. The sessionid cookie is saved automatically.
No password sharing. The
--setupwizard uses Playwright to capture a cookie only.
ig-downloader -u username -o ./my_downloadsNo --sessionid flag needed after setup β the CLI reads your saved config.
| Mode | How | Best For |
|---|---|---|
| Sessionid π₯ | instagrapi login via browser cookie |
Full access. All posts, all carousels, no date limit. No password sharing. |
| Apify (legacy) | unseenuser/IG-posts dataset |
No login at all. Carousels limited to 1 image for posts >4 weeks. |
| Setup | Playwright browser β captures cookie β saves config | One-time. Enables sessionid mode. |
| Feature | Sessionid | Apify |
|---|---|---|
| Authentication | Cookie sessionid |
None |
| All posts (any date) | β | β (catalog) |
| Carousels: ALL images | β
(via media_info()) |
β 1st image only (old posts) |
| Carousels: recent posts | β | β (GQL enhancement) |
| Private profiles | β (if you follow) | β |
| Session persistence | β
config.json |
N/A |
| Download method | instagrapi native |
requests + instagrapi GQL |
| Cost | $0 | ~$0.03/run |
| Setup time | 1 min (first time via --setup) | 5 min (Apify account) |
pip install playwright && playwright install chromium
python instagram_downloader.py --setupsequenceDiagram
actor User
participant Script as instagram_downloader.py
participant PW as Playwright Chromium
participant IG as instagram.com
participant FS as ~/.ig-downloader/config.json
Script->>PW: Launch headful browser
PW->>IG: Navigate to instagram.com
User->>IG: Log in (manual)
Note over IG: User enters credentials,<br/>2FA, or challenge codes
loop Every 3 seconds
Script->>PW: Poll context.cookies()
PW-->>Script: [cookies...]
end
Script->>FS: Save sessionid to config.json
Script->>PW: Close browser
Note over User,FS: β
Done β subsequent runs<br/>auto-load sessionid from config
- Launches a clean Chromium browser (no Chrome profile needed)
- You log into Instagram normally
- Script detects the
sessionidcookie automatically via Playwright'scontext.cookies() - Saves to
~/.ig-downloader/config.json - Done. No
--sessionidflag needed ever again.
Fallback chain: Playwright β Chrome extraction β manual paste prompt.
- Chrome β F12 β Application β Cookies β
www.instagram.com - Copy the
sessionidvalue - Run:
python instagram_downloader.py -u username --sessionid "YOUR_COOKIE"
$env:SESSIONID = "YOUR_COOKIE"
python instagram_downloader.py -u username -o ./downloads# Linux / macOS / Git Bash
curl -fsSL https://raw.githubusercontent.com/cripterhack/ig-downloader-skill/main/install.sh | bash
# Windows PowerShell
iex (iwr -Uri https://raw.githubusercontent.com/cripterhack/ig-downloader-skill/main/install.ps1).ContentThis installs both the Python CLI and the AI agent skill files (SKILL.md). After this, your AI agent can discover and use the skill automatically.
pip install git+https://github.com/cripterhack/ig-downloader-skill.git
ig-downloader --helpgit clone https://github.com/cripterhack/ig-downloader-skill.git
cd ig-downloader-skill
pip install -e .
python instagram_downloader.py --help# Install only for Codex CLI (not auto-detect)
./install.sh --agent codex
# Install only in current project directory
./install.sh --project
# Install for ALL supported agents
./install.sh --agent allThis project is a dual-layer tool: a Python CLI and an AI agent skill.
When you run the installer, it copies SKILL.md and AGENTS.md to your
agent's skill directory:
| Agent | Skill Directory |
|---|---|
| OpenCode | ~/.config/opencode/skills/instagram-downloader/ |
| Claude Code | ~/.claude/skills/instagram-downloader/ |
| Codex CLI | ~/.codex/skills/instagram-downloader/ |
| Cursor | ~/.cursor/skills/instagram-downloader/ |
| Generic | ~/.agents/skills/instagram-downloader/ |
In new sessions, the agent reads SKILL.md and learns how to invoke
ig-downloader optimally β including mode selection logic, flag reference,
error handling, and known issues.
Once the skill is loaded, your AI agent can:
- Auto-detect the best auth method (config β sessionid flag β setup β Apify)
- Download all media from any Instagram profile
- Handle errors gracefully (expired session, missing dependencies, 403s)
- Advise on setup if no sessionid is available
Once the skill is installed, just ask your agent:
"Download all Instagram posts from @username to ./downloads"
"I need to set up Instagram download β can you help?"
"Download only the reels from username using the apify dataset in data.txt"
"My session expired, help me set up Instagram again"
The agent will read SKILL.md, understand the available modes, and invoke
ig-downloader with the correct flags.
To confirm the skill is installed:
# Check if skill files exist
ls ~/.config/opencode/skills/instagram-downloader/SKILL.md
# Check if the CLI works
ig-downloader --versionThe script auto-detects which mode to use (priority order):
1. --sessionid flag / env var / config file / Chrome β Sessionid mode
2. --setup flag β Interactive setup wizard (Playwright)
3. --dataset/--toon-file β Apify mode (legacy)
| Flag | Description |
|---|---|
-u / --username HANDLE |
Target Instagram profile (required). |
--sessionid STR |
sessionid cookie (direct, skips config/env). |
--setup |
Interactive setup wizard (Playwright β Chrome β manual paste). |
-o / --output DIR |
Output directory (default: ./instagram_downloads). |
| Flag | Description |
|---|---|
--dataset ID |
Apify dataset ID. |
--api-token KEY |
Apify API token. |
--toon-file PATH |
Apify dataset as JSON/YAML file. |
--date-start YYYY-MM-DD |
Earliest post date. |
--date-end YYYY-MM-DD |
Latest post date. |
--type {reel,carousel,photo} |
Filter by post type. |
--own-only |
Only posts by --username. |
--mentions-only |
Only posts from other accounts. |
--no-instagrapi |
Disable GQL carousel enhancement. |
# After running --setup once
python instagram_downloader.py -u username -o ./downloadspython instagram_downloader.py \
-u username \
--sessionid "1234567890%3Aabcdef" \
-o ./downloadspython instagram_downloader.py --setuppython instagram_downloader.py \
--toon-file ./data.txt \
-u username \
--type reel \
--date-start YYYY-MM-DD \
--date-end YYYY-MM-DD \
-o ./reels_onlypython instagram_downloader.py \
--dataset <DATASET_ID> \
--api-token apify_api_xxx \
-u username \
-o ./downloadspython instagram_downloader.py \
-u username \
--flat \
-o ./flat_downloads<output-dir>/
βββ YYYY-MM-DD/
βββ <SHORTCODE>/ # Reel
β βββ <SHORTCODE>.mp4 # Video
β βββ <SHORTCODE>.jpg # Thumbnail
β βββ post_info.txt
βββ <SHORTCODE>/ # Photo
β βββ <SHORTCODE>.jpg # Full resolution
β βββ post_info.txt
βββ <SHORTCODE>/ # Carousel (all images)
βββ <SHORTCODE>.jpg # First image
βββ <SHORTCODE>_02.jpg # Image 2/N
βββ <SHORTCODE>_03.jpg # Image 3/N
βββ ...
βββ post_info.txt
Same structure, but carousels >4 weeks get _01.jpg only (single thumbnail).
shortcode: <SHORTCODE>
type: carousel
date: 2026-06-18T22:58:02.000Z
author: username
relation: own_post
url: https://www.instagram.com/p/<SHORTCODE>/
| Problem | Solution |
|---|---|
instagrapi not found |
pip install instagrapi |
playwright not found |
pip install playwright && playwright install chromium |
| "No sessionid found" | Run --setup or pass --sessionid flag. |
| "Login required" | sessionid expired. Re-run --setup. |
| Playwright browser doesn't open | Run playwright install chromium to download browser. |
| Chrome cookie extraction fails | Use --sessionid flag with cookie from DevTools manually. |
| 403 in Apify mode | CDN URL expired β re-run the Actor. |
| GQL timeout | Post >4 weeks β falls back to Apify thumbnail. |
| "No items" in sessionid mode | Check username; profile may be private and session may not follow it. |
| "No items parsed" in toon mode | Try --dataset API mode instead. |
python not found |
Use py or python3. |
Q: Does this share my Instagram password?
A: No. The script uses a sessionid cookie β no password is ever sent or stored.
Q: How does --setup work?
A: It launches a clean Chromium browser via Playwright. You log into Instagram normally. The script extracts the sessionid cookie via Playwright's context.cookies() API. No passwords are transmitted to the script.
Q: How long does the sessionid last?
A: Days to weeks. When it expires, re-run --setup (takes 30 seconds).
Q: Can I download private profiles? A: Sessionid mode can download profiles your account follows. Apify mode only works for public profiles.
Q: Can I download stories / highlights? A: No. This tool downloads profile posts and reels only.
Q: Do I still need Apify? A: No. Sessionid mode replaces Apify entirely for most use cases. Apify mode is kept as a fallback.
Q: Does it work on Linux / macOS?
A: Yes. --setup uses Playwright (cross-platform). Linux/macOS: install playwright and you're set.
See CONTRIBUTING.md. Open issues, fork, submit PRs.
Copyright (C) 2026 Edgar Zorrilla
GNU General Public License v2.0. See LICENSE.