Call the endpoint
One POST with a public Reel URL, from any language. Typed SDKs for Python and Node if you want them, plain REST if you do not.
Read the API referenceEndpoint
POST /api/v2/transcripts/video
50 free credits · no card
Clean text with timestamped segments, for any public Reel, feed video or whole profile: over REST, an MCP server, or the Python and JavaScript SDKs.
No card required. Failed fetches are free.
Independently monitored
YouTube, TikTok, Instagram
Send a Reel or video URL. Most Instagram videos carry no caption track at all, so the usual answer is the transcribed one on the right. Same request, same fields, same parser either way. Only source tells them apart.
curl -X POST https://transcriptfetch.com/api/v2/transcripts/video \
-H "Authorization: Bearer $TRANSCRIPTFETCH_KEY" \
-d '{"video": "<any public reel or video url>"}'{
"ok": true,
"data": {
"kind": "transcript",
"platform": "instagram",
"channel": "@creator",
"duration": 41,
"language": "en",
"source": "captions",
"segments": [
{ "start": 0, "duration": 4.6,
"text": "People keep asking which camera I use" },
… 6 more
]
},
"usage": { "credits_spent": 1, "balance": 49 }
}200 · 1 credit
{
"ok": true,
"data": {
"kind": "transcript",
"platform": "instagram",
"channel": "@creator",
"duration": 38,
"language": "en",
"source": "audio",
"segments": [
{ "start": 0, "duration": 5.1,
"text": "People keep asking which camera I use" },
… 5 more
]
},
"usage": { "credits_spent": 1, "balance": 48 }
}200 · 1 credit · transcribed
Nothing in your code branches on which path ran, which matters more here than anywhere else: on Instagram the audio path is the normal one, not the exception. Transcription is billed by audio duration, which at Reel lengths is usually a single credit and shows up in usage rather than in the shape. Every field, with types
Paste any public Instagram link and run it against the live API. No account, no key, no card: you get the same JSON your code would.
Resolve a profile or a search into a list, then transcribe what you want. Every row's url is accepted by the transcript and batch endpoints as-is. Costs are stamped on each tile.
One Reel or video URL. Captions when they exist, AI Fallback Transcription when they do not.
1 credit
Up to 50 URLs per call, 500 on Mega and Scale. Per-item outcomes.
1 credit per delivered
Latest posts from a public profile, newest first, cursor-paged.
1 credit per page
Keyword search, results ready to transcribe.
1 credit per page
State of an AI Fallback Transcription started by a 202.
Free
Validate the key and read remaining credits.
Free
Public liveness probe for uptime monitoring.
Free
The same fetch, the same credit, whichever way you reach it. Write code, let an assistant call it, or run it from a workflow tool without writing any.
One POST with a public Reel URL, from any language. Typed SDKs for Python and Node if you want them, plain REST if you do not.
Read the API referenceEndpoint
POST /api/v2/transcripts/video
Add the MCP server once and Claude, ChatGPT or Cursor pulls a transcript mid-conversation. OAuth on first use, nothing to deploy, no key to paste.
Set up MCPServer URL
https://transcriptfetch.com/mcp
The official n8n node, or an authenticated HTTP step in Make and Zapier. Fetch on a schedule, on a webhook, or whenever a row lands in a sheet.
See the n8n nodeCommunity node
n8n-nodes-transcriptfetch
curl -X POST https://transcriptfetch.com/api/v2/transcripts/video \
-H "Authorization: Bearer $TRANSCRIPTFETCH_KEY" \
-H "Content-Type: application/json" \
-d '{"video": "https://www.instagram.com/reel/CxxxxxxxxxX/"}'import os, requests
r = requests.post(
"https://transcriptfetch.com/api/v2/transcripts/video",
headers={"Authorization": f"Bearer {os.environ['TRANSCRIPTFETCH_KEY']}"},
json={"video": "https://www.instagram.com/reel/CxxxxxxxxxX/"},
)
data = r.json()["data"]
for seg in data["segments"]:
print(seg["start"], seg["text"])Or pip install transcriptfetch-sdk for typed models and async.
const res = await fetch(
"https://transcriptfetch.com/api/v2/transcripts/video",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TRANSCRIPTFETCH_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
video: "https://www.instagram.com/reel/CxxxxxxxxxX/",
}),
},
);
const { data } = await res.json();
for (const seg of data.segments) {
console.log(seg.start, seg.text);
}Or npm i transcriptfetch for typed models and promises.
<?php
$ch = curl_init("https://transcriptfetch.com/api/v2/transcripts/video");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("TRANSCRIPTFETCH_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"video" => "https://www.instagram.com/reel/CxxxxxxxxxX/",
]),
]);
$data = json_decode(curl_exec($ch), true)["data"];
foreach ($data["segments"] as $seg) {
echo $seg["start"], " ", $seg["text"], PHP_EOL;
}{
"ok": true,
"request_id": "req_…",
"data": {
"kind": "transcript",
"video_id": "CxxxxxxxxxX",
"platform": "instagram",
"channel": "@creator",
"duration": 38,
"language": "en",
"source": "audio",
"segments": [
{ "start": 0, "duration": 5.1,
"text": "People keep asking which camera I use" },
{ "start": 5.1, "duration": 6.2,
"text": "It is genuinely the least important part" }
]
},
"usage": { "credits_spent": 1, "balance": 49 }
}What did they say actually moved retention?
get_transcript(video="…")
00:18Rewriting the first line of thirty old reels nearly doubled median watch time.
Ground an assistant in what was actually said to camera. Segments carry start times, so an answer can cite the second rather than paraphrase a Reel it never watched.
segments
chunked, cited, retrievable
Turn a profile's back catalogue into text your index can reach. Chunk on timestamps and every retrieved passage keeps a link back to the moment.
mentions · 12 weeks
Track a claim, a hook or a product mention across more Reels than anyone can sit through, then query the text instead of the grid.
One credit per delivered transcript, whether it came from captions or from the audio. Failed or empty results are free. Unused credits roll over up to twice your monthly allowance.
How much will my volume cost?
transcripts / month
| Plan | Price | Credits / month | Per 1,000 | |
|---|---|---|---|---|
| Free | $0/mo | 50 | Free | Get started |
| Basic | $5/mo | 1,000 | $5.00 | Start with Basic |
| ProPopular | $15/mo | 7,500 | $2.00 | Go Pro |
| Mega | $45/mo | 35,000 | $1.30 | Go Mega |
| Scale | $229/mo | 250,000 | $0.92 | Scale up |
Top-ups are billed at your plan's per-1,000 rate and never expire. AI Fallback Transcription is billed by audio duration rather than per transcript, which at Reel lengths usually lands at one credit a video. Full pricing
Compared by approach rather than by vendor, because the real choice is whether you want to own the infrastructure.
| Capability | TranscriptFetch | The Instagram Graph API | Your own scraper |
|---|---|---|---|
| Works on | Any public Reel or video URL | Only accounts you own or manage | Whatever survives the login wall |
| Setup | Get a key, make a request | App review, a business account, tokens that expire | Headless browser, proxies, an STT pipeline |
| Transcript text | Captions, or AI Fallback Transcription on the same call | No transcript field exists | Your own transcription step to build |
| Timestamps | Per-segment start and duration | Not available | Depends on your STT setup |
| Blocks and rotation | Handled for you | Not applicable | Your IP, blocked at scale |
| Profiles and search | Built in, paginated | Your own accounts only | More parsers |
| Batch | Up to 50 per call | Not available | Your queue |
| Cost of a failure | Nothing | Not applicable | You pay for the compute either way |
| When Instagram changes | We fix it | Tokens and review, again | You fix it, tonight |
The Graph API deserves the sentence people expect it to earn: even with app review passed and a business account connected, it returns no transcript text for any video, including your own. A public Reel URL is enough here, and captions.download has no Instagram equivalent to argue about.
The audio is transcribed automatically on the same call: no second endpoint and no change to your code. On Instagram this is the common path rather than the fallback, since most videos carry no caption track. Reels are short, so it almost always returns inline. Transcription is billed by audio duration, one credit per started 5 minutes, and only on delivery, so almost every Reel is one credit.
Whatever caption track the video carries, with the language stamped on the response. When none exists and the audio is transcribed, which is usually the case here, the language is detected automatically rather than assumed.
Per-plan request rates, returned on every response as standard rate-limit headers so a client can back off without guessing. Batch is the cheaper path for volume: one call carries up to 50 videos on the free tier, Basic and Pro, and up to 500 on Mega and Scale.
Yes. POST /transcripts/batch takes up to 50 URLs per call, 500 on Mega and Scale, and returns a per-item outcome rather than failing the whole request. You are charged one credit per successfully delivered transcript; failures cost nothing.
50 credits a month, no card. Every endpoint is included, not a reduced subset, so you can build the real integration before deciding to pay for it.
No. A credit is a delivered result. A transcript is one credit, a profile or search page is one credit, and polling a job, checking your balance and the health probe are free. Failed and empty results are never charged.
Python and JavaScript, both thin wrappers over the same REST endpoints with typed models. There is also an official n8n community node, and an MCP server if you would rather let an assistant make the call.
We fix it. Extraction runs through several methods behind one endpoint, so a change that breaks one path usually falls through to another before anyone notices, and the response shape your code parses does not move either way.
50 free credits a month. No card required. Failed fetches are never billed.