
PHP Instagram Downloader API
To download Instagram media from PHP, POST the public link to https://developers.getinsaver.com/v1/resolve with cURL and save each URL from the items array. It needs only the curl extension, so it runs on shared hosting and inside WordPress, with no scraper to maintain when Instagram changes.

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
Steps
- 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. - Save the script below as
resolve.phpand runGIS_KEY=gis_live_... php resolve.php, or include the two functions in your project.
Complete PHP example
<?php
// PHP 7.4+ with the curl extension. Run: GIS_KEY=gis_live_... php resolve.php
const GIS_API_URL = "https://developers.getinsaver.com/v1/resolve";
function gis_resolve(string $service, string $url, int $maxResults = 10, int $retries = 3): array
{
for ($attempt = 0; ; $attempt++) {
$retryAfter = 5;
$ch = curl_init(GIS_API_URL);
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" => $service, "url" => $url, "max_results" => $maxResults]),
CURLOPT_HEADERFUNCTION => function ($ch, $line) use (&$retryAfter) {
if (stripos($line, "Retry-After:") === 0) $retryAfter = (int) trim(substr($line, 12));
return strlen($line);
},
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
$data = json_decode((string) $body, true) ?: [];
if ($status === 200) return $data;
// 429 = rate or concurrency limit, 502/504 = platform hiccup; none of them is charged
if (in_array($status, [429, 502, 504], true) && $attempt < $retries) { sleep(max(1, $retryAfter)); continue; }
throw new RuntimeException(($data["code"] ?? "HTTP_$status") . ": " . ($data["message"] ?? "request failed"));
}
}
// Media URLs expire within minutes to hours, so save the file right away.
function gis_download(array $item, string $name, string $folder = "downloads"): string
{
if (!is_dir($folder)) mkdir($folder, 0755, true);
$tmp = "$folder/$name.part";
$fp = fopen($tmp, "wb");
$ch = curl_init($item["url"]);
curl_setopt_array($ch, [CURLOPT_FILE => $fp, CURLOPT_FOLLOWLOCATION => true, CURLOPT_TIMEOUT => 120, CURLOPT_FAILONERROR => true]);
$ok = curl_exec($ch);
$type = (string) strtok((string) curl_getinfo($ch, CURLINFO_CONTENT_TYPE), ";");
curl_close($ch);
fclose($fp);
if (!$ok) { unlink($tmp); throw new RuntimeException("download failed: " . $item["url"]); }
$ext = ["video/mp4" => ".mp4", "image/jpeg" => ".jpg", "image/png" => ".png", "image/webp" => ".webp", "audio/mpeg" => ".mp3"][$type] ?? ".bin";
rename($tmp, "$folder/$name$ext");
return "$folder/$name$ext";
}
$result = gis_resolve("instagram", "https://www.instagram.com/reel/SHORTCODE/");
echo "{$result['item_count']} items, {$result['credits_used']} credits\n";
foreach ($result["items"] as $i => $item) {
echo $item["type"], " ", gis_download($item, "{$result['request_id']}-$i"), "\n";
}
Using it in WordPress
- Define the key in
wp-config.php(define('GIS_KEY', 'gis_live_...');) and passGIS_KEYinstead ofgetenv("GIS_KEY"). - Call
gis_resolve()from server-side code only: an AJAX or REST route your form posts to. Never print the key into the page. - Return the
itemsto the visitor right away. Media URLs are short-lived, so do not cache them in the database.
Prefer not to build it? We set up a branded downloader site on this API from $149; see website setup.
What the API returns
{
"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
}
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
Does it work on shared hosting?
Yes, if PHP has the curl extension and outbound HTTPS is allowed. Allow up to 130 seconds for the request.
Is there a WordPress plugin?
Not from us. The two functions on this page are the integration; call them from your own AJAX or REST route. We also build complete sites through website setup.
Which PHP version is needed?
PHP 7.4 or newer for the example as written, with the curl extension.
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
- Video Downloader API for Your Own Website
- Python Instagram and TikTok 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.