# Instagram Public Media Downloader (`automation-lab/instagram-public-media-downloader`) Actor

Download authorized media from anonymous public Instagram posts and Reels into Apify storage with creator, format, byte size, and retrieval metadata.

- **URL**: https://apify.com/automation-lab/instagram-public-media-downloader.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Videos, Social media
- **Stats:** 2 total users, 1 monthly users, 95.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.11 / 1,000 item extracteds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Instagram Public Media Downloader

Download authorized images and videos from anonymous public Instagram post and Reel URLs into Apify storage.
This **Instagram media downloader** returns one typed dataset row per stored file, including the source post, creator, format, dimensions, byte size, storage key, and retrieval URL.

Use it for creator-owned backups, approved campaign archiving, media asset handoff, and repeatable public-content preservation.
No Instagram login, cookies, or account credentials are accepted.

### What does Instagram Public Media Downloader do?

The Actor opens each supplied public `/p/` or `/reel/` URL in a resource-efficient browser, reads Instagram's structured public page data, downloads each exposed media asset, and stores it in the run's default key-value store.

It supports:

- public image posts;
- public Reel videos;
- public carousel posts with multiple image or video children;
- batches of up to 10 supplied URLs;
- a maximum of 50 downloaded files per run;
- direct access or Apify datacenter proxy access;
- one metadata row for every successfully stored file.

It does not discover posts by username, hashtag, or keyword.
Supply the exact public URLs you are authorized to archive.

### Who is it for?

#### Creators and social teams

Back up your own published post and Reel assets into durable run storage before repurposing or cataloging them.

#### Agencies and campaign operators

Archive approved client deliverables with source URLs, creator identity, file format, dimensions, and retrieval timestamps.

#### Data engineers

Schedule URL batches, consume typed dataset rows, and copy stored files into a longer-lived object store or media pipeline.

#### Researchers and archivists

Preserve authorized anonymous public media together with provenance instead of keeping only temporary CDN links.

### Why use this Actor?

A copied Instagram CDN URL is temporary and difficult to audit later.
This Actor pairs every downloaded file with source and retrieval metadata.

Key differences from a metadata-only scraper:

- files are downloaded, not merely linked;
- carousel children become separate stored assets;
- each file has a byte count and MIME format;
- dataset rows link to both the Instagram source and Apify storage;
- failed URLs are not charged as media files;
- a partial batch fails visibly while preserving successful files.

### Getting started

1. Open the Actor input page.
2. Add one or more public Instagram post or Reel URLs.
3. Set `maxItems` to the maximum number of media files to store.
4. Keep Apify Proxy enabled for the normal cloud workflow.
5. Start the run.
6. Open **Downloaded media metadata** for dataset rows.
7. Open **Downloaded files** to retrieve images and MP4 files.

A Reel can produce one file.
A carousel can produce several files, subject to `maxItems`.

### Input parameters

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `startUrls` | array | required | One to ten public `instagram.com/p/...` or `instagram.com/reel/...` URLs. |
| `maxItems` | integer | `10` | Maximum stored assets and dataset rows, from 1 to 50. |
| `proxyConfiguration` | object | Apify Proxy enabled | Use the default datacenter proxy or explicitly disable proxy access. |

Duplicate URLs with the same shortcode are processed once.
Query parameters and tracking fragments are removed during normalization.
Profile pages, Stories, private posts, login-only pages, and non-Instagram domains fail validation or extraction.

### Example: download a public Instagram Reel

```json
{
  "startUrls": [
    { "url": "https://www.instagram.com/reel/Dbn-XJhk0_-/" }
  ],
  "maxItems": 1,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

This workflow stores the public Reel video as an MP4 and emits one metadata row.

### Example: archive a carousel post

```json
{
  "startUrls": [
    { "url": "https://www.instagram.com/p/DbtErSrlB2J/" }
  ],
  "maxItems": 2,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

Set `maxItems` high enough for the number of carousel children you need.
The Actor stops cleanly when the limit is reached.

### Example: recurring creator backup workflow

```json
{
  "startUrls": [
    { "url": "https://www.instagram.com/reel/Dbn-XJhk0_-/" },
    { "url": "https://www.instagram.com/p/DbtErSrlB2J/" }
  ],
  "maxItems": 3,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

Save a Task with this input, update its supplied URLs as the creator approves new assets, and schedule the Task.
Export dataset rows to your catalog and copy files to long-term storage if your retention requirements exceed normal Apify storage retention.

### Output fields

Each default-dataset row represents one successfully stored media file.

| Field | Meaning |
| --- | --- |
| `inputUrl` | Original URL supplied by the user. |
| `canonicalUrl` | Normalized Instagram post or Reel URL. |
| `shortcode` | Instagram public content shortcode. |
| `postId` | Instagram post identifier when exposed. |
| `contentType` | `post`, `reel`, or `carousel`. |
| `caption` | Public caption when exposed. |
| `publishedAt` | Public publication timestamp when exposed. |
| `creator` | Public creator ID, username, display name, and profile URL. |
| `assetIndex` | One-based position of this asset in the post. |
| `assetId` | Instagram asset identifier when exposed. |
| `format` | `image` or `video`. |
| `contentTypeHeader` | Stored MIME type such as `image/jpeg` or `video/mp4`. |
| `fileExtension` | Filename extension selected from the response type. |
| `byteSize` | Actual downloaded bytes. |
| `width`, `height` | Media dimensions when exposed. |
| `durationSeconds` | Video duration when exposed. |
| `storageKey` | Record key in the run key-value store. |
| `storageUrl` | API URL for the stored media record. |
| `sourceMediaUrl` | Temporary Instagram CDN URL used during retrieval. |
| `retrievedAt` | ISO 8601 download timestamp. |

### Example output

```json
{
  "inputUrl": "https://www.instagram.com/reel/Dbn-XJhk0_-/",
  "canonicalUrl": "https://www.instagram.com/reel/Dbn-XJhk0_-/",
  "shortcode": "Dbn-XJhk0_-",
  "postId": "3956405067326902270",
  "contentType": "reel",
  "caption": "Lunar landers, assemble.",
  "publishedAt": "2026-08-04T16:18:15.000Z",
  "creator": {
    "id": "528817151",
    "username": "nasa",
    "fullName": "NASA",
    "profileUrl": "https://www.instagram.com/nasa/"
  },
  "assetIndex": 1,
  "assetId": "3956405067326902270",
  "format": "video",
  "contentTypeHeader": "video/mp4",
  "fileExtension": "mp4",
  "byteSize": 5691930,
  "width": 1080,
  "height": 1920,
  "durationSeconds": null,
  "storageKey": "media-Dbn-XJhk0_--01.mp4",
  "storageUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/media-Dbn-XJhk0_--01.mp4",
  "sourceMediaUrl": "https://scontent.cdninstagram.com/temporary-video.mp4",
  "retrievedAt": "2026-08-22T20:15:00.000Z"
}
```

Instagram can omit optional metadata.
The stored file and its byte size are always present for emitted rows.

### How much does it cost to download Instagram media?

The Actor uses pay-per-event pricing:

- one `start` event per run;
- one `item` event for each successfully stored media file and matching dataset row.

The current contract charges **$0.005 per run start**.
At the BRONZE tier, each successfully stored media file costs **$0.00352**.
The per-file tiers decrease from FREE through DIAMOND, and the `item` event is emitted only after storage succeeds.

At the BRONZE tier:

| Stored files | Event price before platform plan effects |
| ---: | ---: |
| 1 | 0.00852 USD |
| 5 | 0.02260 USD |
| 10 | 0.04020 USD |
| 25 | 0.09300 USD |

Failed URLs and files that cannot be stored do not emit or charge an `item` event.
Compute, proxy, and storage usage may also be reflected according to your Apify plan.

### File storage and retention

Files are stored in the run's default key-value store under keys such as `media-<shortcode>-01.mp4`.
Dataset links point to the Apify API record URL.

Access to a private store follows your Apify authorization settings.
Use an API token when required.
For long-term archives, copy files into storage with a retention policy appropriate for your organization.

### Scheduling and integrations

Useful workflows include:

1. **Creator backup:** schedule an approved list of creator-owned URLs and copy new rows to cloud storage.
2. **Campaign handoff:** send stored media and provenance rows to an asset-management system.
3. **Spreadsheet catalog:** connect the dataset to Google Sheets and track shortcode, creator, format, size, and retrieval date.
4. **Webhook pipeline:** trigger a downstream process after the Actor run succeeds.
5. **Content repurposing:** pass stored MP4 or image URLs into authorized editing, OCR, or transcription workflows.

A URL list is intentional.
The Actor does not monitor a profile or discover newly published posts on its own.

### Run with the Apify API

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~instagram-public-media-downloader/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startUrls":[{"url":"https://www.instagram.com/reel/Dbn-XJhk0_-/"}],"maxItems":1}'
```

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/instagram-public-media-downloader').call({
  startUrls: [{ url: 'https://www.instagram.com/reel/Dbn-XJhk0_-/' }],
  maxItems: 1,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].storageUrl);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("automation-lab/instagram-public-media-downloader").call(run_input={
    "startUrls": [{"url": "https://www.instagram.com/reel/Dbn-XJhk0_-/"}],
    "maxItems": 1,
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items[0]["storageUrl"])
```

### Use with Apify MCP

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/instagram-public-media-downloader"
```

#### Claude Desktop, Cursor, and VS Code setup

Use this same HTTP configuration in Claude Desktop, Cursor, or VS Code:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/instagram-public-media-downloader"
    }
  }
}
```

Example prompts:

- "Download this authorized public Instagram Reel and return its stored MP4 URL and byte size."
- "Archive these approved public Instagram post URLs and group the resulting files by creator."
- "Run the Instagram media backup Task and summarize any URL that failed."

### Reliability and proxy behavior

Apify datacenter proxy is enabled by default because Instagram delivery can vary by environment.
The browser blocks image, media, and font rendering while it discovers structured media URLs, reducing transfer before the actual file download.

You can disable proxy access for environments where direct public access is reliable.
There is no automatic residential proxy fallback, so the Actor does not silently incur a higher unmeasured proxy cost.

Each URL receives one bounded fresh-page retry.
Stable private, deleted, age-restricted, or login-gated responses are reported as failures rather than empty success.

### Limits

- Maximum 10 input URLs per run.
- Maximum 50 stored files per run.
- Maximum 250 MB per individual media file.
- Public `/p/`, `/reel/`, `/reels/`, and `/tv/` URL forms only.
- No Stories, Highlights, profile discovery, private media, or authenticated content.
- Signed `sourceMediaUrl` values expire; use `storageUrl` for the downloaded copy.
- Instagram may change its public page data or challenge some network routes.
- Optional caption, ID, dimensions, or duration fields can be absent.

### Failure behavior

Malformed input fails before browsing.
A private or unavailable URL does not generate a charged media row.
If some URLs succeed and another fails, successful files and rows remain stored, but the run exits with a failure status so automation does not silently miss requested media.

This behavior makes retries explicit.
Remove or correct the failed URL before retrying the batch.

### Troubleshooting

#### The run says the URL is unsupported

Use a full `https://www.instagram.com/p/.../` or `https://www.instagram.com/reel/.../` URL.
Profile and Story URLs are outside this Actor's scope.

#### Instagram returned no downloadable public media

Open the URL in a logged-out browser.
Confirm it is public, still available, not age-restricted, and not a Story.
Keep the default proxy configuration enabled for cloud runs.

#### The stored file link asks for authorization

Private Apify key-value stores require an authorized API request.
Use your Apify token or fetch the record through the authenticated Apify client.

#### A carousel produced fewer files than expected

Increase `maxItems`.
The limit counts files across the entire run, not posts.

#### Can I use the temporary CDN URL later?

Do not rely on it.
Instagram signs CDN URLs and may expire them.
Use the file stored in the run key-value store.

### Responsible use and legality

Download only media you own or are authorized to archive.
Public accessibility does not transfer copyright or grant permission to reuse a creator's content.

Follow Instagram's terms, applicable copyright rules, privacy law, contractual restrictions, and your organization's retention policy.
Do not use this Actor to bypass access controls, retrieve private media, impersonate users, or redistribute content without permission.

The Actor accepts no Instagram credentials and supports anonymous public content only.
You are responsible for the purpose, frequency, retention, and downstream use of downloaded files.

### Related Automation Lab Actors

- [Instagram Post & Reel Details Scraper](https://apify.com/automation-lab/instagram-post-reel-details-scraper) — use when you need richer post metadata without storing media files.
- [Instagram Profile Posts Scraper](https://apify.com/automation-lab/instagram-profile-posts-scraper) — use when you need public profile post discovery rather than supplied-URL downloads.
- [Instagram Reel & Video Transcript Scraper](https://apify.com/automation-lab/instagram-reel-video-transcripts) — use for transcript output from public Reel and video URLs.

### FAQ

#### Does it require an Instagram login?

No.
It supports anonymously reachable public post and Reel URLs only.

#### Does it download every carousel child?

Yes, until `maxItems` is reached, provided Instagram exposes each asset publicly and each file is at most 250 MB.

#### Does one dataset row represent a post or a file?

A file.
A carousel can therefore produce multiple rows with the same shortcode and different `assetIndex` values.

#### Are failed downloads charged as items?

No.
The `item` event is emitted only after the file is stored successfully.

#### Can it discover posts from a creator handle?

No.
Use the related profile-posts Actor for discovery, then pass authorized post URLs into this downloader.

#### Can I download private posts or Stories?

No.
The Actor does not accept credentials and does not bypass login or privacy controls.

#### Where are files saved?

In the run's default Apify key-value store.
Each dataset row includes `storageKey` and `storageUrl`.

#### How should I preserve files long term?

Copy them from Apify storage into your approved object store or asset-management system and apply your own retention policy.

# Actor input Schema

## `startUrls` (type: `array`):

One to ten public instagram.com /p/ or /reel/ URLs. Duplicate shortcodes are processed once.

## `maxItems` (type: `integer`):

Stop after storing this many media assets. Carousel children count as separate files.

## `proxyConfiguration` (type: `object`):

Apify Proxy is enabled by default for reliable cloud access. Disable it only when direct Instagram access works from your environment.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.instagram.com/reel/Dbn-XJhk0_-/"
    }
  ],
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing one metadata row per stored media file.

## `files` (type: `string`):

Key-value store containing the downloaded images and videos.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.instagram.com/reel/Dbn-XJhk0_-/"
        }
    ],
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/instagram-public-media-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 = {
    "startUrls": [{ "url": "https://www.instagram.com/reel/Dbn-XJhk0_-/" }],
    "maxItems": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/instagram-public-media-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 '{
  "startUrls": [
    {
      "url": "https://www.instagram.com/reel/Dbn-XJhk0_-/"
    }
  ],
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call automation-lab/instagram-public-media-downloader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/instagram-public-media-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/qM1bbce3tFb6rFVsB/builds/2B6JsochLc5OcxzBB/openapi.json
