Extract data from a video URL

post/v1/extract

Request

  • Base URL: https://framefetch.net
  • URL: https://framefetch.net/v1/extract
  • Auth: HTTP bearer

Query parameters

format'md' | 'markdown' | 'srt' | 'vtt'

Render the response in an alternate view instead of JSON. 'md'/'markdown' returns a Markdown rendering (Content-Type: text/plain), equivalent to sending an Accept: text/plain or text/markdown header. 'srt'/'vtt' renders the transcript's timed segments as subtitles (Content-Type: application/x-subrip or text/vtt) — built from the TRANSLATED segments when the translate param was set, otherwise the source transcript's segments; this is purely an egress view, so it reuses the same cached ExtractResult, cost, and cache key as the plain JSON call. Opt-in only (never inferred from an ambiguous Accept header); JSON stays the default. Extract-family endpoints only (/v1/extract, /v1/metadata, /v1/transcript, /v1/frames); srt/vtt additionally require "transcript" in fields (or "digest", which pulls it in) and return 409 SUBTITLES_UNAVAILABLE if the result has no timed segments (e.g. an older cached entry).

Request body

urlstring uri required
fieldsstring[]

digest (LLM summary of the transcript) auto-includes transcript and degrades gracefully if none is available. audio_digest (a spoken mp3 briefing synthesized from the digest gist) auto-includes digest (and thus transcript); it returns a time-limited signed URL plus the voice/provider used, is billed per estimated spoken second only when the mp3 is actually produced, and degrades to a warning (never charged, never a hard error) when no TTS provider is configured or the requested language isn't supported by the only configured provider. When translate is also set, the digest is generated directly in that target language so the audio speaks it too — combine audio_digest with translate for a foreign-language briefing from one call. structured (typed JSON understanding of the video: chapters, entities, products_shown, claims, key_moments) auto-includes transcript and also triggers the engine's own keyframe pass over the source video, so it works even on caption-less sources; a single gpt-4o-mini vision call over the transcript plus up to 12 sampled keyframes, run at temperature 0 so the result is deterministic and cacheable; a flat $0.03 per video, charged only when the analysis is actually produced (a download/VLM/parse failure omits the field with a warning and is NOT charged — see StructuredError codes STRUCTURED_UNAVAILABLE, STRUCTURED_PROVIDER_ERROR, STRUCTURED_PARSE_ERROR on VideoStructured below). comments returns up to comments_cap top-level comments per video ({ items: [{ text, author?, like_count?, reply_count? }], total_fetched, cap_applied, sort:"top" }); it is INDEPENDENT of the transcript (no download) and available on YouTube only — Reddit's unauthenticated comment API was deprecated on 2026-05-28 and now returns a hard 403, so Reddit omits the field exactly like TikTok/Instagram/Pinterest, with a warning and never a charge (see GET /v1/platforms and COMMENTS_UNSUPPORTED on VideoComments below). Author is a display handle only (no user ids/urls). Flat $0.0045 per call, charged only when comments were actually produced. comment_sentiment (aggregated audience sentiment: percentages, themes, summary — ONE LLM pass over the comments) auto-includes comments (its input; same YouTube-only availability, Reddit's source having been deprecated) and needs at least 5 fetched comments — fewer, or a model/parse failure, omits it with a warning and is never charged (see CommentSentiment below). Flat $0.006 per call, on top of the comments call it rides on. No competitor offers this rollup. delta (change vs the most-recent prior fetch of the same url: engagement velocity per hour + title/thumbnail-change flags) is never cached and returns hasPrior:false the first time a url is seen. text_overlay (on-screen text via OCR) requires frames to also be requested, with a frames spec. Auto-skipped with a warning above 200 estimated frames.

verbositystring
translatestring

Optional ISO-639-1 target language code (e.g. "es", "de", "ja") to also translate the transcript into, surfaced as transcript_translated (with timings preserved when the source transcript had them). Requires "transcript" in fields (or "digest", which pulls transcript in). Billed per audio-minute like transcription — even for caption-sourced transcripts, since the translation is a separate LLM pass. Supported: en, es, de, fr, pt, it, nl, pl, tr, ru, uk, ar, hi, id, vi, th, ja, ko, zh, sv, da, no, fi, cs, ro (25 languages).

voice'alloy' | 'echo' | 'fable' | 'onyx' | 'nova' | 'shimmer' | 'Fritz-PlayAI'

Spoken voice for the "audio_digest" field: the six OpenAI gpt-4o-mini-tts voices (alloy, echo, fable, onyx, nova, shimmer — multilingual) plus Groq/PlayAI's "Fritz-PlayAI" (English/Arabic-only fallback, used when no OpenAI key is configured). Defaults to "alloy". Inert unless "audio_digest" is requested; an unlisted value is a typed 400 that echoes this allowlist.

comments_capinteger

Max number of top-level comments the "comments" field returns (1–200, default 30). Inert unless "comments" (or "comment_sentiment", which auto-includes it) is requested; a value outside 1–200 is a 400 INVALID_PARAMS.

publishboolean

Opt in to a public, shareable per-video SEO page at /v/<id> (a stable hash of the url). Publishes ONLY public metadata plus a short fair-use transcript excerpt — never the full transcript or a signed frame URL. Pages carry VideoObject structured data and are listed in /sitemap-videos.xml. Best-effort; never affects the API response.

Response

Extraction result. Returned as Markdown (Content-Type: text/plain) instead of JSON when ?format=md is set or an Accept: text/plain / text/markdown header is sent; returned as SubRip/WebVTT (Content-Type: application/x-subrip / text/vtt) when ?format=srt|vtt is set.

platformstring
urlstring
insightsobject

Changes

No recorded changes to this operation across all 1 revision of this API.