
Instaloader Alternative API
If you use Instaloader to download Instagram Reels, posts or Stories and want to stop running a logged-in session, a hosted API replaces it with one HTTP call: send the public link, get the media URLs. Instaloader's documentation marks Stories and Highlights as "Requires login"; with this API no Instagram account of yours is involved.

Key facts
- Endpoint
- POST /v1/resolve (one endpoint for every service)
- 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
Instaloader and this API side by side
| Instaloader | GetInSaver API | |
|---|---|---|
| What it is | Free, open-source Python tool you run yourself | Hosted REST API, any language |
| Instagram login | Its docs mark --stories and --highlights as "Requires login" | Never; public content only |
| Stories and Highlights | With a logged-in account | Active public Stories and public Highlights |
| Other platforms | Instagram only | Instagram, TikTok, X, Pinterest, Telegram |
| Profiles, followers, hashtags | Yes (some need login) | No: one link in, its media out |
| Cost | Free; your server, your account, your IP | 20 free credits, then prepaid from $19; failed requests cost 0 |
Keep Instaloader if you need whole-profile archives, follower lists or hashtag feeds. Use the API when your product gets single links from users and must not depend on an Instagram session.
Migrating: one function instead of a session
Where your code builds a post from a shortcode, send the link instead. This is the complete client; resolve() also covers Stories (instagram-story) and Highlights (instagram-highlight):
# pip install requests
import mimetypes, os, time
import requests
API_URL = "https://developers.getinsaver.com/v1/resolve"
API_KEY = os.environ["GIS_KEY"] # keep the key on your server, never in a browser
def resolve(service, url, max_results=10, retries=3):
"""Turn a public link into media items: [{"type": "video", "url": ...}]."""
for attempt in range(retries + 1):
response = requests.post(
API_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
json={"service": service, "url": url, "max_results": max_results},
timeout=130,
)
data = response.json()
if response.ok:
return data
# 429 = rate or concurrency limit, 502/504 = platform hiccup; none of them is charged
if response.status_code in (429, 502, 504) and attempt < retries:
time.sleep(int(response.headers.get("Retry-After", 5)))
continue
raise RuntimeError(f"{data['code']}: {data['message']}")
def download(item, name, folder="downloads"):
"""Media URLs expire within minutes to hours, so save the file right away."""
os.makedirs(folder, exist_ok=True)
with requests.get(item["url"], stream=True, timeout=120) as media:
media.raise_for_status()
kind = media.headers.get("Content-Type", "").split(";")[0]
path = os.path.join(folder, name + (mimetypes.guess_extension(kind) or ".bin"))
with open(path, "wb") as f:
for chunk in media.iter_content(chunk_size=65536):
f.write(chunk)
return path
if __name__ == "__main__":
# TikTok works the same way: resolve("tiktok", "https://www.tiktok.com/@user/video/123...")
result = resolve("instagram", "https://www.instagram.com/reel/SHORTCODE/")
print(f"{result['item_count']} items, {result['credits_used']} credits")
for i, item in enumerate(result["items"]):
print(item["type"], download(item, f"{result['request_id']}-{i}"))
Getting a key
- Create a free account and verify your email. You get 20 free credits, no card needed.
- Create an API key in Dashboard → API keys and store it as the environment variable
GIS_KEYon your server.
Errors to handle
| HTTP | Code | What to do |
|---|---|---|
| 402 | INSUFFICIENT_CREDITS | Top up, or lower max_results: a request reserves max_results × credits per result first. |
| 422 | UPSTREAM_REJECTED | The post is private, deleted, expired or login-only. Show the message to your user; nothing was charged. |
| 429 | RATE_LIMITED / CONCURRENCY_LIMIT | Wait for Retry-After seconds and retry. 120 requests per minute per account; 2 at once on the trial, 8 after buying credits. |
| 502 / 504 | UPSTREAM_* | Temporary platform failure. Safe to retry; nothing was charged. |
Every error body is JSON with a stable code and a readable message. The full list is in the API reference.
FAQ
Can it download private accounts like a logged-in Instaloader?
No. It does not log in and does not bypass privacy. Private, deleted and login-only content returns an error and costs nothing.
Does it download Stories without a login?
Yes, active Stories of public accounts, and one exact Story when the link contains its ID. Expired Stories are gone; use Highlights for saved ones.
Is there a Python package to install?
Only requests. The example on this page is the whole client.
Do failed requests cost credits?
No. Credits are reserved while a request runs and refunded in full when it fails or finds no media. You only pay for items that come back.
Related guides
- Python Instagram and TikTok Downloader API
- n8n Instagram Downloader API
- Node.js Social Media Downloader API
Updated 2026-10-30. The code on this page is executed by our test suite against the API server before every release.