Skip to main content
Every error response is a JSON body with an error field. The error value is sometimes a machine-readable slug (e.g. "no_credits", "limit_reached") and sometimes a human-readable sentence — see the table below for which is which. Status codes are consistent across all four platform endpoints.
{ "error": "Description or slug" }

Status codes

CodeNameWhen it fireserror field
400Bad RequestInvalid JSON body, missing url, or url doesn’t match the expected platform formatInvalid JSON body / Missing "url" in request body / Invalid URL. Please provide a valid <Platform> video URL.
401UnauthorizedMissing, malformed, or revoked API keyInvalid API key
403ForbiddenAccount out of creditsno_credits (slug) — body also includes credits: 0 and a human-readable message
404Not FoundUpstream platform reported the video doesn’t exist, is private, or has no transcript availableVideo not found / Shoot the post does not have a video / No transcript available for this video (varies — comes from upstream)
429Rate Limited60 req/min cap exceeded for this keyRate limit exceeded. Try again later. — see rate limits
500Internal ErrorUnexpected worker error, or SCRAPECREATORS_API_KEY unset on the server sideInternal server error / API key not configured
502Bad GatewayUpstream platform API returned a non-2xx HTTP statusFailed to fetch transcript — body also includes a details string echoing the upstream payload
404 vs 502: a 502 means the upstream HTTP request itself failed (network error, upstream 5xx, etc.). A 404 means the upstream returned 200 but flagged the video as not retrievable (deleted, private, no captions). Treat both as “this video can’t be transcribed today” — but only 502 is worth retrying.

Retry guidance

Retry only on 429 and 502. Use exponential backoff with jitter, and cap retries at 3–5 attempts. Don’t retry on other 4xx codes — the request itself is wrong, retrying won’t fix it.
A common pattern:
import time, random, requests

def call_with_backoff(url, payload, headers, max_retries=4):
    for attempt in range(max_retries):
        r = requests.post(url, json=payload, headers=headers)

        if r.status_code < 400:
            return r

        if r.status_code == 429:
            time.sleep(int(r.headers.get("Retry-After", "1")))
            continue

        if r.status_code == 502:
            time.sleep((2 ** attempt) + random.uniform(0, 1))
            continue

        # Non-retriable error (400, 401, 403, 404, 500)
        r.raise_for_status()

    r.raise_for_status()

Reporting issues

If you hit a status code that doesn’t match the table above, or you see persistent 5xx errors on a URL you believe should work, email hello@transcriptmagic.com with the URL and approximate timestamp — we’ll investigate.