--- name: instagram-post-downloader description: "Download and save Instagram posts as high-resolution files. Use when asked to download, save, or archive an Instagram post, reel thumbnail, or carousel. Produces saved high-res images in a named folder, with carousel slides stitched into a single PDF; supports batch downloading of multiple URLs at once." --- # Instagram Post Downloader Skill Downloads Instagram posts at full resolution from Instagram's CDN — no screenshots, no compression. Handles single images, carousels (multi-slide posts), and Reel cover images. For carousels, produces individual slide files plus a single stitched PDF. Supports batch URLs in one run. --- ## PREREQUISITE — Domain Allowlist Before this skill can fetch any media, you must add Instagram's CDN domain to Claude Code's allowlist: **Settings → Capabilities → Domain allowlist → Add:** ``` *.cdninstagram.com ``` Without this, all CDN fetch calls will be blocked. If you see a permission error when Claude attempts a fetch to `cdninstagram.com`, this is the fix. --- ## Required Inputs Claude will ask for these if not provided upfront: | Input | Required | Notes | |---|---|---| | Instagram post URL(s) | Yes | One per line, or comma-separated. `https://www.instagram.com/p/XXXX/` or `https://www.instagram.com/reel/XXXX/` format | | Output directory | No | Defaults to `./instagram-downloads/` in the current working directory | | PDF stitch for carousels | No | Defaults to **yes** — produces `carousel.pdf` alongside individual slides | | File naming prefix | No | Optional prefix added before slide filenames, e.g. `brand_` → `brand_slide_01.jpg` | **Batch input example:** ``` https://www.instagram.com/p/ABC123/ https://www.instagram.com/p/DEF456/ https://www.instagram.com/p/GHI789/ ``` --- ## Output Structure For each URL processed, Claude creates a folder named after the post caption (first 40 characters, sanitised — spaces become underscores, special characters stripped). If no caption is available, the folder is named after the post shortcode. ### Single image post ``` instagram-downloads/ └── this_is_the_caption_first_40_chars/ ├── image.jpg └── metadata.txt ``` ### Carousel post ``` instagram-downloads/ └── carousel_caption_first_40_chars/ ├── slide_01.jpg ├── slide_02.jpg ├── slide_03.jpg ├── slide_04.jpg ├── carousel.pdf ← all slides stitched in order └── metadata.txt ``` ### Batch run (3 URLs) ``` instagram-downloads/ ├── first_post_caption_sanitised/ │ ├── image.jpg │ └── metadata.txt ├── second_post_carousel_caption/ │ ├── slide_01.jpg │ ├── slide_02.jpg │ ├── carousel.pdf │ └── metadata.txt └── third_post_caption_here/ ├── image.jpg └── metadata.txt ``` ### metadata.txt format ``` Post URL: https://www.instagram.com/p/XXXX/ Shortcode: XXXX Type: carousel | single_image | reel Slide count: 4 (carousel only) Caption: [full caption text] Username: @username Fetched at: 2026-05-27T14:32:00Z CDN URLs: slide_01.jpg https://scontent.cdninstagram.com/v/... slide_02.jpg https://scontent.cdninstagram.com/v/... ``` ### Completion summary (printed to terminal) ``` Instagram Post Downloader — Batch Complete ========================================== URLs processed: 3 Posts saved: 3 Total files: 11 (9 images + 2 PDFs) Skipped: 0 Output dir: /Users/you/project/instagram-downloads/ Results: ✓ this_is_the_caption_first_40_chars/ 1 image ✓ carousel_caption_first_40_chars/ 4 slides → carousel.pdf ✓ third_post_caption_here/ 1 image ``` --- ## How Claude Should Execute This Skill ### Step 1 — Collect and validate inputs 1. Accept the URL(s) from the user. If the user pastes a comma-separated list, split on commas. If they paste one per line, split on newlines. 2. Validate each URL matches `instagram.com/p/`, `instagram.com/reel/`, or `instagram.com/tv/`. Flag malformed URLs before proceeding. 3. Confirm the output directory. If none provided, use `./instagram-downloads/` and tell the user. 4. Ask about PDF stitching preference only if the user hasn't said either way. Default is yes. ### Step 2 — For each URL: fetch the post page Fetch the Instagram post page HTML: ``` GET https://www.instagram.com/p/{shortcode}/?__a=1&__d=dis ``` Instagram frequently changes its API surface. Use this fallback chain in order: **Attempt A — JSON endpoint:** ``` https://www.instagram.com/p/{shortcode}/?__a=1&__d=dis ``` Parse the JSON response. Look for `graphql.shortcode_media` or `data.shortcode_media`. **Attempt B — Embed page (most reliable):** ``` https://www.instagram.com/p/{shortcode}/embed/captioned/ ``` Fetch this page's HTML and extract `og:image` meta tags and any `window.__additionalDataLoaded` or `window.__StaticData` JSON blobs embedded in `