GetInSaver Developers
A desk with a laptop and a desktop monitor showing a website
Guide · PHP and WordPress

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.

PHP code that resolves an Instagram link with gis_resolve and saves each file, and the JSON response

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

  1. Create a free account and verify your email. You get 20 free credits, no card needed.
  2. Create an API key in Dashboard → API keys and store it as the environment variable GIS_KEY on your server.
  3. Save the script below as resolve.php and run GIS_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 pass GIS_KEY instead of getenv("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 items to 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

HTTPCodeWhat to do
402INSUFFICIENT_CREDITSTop up, or lower max_results: a request reserves max_results × credits per result first.
422UPSTREAM_REJECTEDThe post is private, deleted, expired or login-only. Show the message to your user; nothing was charged.
429RATE_LIMITED / CONCURRENCY_LIMITWait for Retry-After seconds and retry. 120 requests per minute per account; 2 at once on the trial, 8 after buying credits.
502 / 504UPSTREAM_*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.

Updated 2026-10-30. The code on this page is executed by our test suite against the API server before every release.

Make your first call in five minutes.

20 free credits when you verify your email. No card needed.

Create a free account