InstagramReelsAPI Tutorial

How to Scrape Instagram Reels Data with an API

Build a production workflow for collecting public Instagram Reels by username, including captions, media, audio, visible metrics, pagination, and metric snapshots.

SocQUpdated July 19, 20266 min read

Collecting one Instagram Reel manually is easy. Building a repeatable dataset across hundreds of public creators is harder: Reels can disappear, metrics change, media URLs expire, and the visible fields differ across posts.

This tutorial shows how to collect public Reels by username with the SocQ Instagram Reels API, poll the asynchronous task, store stable entity fields separately from metric snapshots, and prepare the data for monitoring or analysis.

Quick answer: Submit public usernames and a per-username results_limit to POST /v1/instagram/reels. Save the returned task_id, poll the task endpoint, and read normalized Reel records from data.results.items. The current endpoint accepts usernames, not individual Reel URLs.

Official Instagram API or a Public Reels API?

Meta's official Instagram APIs are the correct choice when a user authorizes a supported professional account and your application needs publishing, insights, comment management, or other permissioned operations.

They are not a general endpoint for collecting arbitrary public consumer profiles. Official access depends on account type, permissions, tokens, app review, and the selected Instagram product. Review the current Instagram Platform documentation before designing an authorized workflow.

Use SocQ for a supported public read workflow. Use Meta's official APIs for account actions and permissioned insights. A public-data API does not grant permission to ignore Instagram's terms, privacy rights, or intellectual-property rules.

Submit an Instagram Reels Task

The current endpoint accepts one or more public usernames:

curl -X POST "https://api.socq.ai/v1/instagram/reels" \
  -H "Authorization: Bearer $SOCQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "usernames": ["natgeo", "instagram"],
    "results_limit": 100
  }'

Normalize usernames before submission:

  • Remove a leading @.
  • Trim whitespace.
  • Convert profile URLs to usernames in your input layer.
  • Deduplicate case-insensitively.
  • Reject empty values.

results_limit limits requested results per username; it does not guarantee that every creator has that many available public Reels.

Poll the Asynchronous Task

Store the returned task_id and poll:

curl "https://api.socq.ai/v1/tasks/$TASK_ID?limit=100" \
  -H "Authorization: Bearer $SOCQ_API_KEY"

Treat queued and running as normal. Use exponential backoff rather than polling in a tight loop. When the task succeeds, read data.results.items. If has_more is true, request the next page with next_cursor.

A robust worker should persist:

  • Batch ID.
  • SocQ task ID.
  • Submitted usernames.
  • Submission and completion times.
  • Terminal status and error category.
  • Last processed result cursor.

That state lets the worker resume without resubmitting a completed collection.

Understand the Reel Response

A normalized Reel record resembles:

{
  "id": "3138424916027781494",
  "platform": "instagram",
  "resource": "reels",
  "type": "reel",
  "shortcode": "CtjoC2BNsB2",
  "url": "https://www.instagram.com/reel/CtjoC2BNsB2/",
  "caption": "A public Instagram Reel.",
  "author": {
    "id": "123",
    "username": "natgeo",
    "name": "National Geographic",
    "url": "https://www.instagram.com/natgeo"
  },
  "metrics": {
    "likes_count": 21904,
    "comments_count": 502,
    "views_count": 284110,
    "plays_count": 284110
  },
  "media": [],
  "duration_seconds": 42,
  "audio": {
    "title": "Original audio",
    "artist": "natgeo"
  },
  "hashtags": [],
  "mentions": [],
  "created_at": "2026-07-08T16:05:00",
  "collected_at": "2026-07-19T10:00:00",
  "extra": {}
}

Use id as the preferred entity key and shortcode as a fallback. Keep url for traceability. Metrics, media, audio, and some profile fields can be unavailable; model them as nullable rather than converting missing values to zero or empty strings.

Store Entities and Metric Snapshots Separately

Reel identity and Reel metrics change at different rates.

An entity table can store:

reel_id
shortcode
canonical_url
author_id
caption
created_at
duration_seconds
audio
first_seen_at
last_seen_at

A snapshot table can store:

reel_id
collected_at
likes_count
comments_count
views_count
plays_count

This prevents daily monitoring from creating duplicate Reel entities while preserving growth over time.

Do not calculate growth when either snapshot is missing the metric. A hidden count is not zero. Also avoid comparing views_count and plays_count as if every source defines them identically.

Build an Incremental Reels Monitor

The simplest reliable monitor:

Creator registry
      ↓
Daily or hourly collection schedule
      ↓
Async task polling
      ↓
Schema validation
      ↓
Upsert Reel entity by id
      ↓
Append metric snapshot
      ↓
Alerts and reports

For each creator:

  1. Collect a reasonable recent window.
  2. Sort records by created_at when available.
  3. Stop treating old repeated records as new discoveries.
  4. Upsert by Reel ID.
  5. Append a snapshot only when collection succeeded.
  6. Track the creator's last successful run separately from task submission.

Instagram feeds are ranked and source availability can change. The endpoint should not be treated as a guaranteed complete historical archive.

Python Example with Pagination

import time
import requests

BASE = "https://api.socq.ai/v1"
HEADERS = {
    "Authorization": f"Bearer {SOCQ_API_KEY}",
    "Content-Type": "application/json",
}

created = requests.post(
    f"{BASE}/instagram/reels",
    headers=HEADERS,
    json={"usernames": ["natgeo"], "results_limit": 200},
    timeout=30,
)
created.raise_for_status()
task_id = created.json()["data"]["task_id"]

delay = 2
while True:
    response = requests.get(
        f"{BASE}/tasks/{task_id}",
        headers=HEADERS,
        timeout=30,
    )
    response.raise_for_status()
    task = response.json()["data"]

    if task["status"] == "succeeded":
        break
    if task["status"] in {"failed", "cancelled"}:
        raise RuntimeError(task)

    time.sleep(delay)
    delay = min(delay * 1.5, 15)

items = task["results"]["items"]
cursor = task["results"].get("next_cursor")

while cursor:
    page = requests.get(
        f"{BASE}/tasks/{task_id}",
        headers=HEADERS,
        params={"limit": 100, "cursor": cursor},
        timeout=30,
    )
    page.raise_for_status()
    results = page.json()["data"]["results"]
    items.extend(results["items"])
    cursor = results.get("next_cursor")

In production, add bounded retries for timeouts, 429, and retriable 5xx responses. Do not automatically resubmit failed inputs without checking the error category.

Validate Reel Data Before Storage

Recommended checks:

  • platform must equal instagram.
  • resource must equal reels.
  • At least one of id, shortcode, or url must exist.
  • author.username should match the submitted creator when available.
  • Counts must be non-negative numbers or null.
  • created_at and collected_at must parse as timestamps.
  • Media entries must be treated as source references, not permanent assets.

Keep invalid records in a quarantine table with the raw task and validation error. Silent field coercion hides upstream changes.

Media URLs Are Not Permanent Storage

Reel video, image, cover, and avatar URLs may be signed, transformed, rate-limited, or changed. Do not assume a URL collected today will work forever.

If the product needs long-term media retention:

  1. Confirm that storing the asset is permitted.
  2. Download only the media needed for the stated purpose.
  3. Record the original URL and collection time.
  4. Apply retention and deletion controls.
  5. Serve stored media securely.

If analytics only needs captions and metrics, storing large media files may add cost and risk without adding value.

Measure Reel Performance Carefully

Useful derived metrics include:

engagement_per_play =
  (likes + comments) / plays

daily_play_growth =
  (current_plays - previous_plays) / elapsed_days

Only calculate a metric when its inputs are present. Compare creators using consistent windows and collection schedules. A Reel published two hours ago should not be ranked against one observed for two weeks without time normalization.

Public counts are visible snapshots, not audited analytics. For owned professional accounts, official Instagram Insights is the better source for permissioned performance data.

Handle Common Failure Cases

CaseRecommended handling
Invalid usernameReject before submission
Private accountMark unavailable; do not bypass
Renamed accountResolve manually or update registry
No public ReelsStore an empty successful observation
Task timeoutRetry polling before resubmitting
Missing metricsPreserve null
Duplicate ReelUpsert by ID or shortcode
Expired media URLRefresh only when the use case permits

An empty successful result and a failed task are different operational states.

Responsible Use

  • Collect only public data needed for a legitimate purpose.
  • Do not access private profiles or bypass controls.
  • Avoid sensitive individual profiling.
  • Respect deletion, privacy, and intellectual-property requests.
  • Secure API keys, exports, and media.
  • Review Instagram's terms and your provider agreement.
  • Use Meta's official authorization for account actions.

SocQ supplies a technical collection workflow, not additional rights to content.

Instagram Reels API FAQ

Can SocQ scrape one Reel URL directly?

The current Reels endpoint accepts public usernames, not individual Reel URLs. It returns available public Reels for those creators.

Does the endpoint return video files?

It returns normalized public media references when available. Treat URLs as temporary source references, not permanent downloads.

Are view and play counts always present?

No. Instagram may hide or omit metrics. Preserve missing values as null.

Can I collect private-account Reels?

No. A public-data workflow should not bypass private-account controls.

How do I avoid duplicate Reels?

Use the public Reel ID as the preferred key and shortcode as a fallback. Store metrics in a separate snapshot table.

Should I use Meta's official Instagram API instead?

Use the official API for authorized professional accounts, publishing, insights, and account actions. Use SocQ for its supported public read workflow.

INSTAGRAM API

Test the workflow with a public Instagram URL

Submit public inputs and receive normalized records with traceable source context.

Explore Instagram APIs