Pass a public reel URL and get the spoken words back as plain text, with the video's duration. Instagram publishes no caption track for reels, so this is the way to read a reel instead of watching it: for summaries, search indexes, retrieval pipelines and agents that need to know what a video says.
| parameter | type | description |
|---|---|---|
| url | string, required | A public Instagram post, reel or profile URL. Share links are resolved. |
| fresh | boolean | Skip the stored copy and read live, at the same price. |
| fields | string | Comma-separated field paths to keep. |
| format | json, text | text returns the plain transcript with no envelope. |
1 credit for the reel + 20 per started minute. Failed calls are never charged, and empty results are free up to 25 a day. Stored copies are stored once, served forever.
One object: the full transcript as a single string, the duration of the video in seconds, and where the text came from. The x-cache header says whether it was served from storage or produced on this call.
Instagram transcripts are plain text today: segments and language are null. Both keys stay in the response so the shape is stable if timings become available.
Transcripts are stored once and kept. The first call for a reel pays for the transcription; every later call for the same reel is served from storage in milliseconds at the same price.
curl "https://api.instadata.dev/v1/instagram/transcript?url=https%3A%2F%2Fwww.instagram.com%2Freel%2FC8xQvZ2sVAb%2F" \ -H "Authorization: Bearer ik_live_..."
{
"data": {
"text": "Start with cold butter. Cube it, then rub it into the flour until it looks like coarse sand. …",
"segments": null,
"language": null,
"duration_sec": 41,
"source": "upstream"
},
"request_id": "req_01J…"
} | field | type | note |
|---|---|---|
| text | string | The whole transcript as one plain string, whitespace collapsed. |
| duration_sec | number|null | Length of the video in seconds. Billing counts started minutes of this value. |
| segments | null | Always null on Instagram today: the upstream transcription carries no timings. |
| language | null | Always null on Instagram today: no language is detected. |
| source | string | "upstream" for a transcript produced by the transcription add-on. |
The reel costs 1 credit and each started minute of video costs 20, which is how the transcription is billed upstream. A 41-second reel is 21 credits; a 90-second one is 41. The minute count comes from the video's duration, not from how much speech it contains, so a music-only reel still costs one started minute and returns whatever the transcription heard.
A stored transcript costs the same as a fresh one; what you gain on the second call is speed.
Reel URLs (/reel/…) and the same reels as post URLs (/p/…) are accepted. Image posts and carousels without video return 422 before anything is transcribed, and so do videos longer than ten minutes. Private accounts and deleted posts return 404. None of these are charged.
Spoken words in a published reel do not change, so a transcript is stored permanently once made. fresh=true re-runs the transcription at the same price, which is rarely useful.
1 credit for the reel plus 20 credits per started minute of video. A reel under a minute is 21 credits, about $0.10 on the monthly plan. Calls that fail (private, deleted, no video, over ten minutes) cost nothing.
Not on Instagram. The transcription returns plain text, so segments is null and text carries everything. The key stays in the response so your code does not have to special-case it.
Not today. The language field is null on Instagram transcripts. The text itself is in whatever language is spoken.
It still costs one started minute, because billing follows the video's duration, and the text will be whatever the transcription heard, which may be a word or two of noise. Check the caption or the view count first if you are unsure a reel has speech.
No. The endpoint reads public content only, without a session. Private accounts and deleted posts return 404 and cost nothing.
No, it is faster. Transcripts are stored once made, so a repeat call returns from storage in milliseconds at the same price.
Add format=text and the response is the plain transcript with no JSON envelope. Add fields=text to keep the envelope but drop the rest.