Instagram Channel Reels API
Latest Reels from a public Instagram profile — pass userId to skip resolve; ceil(n×0.3) credits; nextCursor + hasMore.
Send a profile URL/@handle or a numeric userId and get that account's recent Reels (videos only) plus a top-level user{} profile block (id, username, displayName, url, verified, followers, avatar, isPrivate) so you do not need a second channel-details call. Prefer userId when you already have it (from basic-profile or profile-search) — it skips handle→ID resolve (the old sequential path alone could cost ~80s; url/@handle now uses the same raced resolver as profile-search). instagram.com/handle/ and instagram.com/@handle/ both parse. Each Reel includes videoUrl, thumbnailUrl, caption (not a duplicated description), likes, comments, duration (decoded from the CDN efg blob when the mapper had none), publish date, coauthors[], and split CDN expiry — videoUrlExpiresAt (~1.5d, the tight window) and thumbnailUrlExpiresAt (~4d), never collapsed to one min. reels[].author is the clip owner — the clips tab includes collabs; coauthors[] names the partners, so a reel authored by a collaborator still shows the queried channel there. Read data.user for the requested account — user.id / userId / displayName are lifted from matching reel authors when handle→ID resolve missed (extended path), never from a collab first row. Envelope: requested + totalReturned, and two clocks — fetchedAt is when the data came from Instagram, servedAt is when we handed it over; on a stale last-good page (stale + cached) the gap is the data's age, fetchedAt is never restamped to the request time. Billing is ceil(n × 0.3) credits on the returned reel count (17 → 6, 5 → 2), including a labelled last-good page after a live miss. Metrics when Instagram exposes them: engagement.views + viewsSource; likes:null never ships next to likeAndViewCountsDisabled:false (an unread count makes the flag null — unknown, not a claim). Cursor pagination via nextCursor; hasMore is true until the end of the list, and null on a degraded page (unknown — never a false end). Several fetch paths run in parallel until the 100s wall; the first with reels wins. A 6h last-good page is served stale when live paths miss. A miss with no snapshot is 502 UPSTREAM_UNAVAILABLE at 0 credits. A deleted / renamed / banned account is a non-retryable 404 PROFILE_NOT_FOUND decided at resolve time — never a retryable 502 that sends pollers into all-day loops on a dead handle. Pass cache=true for the 24h shared cache (0 credits on hit).
Request
- Base URL: https://api.captapi.com
- URL: https://api.captapi.com/v1/instagram/channel-reels
- Auth: one of:
- HTTP bearer
- API key in header X-API-Key
Query parameters
Instagram profile URL, @handle, or username. Omit when userId is set. The URL platform must match this endpoint's platform.
Instagram numeric user ID (e.g. 173560420). Skips handle→ID resolve (legacy sequential WPI alone could cost ~80s). Prefer when you already have the ID from basic-profile or profile-search.
Max items to return (default 20, max 200). Billed per result.
Pagination cursor. Leave empty for the first page; then pass nextCursor from the previous response (clips:{userId}:{opaque} on the native Reels path, or legacy {mediaId}_{userId}). Stop when hasMore is false.
Set true to serve from the 24h response cache (0 credits on hit). Default false — always fetch fresh.
Response
Success. The data object for this endpoint.
Changes
No recorded changes to this operation across all 3 revisions of this API.