From public URL to usable media.
Base URL https://developers.getinsaver.com/v1. JSON in, JSON out. One endpoint for every service.
At a glance
- Endpoint
- POST /v1/resolve (one endpoint for every service)
- Services
- 7: Instagram, Stories, Highlights, TikTok, X, Pinterest, Telegram
- Free trial
- 20 result credits after email verification, no card
- Price
- from $19 for 7,500 results ($1.33–$2.53 per 1,000)
- Billing
- prepaid credits, no subscription, no expiry; failed or empty requests cost 0
- Credits per result
- 1 (Instagram, TikTok, X, Pinterest) or 2 (Stories, Highlights, Telegram)
- Limits
- up to 20 items per request; 120 requests per minute per account; 2 in progress at once on the trial, 8 on paid accounts
- Payment
- card (Stripe) or USDT TRC20 (OxaPay)
Quickstart
- Create an account and verify your email (20 free credits).
- Create an API key in Dashboard → API keys. It is shown once; store it as
GIS_KEY. - Send your first request:
curl -X POST https://developers.getinsaver.com/v1/resolve \
-H "Authorization: Bearer $GIS_KEY" \
-H "Content-Type: application/json" \
-d '{"service":"instagram","url":"https://www.instagram.com/reel/SHORTCODE/","max_results":10}'const response = await fetch("https://developers.getinsaver.com/v1/resolve", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.GIS_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({"service":"instagram","url":"https://www.instagram.com/reel/SHORTCODE/","max_results":10})
});
const data = await response.json();
if (!response.ok) throw new Error(`${data.code}: ${data.message}`);
for (const item of data.items) console.log(item.type, item.url);import os, requests
response = requests.post(
"https://developers.getinsaver.com/v1/resolve",
headers={"Authorization": f"Bearer {os.environ['GIS_KEY']}"},
json={"service": "instagram", "url": "https://www.instagram.com/reel/SHORTCODE/", "max_results": 10},
timeout=130,
)
data = response.json()
response.raise_for_status()
for item in data["items"]:
print(item["type"], item["url"])<?php
$ch = curl_init("https://developers.getinsaver.com/v1/resolve");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 130,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("GIS_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"service" => "instagram",
"url" => "https://www.instagram.com/reel/SHORTCODE/",
"max_results" => 10,
]),
]);
$data = json_decode(curl_exec($ch), true);
foreach ($data["items"] ?? [] as $item) echo $item["type"], " ", $item["url"], "\n";Authentication
Send your key as a Bearer token on every request. Keys start with gis_live_. Revoke a leaked key in the dashboard; the others keep working.
Authorization: Bearer gis_live_••••••••••••••••
POST /v1/resolve
| Field | Type | Required | Description |
|---|---|---|---|
| service | string | yes | A service ID from the table below. |
| url | string | yes | The public link, up to 2,048 characters. |
| max_results | integer | no | Most items to return, 1–20. Default 10. Credits are reserved for this many and the unused part is refunded at once. |
Response
{
"ok": true,
"service": "instagram",
"source_url": "https://www.instagram.com/reel/SHORTCODE/",
"item_count": 1,
"items": [
{
"type": "video",
"url": "https://cdn.example/media.mp4"
}
],
"metadata": {
"title": null,
"author": "creator",
"caption": null
},
"request_id": "39a3bff5-0000-4000-8000-000000000000",
"credits_used": 1
}
items[].type is video, image or audio. request_id matches the row in your usage log. credits_used is what this call cost.
Services
| ID | Covers | Credits / result | Link format |
|---|---|---|---|
| Instagram Posts & Reels | 1 | instagram.com/p/... instagram.com/reel/... | |
| instagram-story | Instagram Stories | 2 | instagram.com/stories/username/... |
| instagram-highlight | Instagram Highlights | 2 | instagram.com/stories/highlights/... |
| tiktok | TikTok | 1 | tiktok.com/@user/video/... |
| x | X / Twitter | 1 | x.com/user/status/... |
| 1 | pinterest.com/pin/... pin.it/... | ||
| telegram | Telegram Public Media | 2 | t.me/channel/123 |
Credits
A request reserves max_results × credits per result, then settles to items returned × credits per result. If the request fails or returns nothing, the whole reservation is refunded. Your balance and every movement are visible in the dashboard.
Errors
Errors return JSON with error: true, a stable code and a readable message.
{
"error": true,
"code": "URL_INVALID",
"message": "Enter a valid Instagram Posts & Reels URL."
}
| HTTP | Code | Meaning |
|---|---|---|
| 400 | SERVICE_UNSUPPORTED | The service ID is not one of the IDs listed below. |
| 400 | URL_INVALID | The URL is not a valid link for the chosen service (for example a Story link sent as service instagram). |
| 401 | API_KEY_INVALID | Missing, revoked or unknown key, or the account's email is not verified. |
| 402 | INSUFFICIENT_CREDITS | The balance cannot cover max_results × the service's credits. Buy credits or lower max_results. |
| 422 | MEDIA_NOT_FOUND | The link resolved but contained no downloadable media. |
| 422 | UPSTREAM_REJECTED | The platform refused the link: private, deleted, expired or login-only content. Some failures carry a more specific code. |
| 429 | RATE_LIMITED | More than 120 requests in a minute on one account (all its keys together). Retry after the RateLimit-Reset header. |
| 429 | CONCURRENCY_LIMIT | The account already has its maximum number of requests in progress. Retry after the Retry-After header; nothing was charged. |
| 502 | UPSTREAM_INVALID_RESPONSE | Temporary provider failure. Safe to retry; nothing was charged. |
| 504 | UPSTREAM_TIMEOUT | The platform did not answer in time. Safe to retry; nothing was charged. |
Rate limits
120 requests per minute per account, shared by all of its API keys, with standard RateLimit headers. At most 2 requests can be in progress at once on the free trial and 8 once the account has bought credits; a request over that answers 429 CONCURRENCY_LIMIT with a Retry-After header and costs nothing. Requests can take up to two minutes for slow platforms, so set your client timeout to at least 130 seconds.
Media URLs
Returned URLs point at the platform's CDN or at a GetInSaver relay and are short-lived (minutes to a few hours). Download or proxy the file right after the call; do not store the URL for later.
Integration guides
- Python Instagram and TikTok Downloader API
- Node.js Social Media Downloader API
- PHP Instagram Downloader API
- n8n Instagram Downloader API
- Instaloader Alternative API
- Video Downloader API for Your Own Website
request_id.