GitHubLog in
Guides

AI Fallback Transcription

When a video has no caption track, AI Fallback Transcription transcribes the audio. It is on by default and billed by length on delivery; choose captions only to never pay for audio, or audio only to skip captions. Long-running work returns a job you can poll or receive by callback.

On by default. Every transcript request runs in "mode": "auto" unless you send another mode: captions first, and when a video has none, AI Fallback Transcription transcribes the audio. It costs 1 credit per started 5 minutes of audio, minimum 1 credit, charged only when the transcript is delivered. Send "mode": "captions" to never pay for audio.

Choose a transcription mode

The mode field on POST /api/v2/transcripts/video decides where the text may come from, and so what a request can cost:

ModeWhat it doesWhat it costs
"auto" (the default)Read captions first. If none are available, use AI Fallback Transcription; long-running work may return a job.1 credit from captions; 1 credit per started 5 minutes of audio, minimum 1, when AI Fallback Transcription runs
"captions"Read an existing caption track only. Return 422 when there is none; never return a job.1 credit; never charged for audio
"audio"Skip the caption lookup and always use AI Fallback Transcription; long-running work may return a job.1 credit per started 5 minutes of audio, minimum 1
HTTP
POST /api/v2/transcripts/video

{ "video": "https://www.tiktok.com/@user/video/7137723462233555205", "mode": "audio" }

ai_fallback: true remains accepted as a legacy alias for "mode": "audio"; omitted or false maps to "mode": "auto". Send mode or ai_fallback, not both. A request containing both fields returns 400 invalid_request.

Where mode applies. /transcripts/video takes all three modes. /transcripts/batch takes "auto" (its default too) and "captions", and monitors that deliver transcripts work like "auto". /channel, /playlist and /search reject mode and ai_fallback.

How the response is chosen

The v2 API tells you where the words came from in data.source:

OutcomeResponse and billing
Captions are available200 with data.source: "captions"; 1 credit.
AI Fallback Transcription finishes during the inline wait200 with data.source: "audio"; its charge appears in usage.credits_spent.
AI Fallback Transcription is still running202 with status: "processing", job_id, and poll_url; nothing is charged yet.
The request cannot be servedA standard error envelope; free.

For standard direct API requests, TranscriptFetch waits up to about 45 seconds when the media duration is known to be 20 minutes or less. When duration is unknown, TikTok and Instagram are also held inline. If the work does not finish during that window, or the media is known to be longer, the job continues and the API returns 202.

RapidAPI requests can be held for up to about 90 seconds and for known media up to one hour because each poll also counts against the caller's RapidAPI quota.

mode: "captions" never starts AI Fallback Transcription. If no caption track exists, it returns a synchronous 422 and costs 0 credits.

The 202 job envelope

AI Fallback Transcription uses the same v2 job envelope whether "auto" fell back to it or "mode": "audio" asked for it:

JSON
{
  "ok": true,
  "request_id": "req_8f2c1a90b3d44e01",
  "status": "processing",
  "job_id": "asr_m3k1x9qz4vb2p7",
  "poll_url": "/api/v2/transcripts/jobs/asr_m3k1x9qz4vb2p7",
  "data": {
    "kind": "transcript_job",
    "video_id": "https://www.tiktok.com/@user/video/7137723462233555205",
    "platform": "tiktok"
  }
}

The poll_url is a relative API path. Branch on status; the initial response uses HTTP 202, while later polls use HTTP 200 for processing, completed, and failed jobs.

Polling the job

GET the poll_url until status is no longer processing:

HTTP
GET /api/v2/transcripts/jobs/asr_m3k1x9qz4vb2p7
JSON
{ "ok": true, "request_id": "req_…", "status": "processing", "job_id": "asr_m3k1x9qz4vb2p7", "data": null }

When the job completes, the poll returns the transcript and the actual delivery charge under usage:

JSON
{
  "ok": true,
  "request_id": "req_…",
  "status": "completed",
  "job_id": "asr_m3k1x9qz4vb2p7",
  "data": {
    "kind": "transcript",
    "video_id": "7137723462233555205",
    "url": "https://www.tiktok.com/@user/video/7137723462233555205",
    "platform": "tiktok",
    "title": "How I make my espresso",
    "channel": "@user",
    "duration": 58,
    "language": "en",
    "thumbnail_url": "https://p16-sign.tiktokcdn.com/…",
    "source": "audio",
    "text": "So the first thing people get wrong is the grind…",
    "segments": [
      { "start": 0.0, "duration": 4.1, "text": "So the first thing people get wrong is the grind" }
    ]
  },
  "usage": { "credits_spent": 1, "balance": 96, "bytes": 4812031 }
}

A completed job includes both text and segments. A failed job returns ok: false, status: "failed", and the standard v2 error object. It still uses HTTP 200 because the job resource was found; an unknown job, or one owned by another account, returns 404.

Worth knowing:

  • Jobs are scoped to your account, not to the key that created them; any of your keys can poll a job, and someone else's job id returns 404.
  • Job-status polling is free. It uses a separate account allowance and does not consume your extraction request allowance or credits.
  • Concurrent requests collapse. Two requests for the same video while a job is live join the same job rather than starting a second one.
  • Re-requesting a finished video is free. A video that already went through AI Fallback Transcription is served from cache, with a guard against charging twice.
  • Delivery can fail on credits. If your balance runs out between enqueue and completion, the job fails with insufficient_credits. The result stays cached; top up and request the same media again to claim it.
  • RapidAPI callers: every poll is a metered gateway call against your plan, so prefer callback_url below. (The API also holds the connection longer for RapidAPI requests, about 90 seconds, precisely to spare you the poll.)

Webhooks instead of polling

Pass callback_url with the original transcript request to receive the finished result by POST. It must be a public HTTPS URL on the standard port.

JSON
{
  "video": "https://www.tiktok.com/@user/video/7137723462233555205",
  "callback_url": "https://example.com/webhooks/transcriptfetch"
}

A successful delivery has this shape:

JSON
{
  "ok": true,
  "status": "completed",
  "job_id": "asr_m3k1x9qz4vb2p7",
  "data": {
    "kind": "transcript",
    "video_id": "7137723462233555205",
    "url": "https://www.tiktok.com/@user/video/7137723462233555205",
    "platform": "tiktok",
    "title": "How I make my espresso",
    "channel": "@user",
    "duration": 58,
    "language": "en",
    "thumbnail_url": "https://p16-sign.tiktokcdn.com/…",
    "source": "audio",
    "text": "So the first thing people get wrong is the grind…",
    "segments": [ { "start": 0.0, "duration": 4.1, "text": "…" } ]
  }
}

A failed delivery has the same outer fields, with ok: false and an error containing code and message.

  • The webhook body does not include usage or request_id; poll the job when you need those fields.
  • Delivery is attempted up to three times. The job remains pollable even if every callback attempt fails.

What AI Fallback Transcription costs

AI Fallback Transcription is billed by delivered audio length: 1 credit per started 5 minutes of audio, minimum 1 credit. It runs whenever a video has no captions, because "auto" is the default; send "mode": "captions" to rule it out.

Delivered resultCredits
Caption transcript, any length1
AI Fallback Transcription, up to 5 minutes1
AI Fallback Transcription, 10 minutes2
AI Fallback Transcription, 1 hour12
AI Fallback Transcription, 4 hours (the limit)48

Failures are free. A 202 has no usage because nothing has been delivered or charged yet. The completed response reports the actual charge in usage.credits_spent.

When retry_with appears

When mode: "captions" finds no caption track, the v2 error includes retry_with ("mode": "auto", which uses AI Fallback Transcription when there are no captions) only when an audio request is eligible and your available credits can cover the estimated charge:

JSON
{
  "ok": false,
  "request_id": "req_…",
  "error": {
    "code": "no_captions",
    "number": 4103,
    "message": "No caption track is available for this video.",
    "docs": "https://transcriptfetch.com/docs/errors/no_captions",
    "retry_with": { "mode": "auto" }
  }
}

Merge retry_with into the original request body and send it again to start AI Fallback Transcription. If the field is absent, changing mode would not currently help: for example, the content has no usable speech, cannot be reached, is not an eligible media input, or the estimated charge exceeds the available balance.