# Instagram Video Downloader (`lance_api/instagram-video-downloader`) Actor

Download public Instagram video, audio, images, carousel media, and post metadata.

- **URL**: https://apify.com/lance_api/instagram-video-downloader.md
- **Developed by:** [LanceAPI](https://apify.com/lance_api) (community)
- **Categories:** Social media, AI, Videos
- **Stats:** 12 total users, 5 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.50 / 1,000 media results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

**Paste an Instagram link. Get the media URL and post data your app can use.**

Instagram Video Downloader API turns public Reels and posts into download-ready **video, audio, image, cover, and carousel URLs**—plus the caption, creator, duration, publish date, and available engagement numbers. No browser automation to build. No page HTML to maintain. Just send URLs and get structured JSON back.

This is an **unofficial Actor** and is not affiliated with, endorsed by, or sponsored by Instagram or Meta.

#### The quick version

- **You send:** public Instagram Reel or post URLs.
- **You get:** direct media links and clean post metadata in JSON.
- **You pay for:** successful unique results only—never failed URLs or duplicates.
- **Price per 1,000 results:** **Free $2.50 · Starter $2.00 · Scale $1.80 · Business $1.50**.
- **Resolution coverage:** Free and paid runs use the same compatibility processing for eligible public URLs, including additional handling when Instagram places a public URL behind extra access checks.
- **Batch size:** up to 200 unique URLs per run on every plan.
- **Optional enhanced mode:** if regular resolution fails, one additional recovery method can be tried. Regular mode handles most eligible URLs; a successful enhanced recovery costs an extra **$0.005 per result**, while an unsuccessful attempt is not charged.
- **One thing to know:** Instagram CDN links expire, so download or copy the files soon after the run.

### What you get

- **The best available media link** for video, audio, image, cover, or carousel content.
- **The post context your workflow needs:** caption, creator, publish time, duration, and available engagement metrics.
- **Cleaner batch jobs:** tracking parameters are removed, duplicate posts run once, and one bad URL does not stop the rest.
- **Predictable JSON:** consistent result objects and fixed engagement keys make integrations easier to maintain.
- **Easy automation:** call it from the Apify Console, REST API, JavaScript, Python, schedules, webhooks, or an AI agent.

The Actor returns URLs, not hosted copies of the files. If you need permanent storage, download the media into your own bucket or asset library right after the run.

### Try it in under a minute

1. Click **Try for free** or **Start**.
2. Paste one or more public Instagram Reel or post URLs.
3. Click **Start**.
4. Open **Dataset** and use the link in `media.videoUrl`, `media.audioUrl`, `media.imageUrl`, or `media.items`.

Most public posts need nothing else. If Instagram puts a public post behind a login check, you can optionally provide your own session ID for that run.

Example input:

```json
{
  "urls": [
    "https://www.instagram.com/p/DbbQB9tCgeO/"
  ]
}
```

The example is ready to run as-is. Swap in your own public post whenever you are ready.

### Input reference

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `urls` | array of strings | Required | Public Instagram URLs using `/reel/`, `/reels/`, or `/p/`. Provide at least one URL. The Input Schema accepts up to 200 entries. |
| `enhancedMode` | boolean | `false` | Optional. Tries an additional recovery method only after regular resolution fails. A successful enhanced recovery adds $0.005; failed enhanced attempts are not charged. |
| `sessionid` | string | None | Optional sensitive session value used only for the current run when Instagram places otherwise public content behind a login check. It does not grant access to private content. |

#### Supported URLs

The Actor accepts:

- `https://www.instagram.com/reel/SHORTCODE/`
- `https://www.instagram.com/USERNAME/reel/SHORTCODE/`
- `https://www.instagram.com/reels/SHORTCODE/`
- `https://www.instagram.com/p/SHORTCODE/`
- The same URLs with tracking query parameters such as `?utm_source=...`

Supported hosts are `instagram.com`, `www.instagram.com`, and `m.instagram.com`. A `/p/` post may contain a video, image, or carousel. Username-prefixed Reel links are normalized to the same canonical Reel URL.

The Actor does not accept profile pages, usernames, Stories, Explore pages, login pages, shortened share redirects, or private posts. Open a share redirect in your browser first and provide the final canonical post or Reel URL.

#### Batch limits and duplicate handling

- Every plan accepts up to 200 unique URLs per run.
- Blank entries are ignored and surrounding whitespace is removed.
- Exact duplicates are removed.
- URLs that differ only by `/reel/` versus `/reels/`, host spelling, or tracking parameters are normalized and processed once.
- Each unique input normally creates one Dataset item, including item-level errors.
- Items are processed concurrently, so Dataset order is not guaranteed. Match results using `inputUrl` rather than array position.
- Exceeding the applicable batch limit stops the run before item processing with `BATCH_LIMIT_EXCEEDED`.

The program also recognizes the legacy keys `videoUrls`, `bulkUrls`, and `videoUrl` for existing integrations. New integrations should use `urls` because it is the documented Input Schema field.

### Output reference

A successful Dataset item contains the original URL, canonical URL, content details, media links, author information, engagement metrics, and a null `error`.

```json
{
  "success": true,
  "status": "success",
  "inputUrl": "https://www.instagram.com/p/DbbQB9tCgeO/",
  "normalizedUrl": "https://www.instagram.com/p/DbbQB9tCgeO/",
  "content": {
    "id": "1234567890123456789_123456789",
    "pk": "1234567890123456789",
    "shortcode": "DbbQB9tCgeO",
    "type": "video",
    "caption": "Example Instagram caption",
    "publishedAt": "2026-01-15T10:30:00.000Z",
    "durationSeconds": 18.4
  },
  "media": {
    "videoUrl": "https://example-cdn.invalid/video.mp4",
    "smallVideoUrl": "https://example-cdn.invalid/video-small.mp4",
    "audioUrl": "https://example-cdn.invalid/audio.mp4",
    "thumbnailUrl": "https://example-cdn.invalid/thumbnail.jpg",
    "mediaUrlsTemporary": true
  },
  "author": {
    "id": "123456789",
    "username": "example_creator",
    "displayName": "Example Creator",
    "avatarUrl": "https://example-cdn.invalid/avatar.jpg",
    "verified": false
  },
  "engagement": {
    "viewCount": 1200,
    "playCount": 1320,
    "likeCount": 85,
    "commentCount": 7,
    "shareCount": null
  },
  "platformData": {
    "instagram": {
      "productType": "clips",
      "mediaType": 2
    }
  },
  "error": null
}
```

The example uses placeholder CDN URLs to show the response structure. Real runs return the available URLs supplied for the requested Instagram post.

#### Top-level fields

| Field | Meaning |
| --- | --- |
| `success` | `true` when usable media was resolved; otherwise `false`. |
| `status` | Stable result category such as `success`, `invalid_url`, `login_required`, `private_content`, `media_not_found`, or `error`. |
| `inputUrl` | The URL supplied by the user. |
| `normalizedUrl` | Canonical Instagram URL without tracking parameters, when normalization succeeds. |
| `content` | Post identity, type, caption, publication time, and duration when available. |
| `media` | Resolved media and thumbnail URLs. |
| `author` | Available creator identity and profile metadata. |
| `engagement` | Stable engagement counters. |
| `platformData` | Small Instagram-specific classification values when available. |
| `error` | `null` on success; otherwise a safe error object. |

#### Content fields

| Field | Meaning |
| --- | --- |
| `id` | Instagram media identifier when supplied. |
| `pk` | Instagram media primary key when supplied. |
| `shortcode` | Shortcode used in the canonical post URL. |
| `type` | Normalized media type: `video`, `image`, or `carousel`. |
| `caption` | Post caption or description when available. |
| `publishedAt` | Publication time as an ISO 8601 timestamp when available. |
| `durationSeconds` | Video duration in seconds, rounded to at most two decimal places. |

#### Media fields

| Field | Meaning |
| --- | --- |
| `videoUrl` | Preferred downloadable video URL. |
| `smallVideoUrl` | A smaller video alternative when a genuinely different variant is available. |
| `audioUrl` | Separate audio-track URL when available. |
| `thumbnailUrl` | Cover or preview image URL. |
| `imageUrl` | Downloadable image URL for an image item. |
| `videoVariants` | Additional video variants when the source exposes distinct alternatives. |
| `items` | Normalized child media for a carousel. Each item may contain its own type and media URLs. |
| `mediaUrlsTemporary` | Always `true`; download URLs are temporary and can expire. |

Optional fields are emitted only when the source provides a real value. Empty `videoVariants` or `items` arrays are not added merely as placeholders.

#### Engagement fields

The `engagement` object always contains the following five keys:

| Field | Meaning |
| --- | --- |
| `viewCount` | Independent view count supplied by Instagram, or `null`. |
| `playCount` | Independent play count supplied by Instagram, or `null`. |
| `likeCount` | Like count, or `null`. |
| `commentCount` | Comment count, or `null`. |
| `shareCount` | Share count, or `null`. There is no separate switch or charge for this field. |

Unavailable engagement values are returned as `null`, not copied from another metric, estimated, or replaced with zero. `viewCount` and `playCount` may be equal, different, or independently unavailable because they represent separate source fields.

### Carousel and image posts

For a carousel, `content.type` is `carousel` and the downloadable child media is returned in `media.items`. Each child is normalized independently and can be a video or image.

For a single image post, `content.type` is `image` and the preferred file is normally available in `media.imageUrl`. Because Instagram can expose different combinations of media fields, integrations should check the relevant URL fields instead of assuming every result contains `media.videoUrl`.

### Download the returned media

The Dataset stores URLs, not the media bytes. To save a returned file, read the appropriate URL from the result and download it promptly. For example:

```bash
curl -L 'RETURNED_MEDIA_URL' -o instagram-media.mp4
```

Use the correct file extension for the returned media type. Do not treat a CDN URL as a permanent identifier or publish it as a long-lived link.

### Status and error handling

| Status | Meaning |
| --- | --- |
| `success` | At least one usable media URL was resolved. |
| `invalid_url` | The input is malformed or is not a supported Instagram post/Reel URL. |
| `login_required` | Instagram placed the requested public page behind a login check. |
| `private_content` | The content is private or otherwise inaccessible. |
| `media_not_found` | No usable video, audio, or image source was found. |
| `error` | Another item-level or temporary error occurred. Inspect `error.code` and `error.retryable`. |

Failed result example:

```json
{
  "success": false,
  "status": "media_not_found",
  "inputUrl": "https://www.instagram.com/reel/EXAMPLE/",
  "normalizedUrl": "https://www.instagram.com/reel/EXAMPLE/",
  "content": {},
  "media": {},
  "author": {},
  "engagement": {
    "viewCount": null,
    "playCount": null,
    "likeCount": null,
    "commentCount": null,
    "shareCount": null
  },
  "platformData": {
    "instagram": {}
  },
  "error": {
    "code": "MEDIA_NOT_FOUND",
    "message": "Media was not found.",
    "retryable": false
  }
}
```

If `error.retryable` is `true`, retry the URL later. A valid public post can be temporarily unavailable because of rate limits, login gating, regional or age restrictions, CDN changes, or changes to the page response.

Item-level failures do not stop other URLs in the batch. Top-level input errors such as empty input or an exceeded batch limit stop the run before Dataset processing.

### Run with JavaScript

Install the Apify API client:

```bash
npm install apify-client
```

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const input = {
  urls: ['https://www.instagram.com/p/DbbQB9tCgeO/'],
};

const run = await client
  .actor('lance_api/instagram-video-downloader-api')
  .call(input);

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Run with Python

Install the Apify API client:

```bash
pip install apify-client
```

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])

run_input = {
    'urls': ['https://www.instagram.com/p/DbbQB9tCgeO/'],
}

run = client.actor('lance_api/instagram-video-downloader-api').call(
    run_input=run_input
)
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Run with cURL

The synchronous endpoint starts the Actor, waits for completion, and returns Dataset items:

```bash
curl -X POST \
  'https://api.apify.com/v2/acts/lance_api~instagram-video-downloader-api/run-sync-get-dataset-items' \
  -H 'Authorization: Bearer APIFY_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "urls": ["https://www.instagram.com/p/DbbQB9tCgeO/"]
  }'
```

For long or large batches, use the asynchronous Run Actor endpoint and retrieve the Dataset after the run finishes. Keep API tokens out of source control, screenshots, prompts, and logs.

### Use with AI agents through MCP

After publication, MCP-compatible AI clients can discover and run this Actor through the hosted Apify MCP server.

1. Connect the client to `https://mcp.apify.com` using Streamable HTTP.
2. Authenticate with Apify using your client's supported OAuth or API-token method.
3. Ask the agent to find and run `lance_api/instagram-video-downloader-api`.
4. Provide individual public Instagram post or Reel URLs and ask the agent to retrieve the Dataset output.

Common MCP tools are `search-actors`, `fetch-actor-details`, and `call-actor`. Running an Actor and reading its storage requires authentication.

Example agent request:

> Run lance_api/instagram-video-downloader-api for this public Instagram Reel and return the downloadable video URL, caption, author, duration, and engagement metadata.

### Pricing

Pay only for successful, unique results. Your price automatically drops with your Apify plan:

| Apify plan | Price per 1,000 successful results | Price per result |
| --- | ---: | ---: |
| Free | **$2.50** | $0.0025 |
| Starter | **$2.00** | $0.0020 |
| Scale | **$1.80** | $0.0018 |
| Business | **$1.50** | $0.0015 |

One result can include a video, a separate audio track, a cover image, or multiple carousel items. You still pay for **one result**, not for every file inside it.

Failed URLs, unsupported URLs, and duplicates removed before processing do **not** trigger a `media-result` charge. Apify may separately show its standard Actor-start event in the run pricing.

Enhanced mode is optional and off by default. If enabled, it runs only after regular resolution fails and adds **$0.005 for each result it successfully recovers**. An enhanced result also receives the normal successful-result charge. If enhanced recovery fails, neither `media-result` nor `enhanced-result` is charged.

#### Resolution reliability

Free and paid runs use the same compatibility processing for eligible public URLs. When Instagram places an otherwise public URL behind additional access checks, the Actor can apply additional processing to improve resolution coverage. This does not bypass private-content controls and cannot recover invalid, private, or confirmed removed content.

Every plan accepts up to 200 unique URLs per run. Plan differences apply to per-result pricing, not batch capacity.

### Use cases

- Pull Reels into an editing, clipping, or repurposing workflow
- Save approved social assets to your own media library
- Feed videos and captions into AI analysis or moderation pipelines
- Collect post metadata for creator, campaign, or content research
- Grab covers, audio tracks, and carousel assets without manual downloading
- Power no-code automations, internal tools, and AI agents with clean Instagram data

### Limits and practical notes

- Public Instagram posts and Reels only; profile and profile-post collection are not included.
- Private posts, removed posts, Stories, login pages, and unsupported redirect/share URLs cannot be downloaded.
- An optional session ID may help with a login check on public content but must not be used to bypass access controls or retrieve private content.
- Metadata is best effort. Instagram may omit captions, counters, author fields, audio tracks, or alternative media variants.
- Download URLs are temporary and may stop working after the run.
- Instagram can rate-limit requests, change page data, or temporarily withhold media URLs.
- Dataset item order is not guaranteed for batches.
- No permanent file hosting, profile scraping, comment-list scraping, or historical engagement tracking is included.

### Responsible use

Use this Actor only for content you are legally permitted to access, download, and process. Respect privacy, copyright, contractual restrictions, Instagram's terms, and applicable laws. Do not use session credentials to access private content, bypass access controls, or process another person's account without authorization.

Never publish, log, email, or include an Instagram session ID or Apify API token in a support request. Rotate any credential immediately if it is exposed.

### Related Actor

Need searchable speech instead of only media links? Use **Instagram Video AI Transcript Scraper API** to generate plain text, timestamped segments, SRT, WebVTT, and optional translations from individual public Instagram videos:

`lance_api/instagram-video-ai-transcript-scraper-api`

### FAQ

#### Does this Actor save files to Apify storage?

No. It returns temporary downloadable URLs in the Dataset. Your application must download and store the files if permanent retention is required.

#### Why did a valid-looking URL fail?

The post may be private, removed, image-only with unavailable image data, region- or age-restricted, temporarily rate-limited, or placed behind a login check. Confirm that the final canonical URL opens publicly in a logged-out browser and retry later when `error.retryable` is `true`.

#### Why is the caption or another metadata field missing?

Instagram may not expose every field in every response. Optional `content`, `media`, and `author` fields are omitted when unavailable rather than populated with invented values.

#### Why are `viewCount` and `playCount` equal?

They are independent source values and are never copied from one another. Instagram can report the same number for both, different numbers, or omit either value.

#### Is `shareCount` charged separately?

No. It is returned whenever available and otherwise set to `null`. There is no share-count option or separate fee.

#### Are duplicate URLs returned or charged twice?

No. Canonical duplicates are processed once. Tracking parameters, equivalent Reel path variants, and supported host variants do not create additional results or charges.

#### Why are `videoVariants` or carousel `items` missing?

Those fields appear only when Instagram exposes genuine alternatives. Empty arrays are not returned as processing diagnostics.

#### Can I download every file from a carousel?

When carousel children are available, they are returned in `media.items`. Check each child object's `type`, `videoUrl`, and `imageUrl` fields.

#### Does the Actor scrape profiles, feeds, Stories, or comments?

No. It accepts individual public post and Reel URLs. It returns an available comment count, but it does not download comment bodies or expand profile feeds.

#### How should I handle temporary download URLs?

Download the files immediately after the run and store them in storage you control. Do not rely on Instagram CDN URLs remaining valid.

### Support

For help, open an issue on the Actor page or email lanceapi2026@hotmail.com.

Include the Actor run ID, the input URL with unnecessary query parameters removed, the expected behavior, the actual `status` and `error.code`, and a short reproducible description. Never send Apify tokens, Instagram session IDs, passwords, cookies, or other credentials.

# Actor input Schema

## `urls` (type: `array`):

Public Instagram post or Reel URLs. Every plan accepts up to 200 unique URLs per run.

## `enhancedMode` (type: `boolean`):

If regular resolution fails, try an additional low-frequency recovery method. The extra $0.005 charge applies only when enhanced mode successfully returns a result; unsuccessful attempts are not charged.

## `sessionid` (type: `string`):

Used only for this run and never stored in results or logs.

## Actor input object example

```json
{
  "urls": [
    "https://www.instagram.com/p/DcmFt2WPGxp/"
  ],
  "enhancedMode": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://www.instagram.com/p/DcmFt2WPGxp/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lance_api/instagram-video-downloader").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": ["https://www.instagram.com/p/DcmFt2WPGxp/"] }

# Run the Actor and wait for it to finish
run = client.actor("lance_api/instagram-video-downloader").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "https://www.instagram.com/p/DcmFt2WPGxp/"
  ]
}' |
apify call lance_api/instagram-video-downloader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lance_api/instagram-video-downloader"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/2a2e4NKzPbJYXhjCz/builds/fmz0MmKNhW8POfAbL/openapi.json
