Quickstart
Get a key with an email address, then make one authenticated request. No password or card is required for the free tier.
1. Request a code
curl https://api.scripthaul.com/v1/auth/code \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com"}'
2. Verify and save the key
curl https://api.scripthaul.com/v1/auth/verify \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","code":"123456","accept_terms":true}'
The response shows the sh_live_… key once. Store it in a secret manager. Never put it in a URL, log, browser bundle, or query string.
export SCRIPTHAUL_API_KEY="sh_live_replace_me"
3. Fetch a transcript
curl --get https://api.scripthaul.com/v1/transcript \
-H "Authorization: Bearer $SCRIPTHAUL_API_KEY" \
--data-urlencode "video_id=jNQXAC9IVRw" \
--data-urlencode "format=clean"
Inspect X-Cache, X-Credits-Charged, X-Credits-Balance, and X-Request-Id. A cache hit costs 0. A successful cold delivery costs 1. Failures cost 0.
4. Download SRT
curl --get https://api.scripthaul.com/v1/transcript \
-H "Authorization: Bearer $SCRIPTHAUL_API_KEY" \
--data-urlencode "video_id=jNQXAC9IVRw" \
--data-urlencode "format=srt" \
--data-urlencode "raw=1" \
-o jNQXAC9IVRw.srt
Cold calls may return 202 after 25 seconds. Follow the returned poll_url with the same Bearer key; polling itself does not add another delivery charge.
Thin clients
The MIT-licensed JavaScript and Python clients are published to npm and PyPI once the live verification run passes; until then use curl or copy the examples. Every response carries meta (cache, credits charged, balance, rate limit, request id), and wait() stops on a paused job instead of polling through it. Both clients expose the same small surface: transcript(), videos(), and jobs.create() returning a job with wait(). They bound retries for 429/502/503 responses and 202 polling, raise typed errors that mirror errorClass, and keep request_id on exceptions.
import ScriptHaul from "scripthaul";
const client = new ScriptHaul({ apiKey: process.env.SCRIPTHAUL_API_KEY });
const job = await client.jobs.create({ input: "https://www.youtube.com/@example" });
await job.wait();
from scripthaul import ScriptHaul
client = ScriptHaul()
job = client.jobs.create(input="https://www.youtube.com/@example").wait()
Next
- Understand requested and delivered languages
- List channel and playlist videos
- See every credit and capacity limit
- Handle typed errors
Quickstart in four languages
All examples read the key from SCRIPTHAUL_API_KEY. Maintained runnable versions are in the examples directory.
curl --get https://api.scripthaul.com/v1/transcript \
-H "Authorization: Bearer $SCRIPTHAUL_API_KEY" \
--data-urlencode "video_id=jNQXAC9IVRw" --data-urlencode "format=clean"
import os, urllib.request
request = urllib.request.Request("https://api.scripthaul.com/v1/transcript?video_id=jNQXAC9IVRw&format=clean")
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&format=clean", {
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&format=clean", 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)