Languages and strict mode
Every transcript and job row separates what you asked for from what YouTube delivered. Never infer a translation from the text alone; use the structured language object.
| Field | Meaning |
|---|---|
requested | Normalized language requested by the client. |
delivered | Language code on the caption track actually served. |
kind | manual or asr for auto-generated captions. |
fallback | true only when a different available language was deliberately substituted. |
translation | not_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.
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)