mcp-instagram
by smorand
README.md
# mcp-instagram
## Overview
MCP server for downloading Instagram content (videos, reels, audio, single images, carousels)
using yt-dlp, with an instaloader + httpx fallback for image-only posts that yt-dlp refuses.
Supports both stdio and HTTP streamable transports, selectable via a CLI argument.
**Tech Stack:** Python 3.13, FastMCP 2.x, yt-dlp, Typer, Pydantic, OpenTelemetry, Ruff, mypy
## Installation
```bash
uv tool install .
```
After installation, the `mcp-instagram` binary is available system-wide.
## Usage
### stdio mode (for Claude Desktop, pi)
```bash
mcp-instagram stdio
mcp-instagram stdio --verbose
mcp-instagram stdio --quiet
```
### CLI download
```bash
mcp-instagram dl 'https://www.instagram.com/reel/<code>/' # video (transcoded to H.264 if VP9)
mcp-instagram dl 'https://www.instagram.com/p/<code>/' # single image or carousel
mcp-instagram dl --audio 'https://www.instagram.com/reel/<code>/'
mcp-instagram dl -o /tmp/out --force 'https://...' 'https://...'
mcp-instagram dl --json 'https://www.instagram.com/reel/<code>/' # machine-readable, full caption
```
Routing is automatic: `get_metadata` decides video vs image, image posts go through
instaloader + httpx. Image extensions come from the HTTP `Content-Type`, since Instagram CDN
URLs often keep a `.heic` path while serving JPEG bytes. Existing files are skipped unless
`--force`.
#### Captions
Every result carries a `description` field holding the **full post caption**, hashtags included.
This is usually the richest source of information about a post (titles, names, lists), so read it
before analysing the media itself: yt-dlp only sets `title` to `"Video by <user>"`, never the
caption. The human-readable output prints the caption truncated at 500 characters; `--json`
prints the untruncated value. Logs go to stderr, so `dl --json ... > result.json` yields clean JSON.
### HTTP streamable mode
```bash
mcp-instagram http
mcp-instagram http --verbose
```
Default: `http://127.0.0.1:8000`
### Usage instructions for LLMs / agents
```bash
mcp-instagram skill
```
Prints the CLI usage guide (command, options, examples) to stdout. Point an agent at
this command instead of embedding the docs in a prompt: on demand, near-zero tokens.
## Configuration
All settings are loaded from environment variables (prefix `MCP_INSTAGRAM_`) or a `.env` file.
| Variable | Default | Description |
|---|---|---|
| `MCP_INSTAGRAM_OUTPUT_DIR` | `~/Downloads/instagram` | Directory where downloads are saved |
| `MCP_INSTAGRAM_COOKIES_FILE` | _(empty)_ | Path to a Netscape-format cookies.txt file |
| `MCP_INSTAGRAM_HTTP_HOST` | `127.0.0.1` | Host for HTTP mode |
| `MCP_INSTAGRAM_HTTP_PORT` | `8000` | Port for HTTP mode |
| `MCP_INSTAGRAM_DEBUG` | `false` | Enable debug mode |
Copy `.env.example` to `.env` and edit as needed. Unrelated keys in `.env` (for example
`INSTAGRAM_USERNAME` used by `scripts/list-saved.py`) are ignored, not rejected.
## Claude Desktop / pi MCP config (stdio)
Add to your `claude_desktop_config.json` or pi MCP config:
```json
{
"mcpServers": {
"mcp-instagram": {
"command": "mcp-instagram",
"args": ["stdio"]
}
}
}
```
## Cookies setup
Instagram limits access to public content and blocks most authenticated content without cookies.
To provide cookies, log into Instagram in your browser, export your cookies as a Netscape-format
`cookies.txt` file (e.g., using the "Get cookies.txt LOCALLY" Chrome extension), save it anywhere
on disk, then set `MCP_INSTAGRAM_COOKIES_FILE=/path/to/cookies.txt` in your `.env` or environment.
The file is passed directly to yt-dlp's `cookiefile` option.
## Tools
| Tool | Description |
|---|---|
| `download_video` | Download a video, reel, or IGTV. Returns local path and metadata. |
| `download_audio` | Download audio only as MP3. Returns local path and metadata. |
| `download_carousel` | Download all items in a carousel/sidecar post, or a single image post. Returns list of paths. |
| `get_metadata` | Fetch post metadata without downloading (title, duration, counts, full caption in `description`). |
## Development
```bash
make sync # Install dependencies
make check # Full quality gate (lint, format, typecheck, security, tests)
make test # Run tests only
make run ARGS='stdio --help'
```
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues