socialdl-mcp
Downloads images and videos from Facebook accounts into per-account folders, with support for limits, date filtering, captions, and metadata.
Downloads images and videos from Instagram accounts into per-account folders, with support for limits, date filtering, top-liked ranking, captions, and metadata.
Downloads images and videos from TikTok accounts into per-account folders, with support for limits, date filtering, captions, and metadata.
socialdl
Save images and videos from public social accounts — Instagram, TikTok, and Facebook — into tidy, per-account folders. Built for AI agents as well as humans: it ships as a CLI (with JSON output), an MCP server, an HTTP REST API, and an importable Python library, all sharing one core that returns structured, machine-readable results.
Under the hood it drives gallery-dl, the actively-maintained downloader that handles each platform's quirks.
downloads/
├── instagram/natgeo/ photo.jpg photo.jpg.json photo.jpg.txt ...
├── tiktok/nasa/ ...
└── facebook/NASA/ ...Before you use this: it downloads only what your own account can already see, but you are responsible for respecting each platform's Terms of Service, copyright, and privacy. Authenticating with your cookies can get that account banned. See Legal & responsible use.
Setup
./setup.sh # venv + editable install + links socialdl/socialdl-mcp/socialdl-serve into ~/.local/binThis installs three commands (from the venv): socialdl, socialdl-mcp,
socialdl-serve.
Related MCP server: Instagram Download MCP Server
Authentication (read this first)
As of 2026, these platforms block anonymous access and require login even for
public accounts — without credentials most fetches fail (NotFoundError,
403 Forbidden). Provide a cookies.txt exported from a browser where
you're logged in — this is the portable choice for headless/agent use:
Export with a "cookies.txt" browser extension (Netscape format), or
yt-dlp --cookies-from-browser firefox --cookies cookies.txtto generate one.Pass it as
--cookies cookies.txt(CLI), thecookiesfield (MCP/HTTP), or setcookiesin the config file.
For interactive/local use you can instead read cookies live from a browser
with --cookies-from-browser firefox (not available on headless servers).
⚠️ Account-ban risk — use a throwaway account, not your main one. Your cookies make every request run as your account. Instagram, TikTok, and Facebook actively detect automated access and may rate-limit, temporarily "action-block", or permanently ban the account whose cookies you use — this happens even at slow speeds, and people have had accounts flagged this way. To stay safe:
Use a secondary "burner" account you can afford to lose — never your personal/main account.
Keep volume low: scope with
--limit,--since, and--top-likedinstead of pulling entire histories.If you hit
429 Too Many Requestsor an action-block, stop and wait hours or days — retrying aggressively lengthens the ban.A ban is a risk you accept by using cookies; this tool can't prevent it.
The four interfaces
1. CLI (with --json)
socialdl natgeo --platform instagram --images-only --cookies cookies.txt
socialdl https://www.instagram.com/natgeo/ --json # machine-readable
socialdl @nasa -p tiktok --probe --json # dry-run: what WOULD download--json prints the structured result (below) to stdout; exit code is 0 on
success, 1 otherwise — ideal for agents that shell out.
2. MCP server
socialdl-mcp # speaks MCP over stdioRegister it with an MCP client. Example Claude Desktop / Claude Code config:
{ "mcpServers": { "socialdl": { "command": "/ABSOLUTE/PATH/TO/socialdl/.venv/bin/socialdl-mcp" } } }Tools exposed: download_media, probe_media, supported_platforms —
each with typed parameters (target, platform, limit, images_only,
videos_only, since, until, metadata, captions, cookies, out, …).
3. HTTP REST API
socialdl-serve --host 127.0.0.1 --port 8000 # OpenAPI docs at /docsMethod | Path | Body / Result |
|
|
|
|
|
|
|
|
|
|
|
|
curl -X POST http://127.0.0.1:8000/download -H 'Content-Type: application/json' \
-d '{"target":"natgeo","platform":"instagram","images_only":true,
"limit":10,"cookies":"/path/cookies.txt"}'Bind to 127.0.0.1 for local agents; only use --host 0.0.0.0 on a trusted
network (there is no auth layer).
4. Python library
from socialdl import download, probe, DownloadOptions
result = download(DownloadOptions(
target="natgeo", platform="instagram",
images_only=True, limit=10, cookies="cookies.txt",
))
print(result.to_dict())
for f in result.downloaded:
print(f.type, f.path, f.size_bytes)Structured result
Every interface returns the same shape:
{
"ok": true,
"target": "natgeo",
"platform": "instagram",
"account": "natgeo",
"source_url": "https://www.instagram.com/natgeo/",
"output_dir": ".../downloads/instagram/natgeo",
"downloaded": [
{"path": ".../photo.jpg", "filename": "photo.jpg", "type": "image", "size_bytes": 161547}
],
"downloaded_count": 1,
"skipped_count": 0, // already present (deduped via archive)
"wrote_metadata": false,
"wrote_captions": false,
"simulated": false, // true for probe
"exit_code": 0,
"errors": []
}Options reference
Option | CLI flag | MCP/HTTP field | Meaning |
Platform |
|
|
|
Limit |
|
| Most-recent N items |
Images only |
|
| Skip videos |
Videos only |
|
| Skip images |
Since |
|
| Posts on/after date |
Until |
|
| Posts on/before date |
Top by likes |
|
| Rank posts by likes; take the top N (Instagram) |
Metadata |
|
| Write |
Captions |
|
| Write |
Cookies |
|
| Path to a |
Output dir |
|
| Base download folder |
No archive |
|
| Ignore dedup archive; re-fetch |
Backfill sidecars |
|
| Write captions/metadata for files already downloaded (no new media) |
Timeout |
|
| Max seconds to run |
Probe |
| (own endpoint/tool) | Dry-run; report without downloading |
Filtering by date and type
Feeds are newest-first, so --since stops early once it reaches posts older
than the cutoff — it won't crawl a whole back-catalog.
Caveat on dates + videos: date filtering is reliable for images. Videos
(esp. reels) are fetched through a path that can ignore the date filter, so on
video-heavy/video-only accounts since/until may pull more than the window.
For precise date-bounded results, add images_only.
Most-liked posts (--top-liked)
Instagram only serves posts newest-first — there's no "sort by popularity". So
--top-liked N scans a window of posts, reads each one's like count, ranks
them, and downloads the top N:
# the 5 most-liked videos since a date:
socialdl natgeo -p instagram --videos-only --since 2025-06-01 --top-liked 5
# preview the ranking first, without downloading:
socialdl natgeo -p instagram --videos-only --since 2025-06-01 --top-liked 5 --probeScope the scan with
--since(and it stops early past the cutoff) — an unbounded scan is slow, so a date or recent window is strongly recommended.--videos-onlyranks video posts (reels/tv);--images-onlyranks the rest.Instagram-only for now; scanning a large window can take minutes (you'll see live progress). The
probeform is cheap — it ranks without downloading.Limitation: video posts inside regular feed carousels aren't classified as "video" during ranking (reels/tv are); the date boundary is also fuzzy for reels (same reason as the date caveat above).
Captions & metadata
Next to photo.jpg you get photo.jpg.txt (the caption, via captions) and/or
photo.jpg.json (full metadata: description, date, likes, tags,
post_url, username, … via metadata). Carousels get one sidecar per image.
Backfilling already-downloaded files. A normal re-run skips posts already in
the archive, so it won't add sidecars to files you grabbed earlier. --backfill
writes captions+metadata for the media already on disk without re-downloading
anything (posts you never downloaded are left alone):
socialdl natgeo -p instagram --backfillRe-running (sync)
Re-running a target is cheap and safe: a .archive.sqlite in each account folder
records what's downloaded, so a rerun only fetches new posts and never
duplicates. no_archive forces a full re-fetch; deleting downloads resets it.
Config file & env vars
Reusable defaults live in ~/.config/socialdl/config.toml (see
config.example.toml). Precedence is
explicit value > env var > config file > built-in default:
cookies = "/home/you/cookies.txt" # or cookies_from_browser = "firefox"
# out = "/home/you/Pictures/socials"
# captions = true
# metadata = trueEnv vars: SOCIALDL_COOKIES, SOCIALDL_COOKIES_FROM_BROWSER, SOCIALDL_OUT,
SOCIALDL_METADATA, SOCIALDL_CAPTIONS, SOCIALDL_CONFIG, and for the server
SOCIALDL_HOST / SOCIALDL_PORT.
Notes & limitations
Platforms change and rate-limit constantly. If a fetch fails or returns nothing, check credentials first, then update the engine:
.venv/bin/pip install -U gallery-dl yt-dlp.The HTTP server has no built-in authentication — keep it on localhost.
Legal & responsible use
This is a tool for saving media you have a legitimate right to access. By using it you agree that you are solely responsible for how you use it.
Respect Terms of Service. Automated downloading may be restricted by Instagram/TikTok/Facebook's terms. You are responsible for complying with the terms of any service you access.
Respect copyright and privacy. Content belongs to its creators. Don't redistribute, republish, or use downloaded media without the rights to do so, and don't use this tool to harvest or target private individuals.
Don't hammer the sites. Use reasonable limits (
--limit,--since) and don't run aggressive, high-volume scraping.Account-ban risk is on you. Authenticating with your cookies can get that account rate-limited or banned (see the warning in Authentication). Use a disposable account; the maintainers are not liable for banned accounts.
No affiliation. This project is not affiliated with, endorsed by, or sponsored by Instagram, TikTok, Facebook/Meta, or ByteDance. All trademarks belong to their respective owners.
The software is provided "as is", without warranty of any kind (see LICENSE).
Related projects
socialdl is far from the only tool in this space — it deliberately stands on the shoulders of mature downloaders rather than reinventing them:
gallery-dl — the multi-site engine socialdl drives under the hood.
yt-dlp — video downloader (used by gallery-dl for some video content).
Instaloader — Instagram-specialised downloader (profiles, stories, hashtags).
cobalt — privacy-first, no-account media downloader across many platforms.
What socialdl adds: a single, small, agent-friendly layer over gallery-dl
that exposes the same structured operation through a CLI, an MCP server, and
an HTTP API — plus conveniences like like-ranking (--top-liked), sidecar
backfill, and JSON output. If you just want a one-off download, the tools above
may serve you directly.
Contributing
Contributions are welcome — see CONTRIBUTING.md. Run the tests
with pytest (they're offline). Please add tests for logic you change.
License
MIT © socialdl contributors.
This server cannot be deployed
Maintenance
Related MCP Connectors
Get social media data from Instagram and TikTok: profiles, posts, videos, comments, and more.
- MysocialOAuthio.mysocial
Social media MCP server: your Instagram, TikTok, YouTube, LinkedIn and Threads history for your AI.
Social media analytics, video analysis, and competitor intel for any MCP-compatible AI agent.
MCP server for QPost — lets AI agents publish video and image posts to YouTube, TikTok, Instagram.
Related MCP Servers
- AlicenseBqualityCmaintenanceQuery social media data from Instagram, TikTok, Twitter/X, Threads, YouTube, Facebook, and Reddit directly through natural language commands. Retrieves profiles, posts, videos, and engagement metrics using the SociaVault API.1132 npm1MIT
- AlicenseAqualityCmaintenanceEnables AI assistants to download Instagram content including posts, videos, reels, stories, highlights, and profile pictures using Instaloader, with optional metadata and caption extraction.5MIT
- FlicenseBqualityCmaintenanceProvides Instagram analytics, media downloads, and search capabilities through an MCP interface for use with Claude and other MCP clients.4341-
- FlicenseNot gradedqualityCmaintenanceA remote MCP server that provides tools to query live Meta (Facebook+Instagram) and TikTok organic social data, such as follower counts, insights, recent posts, and aggregated overviews.-