ScriptHaul API
Log inGet API key

Languages and strict mode

Every transcript and job row separates what you asked for from what was delivered. Never infer a translation from the text alone; use the structured language object.

FieldMeaning
requestedNormalized language requested by the client.
deliveredLanguage code on the caption track actually served.
kindmanual or asr for auto-generated captions.
fallbacktrue only when a different available language was deliberately substituted.
translationnot_requested, served, refused, or unavailable. Job rows show null before delivery.

refused means YouTube's translation throttle declined the request this time and the source track was delivered instead; retrying later can succeed. unavailable means the video offers no translation into the requested language at all, so a retry cannot change the outcome. In strict mode the first is a retryable translation_refused error and the second a language_unavailable error listing available_languages; both cost 0.

fallback=true permits a labelled substitute when the requested track cannot be delivered. fallback=false is strict mode: ScriptHaul returns an actionable language error with available languages and charges zero rather than silently switching. A translation refusal is also labelled; it is never presented as though the requested text arrived.

When YouTube declines a translation, a keyed request or bulk job that sets translate=true can still receive the requested language, labelled served, for 300 credits per started 10,000 characters of transcript (at most 1,500), on top of the delivery credit. See when that applies for single transcripts and bulk jobs; without translate=true, and whenever it cannot apply, the outcomes above are unchanged.

Language matching uses normalized BCP 47-style tags. A base request such as en may match a compatible regional source such as en-US; the response still reports the delivered tag. Cache hits preserve the original track kind and translation verdict.

Strict request in four languages

Maintained runnable versions are in the examples directory.

curl 'https://api.scripthaul.com/v1/transcript?video_id=jNQXAC9IVRw&language=es&fallback=false&format=json' -H "Authorization: Bearer $SCRIPTHAUL_API_KEY"
import os, urllib.request
url = "https://api.scripthaul.com/v1/transcript?video_id=jNQXAC9IVRw&language=es&fallback=false&format=json"
request = urllib.request.Request(url)
request.add_header("Authorization", f"Bearer {os.environ['SCRIPTHAUL_API_KEY']}")
print(urllib.request.urlopen(request).read().decode())
const response = await fetch("https://api.scripthaul.com/v1/transcript?video_id=jNQXAC9IVRw&language=es&fallback=false&format=json", {
  headers: { Authorization: `Bearer ${process.env.SCRIPTHAUL_API_KEY}` },
});
console.log(await response.json());
req, _ := http.NewRequest("GET", "https://api.scripthaul.com/v1/transcript?video_id=jNQXAC9IVRw&language=es&fallback=false&format=json", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("SCRIPTHAUL_API_KEY"))
response, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer response.Body.Close()
io.Copy(os.Stdout, response.Body)