Skip to content

API reference

Download any post's media with one call

Send a post link, get back direct links to its photos and videos. One endpoint, one key.

Quick start

curl -s -X POST https://omnimediaapi.com/v1/download \
  -H "X-API-Key: $OMNI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "User-Agent: my-agent/1.0" \
  -d '{"url":"https://www.instagram.com/p/XXXXXXXXXXX/"}'

Agent prompt

Paste this into Claude, ChatGPT or any agent that can run shell commands or HTTP requests. Put your key in the OMNI_API_KEY environment variable, never in the prompt.

You can download photos and videos from public social media posts with OmniMediaApi.

Call:
  POST https://omnimediaapi.com/v1/download
  Headers: X-API-Key: $OMNI_API_KEY, Content-Type: application/json,
           User-Agent: my-agent/1.0
  Body: {"url": ""}

Supported: Instagram (posts, reels, carousels), TikTok (videos, photo posts),
Threads, Facebook (videos only), X/Twitter, Pinterest, Douyin.

The answer has data.media[]: each item has "type" (image, video or audio)
and "url" (a direct CDN link). Rules:
- Download every url right away; links expire within hours.
- Skip "audio" items unless asked for sound.
- TikTok, Douyin, Facebook and Pinterest list the same video in several
  qualities: take only the first video whose quality contains "HD", else the
  first video.
- Instagram, Threads and X carousels list different files: take all of them.
- An item without "url" has "formats": take its first video, else first image.
- Save files with the extension from the url (.jpg, .mp4 ...).

Errors: 404 MEDIA_UNAVAILABLE (private/deleted, do not retry), 424
PROVIDER_UNAVAILABLE or 503 (retry once after 60 s), 429 (wait Retry-After
seconds; QUOTA_EXCEEDED means no downloads left this month).
Downloads left: GET https://omnimediaapi.com/v1/me (same headers, free to call).
Never print the API key.

Request

POST https://omnimediaapi.com/v1/download
X-API-Key: omni_your_key
Content-Type: application/json
User-Agent: my-agent/1.0

{"url": "https://www.instagram.com/p/XXXXXXXXXXX/"}
  • Authorization: Bearer omni_your_key works too.
  • The platform is detected from the link. Short links (vt.tiktok.com, pin.it, fb.watch) are fine.
  • Send your own User-Agent. User-Agents containing "python", the default of Python requests and urllib, are blocked by our firewall.
  • Use a client timeout of at least 60 seconds.

Response

{
  "success": true,
  "data": {
    "platform": "instagram",
    "type": "carousel",
    "title": "Post caption or null",
    "thumbnail": "https://…jpg",
    "media": [
      {"type": "image", "url": "https://…/1.jpg"},
      {"type": "video", "url": "https://…/2.mp4", "quality": "HD"}
    ]
  },
  "meta": {"request_id": "…", "latency_ms": 2140, "charged": true, "remaining": 87}
}
FieldMeaning
data.media[]The files to download. type is image, video or audio, read from the real file. Some items also have quality, width, height.
data.thumbnailA cover image. Not one of the post's own photos.
meta.chargedWhether this call used a download.
meta.remainingDownloads left: this month's plus credits.

Media URLs are direct CDN links. They expire, often within hours. Download them right away; if one returns 403 or 404, call the API again for fresh links.

Picking files

  • Carousels (Instagram, Threads, X) list different photos and videos in post order. Take all of them.
  • One video in several qualities (TikTok, Douyin, Facebook, Pinterest): take the first video whose quality contains "HD", else the first video.
  • TikTok photo posts return several images: those are separate photos.
  • Audio items are the post's sound. Skip them unless you need the audio.
  • An item without url has a formats list. Take its first video, else its first image.

Errors

{"success": false, "error": {"code": "MEDIA_UNAVAILABLE", "message": "…"}}
HTTPCodeWhat to do
400VALIDATION_ERRORMissing or unsupported link. Fix the link.
401UNAUTHORIZEDMissing, wrong or revoked key.
404MEDIA_UNAVAILABLEThe post is deleted, private or region-blocked. Do not retry.
424PROVIDER_UNAVAILABLEAll download sources failed this time. Retry once after 30–60 s.
429RATE_LIMITEDToo many requests this minute. Wait Retry-After seconds.
429QUOTA_EXCEEDEDNo downloads left. Upgrade or buy credits, or wait for the 1st of the month.
503SERVICE_UNAVAILABLETemporary. Retry after Retry-After seconds.

Errors never use up a download.

Usage & limits

Every /v1/download answer carries these headers:

HeaderMeaning
X-RateLimit-LimitRequests allowed per minute on your plan.
X-RateLimit-RemainingRequests left this minute.
X-Quota-RemainingDownloads left: this month's plus credits.

To check before a batch, call GET https://omnimediaapi.com/v1/me with the same key. It is free and returns the plan, downloads used and left, credits and the reset time.

{"success": true, "data": {"plan": "free", "monthly_limit": 100, "used_this_month": 37,
  "credits": 0, "remaining": 63, "requests_per_minute": 10,
  "resets_at": "2026-12-01T00:00:00+00:00", "resets_in_seconds": 2592000}}
PlanDownloads / monthRequests / minute
Free10010
Starter3,00030
Pro20,00060
Scale100,000120
  • Monthly downloads reset on the 1st (UTC). Credits never expire.
  • The same link with the same key within 10 minutes is not counted again.
  • A request takes 2–8 s, sometimes up to 20 s.
  • Health check: GET https://omnimediaapi.com/health, no key needed.

OpenAPI

A machine-readable description of the API is at https://omnimediaapi.com/openapi.json. Import it into Postman, an SDK generator or an agent framework that reads OpenAPI tools.