curl --request POST \
--url https://api.vidnavigator.com/v1/extract/video \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"video_url": "https://youtube.com/watch?v=dQw4w9WgXcQ",
"schema": {
"main_topics": {
"type": "Array",
"description": "List of main topics discussed",
"items": {
"type": "String",
"description": "A topic"
}
},
"sentiment": {
"type": "Enum",
"description": "Overall sentiment of the video",
"enum": [
"positive",
"negative",
"neutral"
]
},
"key_takeaway": {
"type": "String",
"description": "The single most important takeaway"
}
},
"what_to_extract": "Extract the main topics and any product names mentioned",
"transcribe": true,
"include_usage": false
}
'import requests
url = "https://api.vidnavigator.com/v1/extract/video"
payload = {
"video_url": "https://youtube.com/watch?v=dQw4w9WgXcQ",
"schema": {
"main_topics": {
"type": "Array",
"description": "List of main topics discussed",
"items": {
"type": "String",
"description": "A topic"
}
},
"sentiment": {
"type": "Enum",
"description": "Overall sentiment of the video",
"enum": ["positive", "negative", "neutral"]
},
"key_takeaway": {
"type": "String",
"description": "The single most important takeaway"
}
},
"what_to_extract": "Extract the main topics and any product names mentioned",
"transcribe": True,
"include_usage": False
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
video_url: 'https://youtube.com/watch?v=dQw4w9WgXcQ',
schema: {
main_topics: {
type: 'Array',
description: 'List of main topics discussed',
items: {type: 'String', description: 'A topic'}
},
sentiment: {
type: 'Enum',
description: 'Overall sentiment of the video',
enum: ['positive', 'negative', 'neutral']
},
key_takeaway: {type: 'String', description: 'The single most important takeaway'}
},
what_to_extract: 'Extract the main topics and any product names mentioned',
transcribe: true,
include_usage: false
})
};
fetch('https://api.vidnavigator.com/v1/extract/video', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vidnavigator.com/v1/extract/video",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'video_url' => 'https://youtube.com/watch?v=dQw4w9WgXcQ',
'schema' => [
'main_topics' => [
'type' => 'Array',
'description' => 'List of main topics discussed',
'items' => [
'type' => 'String',
'description' => 'A topic'
]
],
'sentiment' => [
'type' => 'Enum',
'description' => 'Overall sentiment of the video',
'enum' => [
'positive',
'negative',
'neutral'
]
],
'key_takeaway' => [
'type' => 'String',
'description' => 'The single most important takeaway'
]
],
'what_to_extract' => 'Extract the main topics and any product names mentioned',
'transcribe' => true,
'include_usage' => false
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vidnavigator.com/v1/extract/video"
payload := strings.NewReader("{\n \"video_url\": \"https://youtube.com/watch?v=dQw4w9WgXcQ\",\n \"schema\": {\n \"main_topics\": {\n \"type\": \"Array\",\n \"description\": \"List of main topics discussed\",\n \"items\": {\n \"type\": \"String\",\n \"description\": \"A topic\"\n }\n },\n \"sentiment\": {\n \"type\": \"Enum\",\n \"description\": \"Overall sentiment of the video\",\n \"enum\": [\n \"positive\",\n \"negative\",\n \"neutral\"\n ]\n },\n \"key_takeaway\": {\n \"type\": \"String\",\n \"description\": \"The single most important takeaway\"\n }\n },\n \"what_to_extract\": \"Extract the main topics and any product names mentioned\",\n \"transcribe\": true,\n \"include_usage\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.vidnavigator.com/v1/extract/video")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"video_url\": \"https://youtube.com/watch?v=dQw4w9WgXcQ\",\n \"schema\": {\n \"main_topics\": {\n \"type\": \"Array\",\n \"description\": \"List of main topics discussed\",\n \"items\": {\n \"type\": \"String\",\n \"description\": \"A topic\"\n }\n },\n \"sentiment\": {\n \"type\": \"Enum\",\n \"description\": \"Overall sentiment of the video\",\n \"enum\": [\n \"positive\",\n \"negative\",\n \"neutral\"\n ]\n },\n \"key_takeaway\": {\n \"type\": \"String\",\n \"description\": \"The single most important takeaway\"\n }\n },\n \"what_to_extract\": \"Extract the main topics and any product names mentioned\",\n \"transcribe\": true,\n \"include_usage\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vidnavigator.com/v1/extract/video")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"video_url\": \"https://youtube.com/watch?v=dQw4w9WgXcQ\",\n \"schema\": {\n \"main_topics\": {\n \"type\": \"Array\",\n \"description\": \"List of main topics discussed\",\n \"items\": {\n \"type\": \"String\",\n \"description\": \"A topic\"\n }\n },\n \"sentiment\": {\n \"type\": \"Enum\",\n \"description\": \"Overall sentiment of the video\",\n \"enum\": [\n \"positive\",\n \"negative\",\n \"neutral\"\n ]\n },\n \"key_takeaway\": {\n \"type\": \"String\",\n \"description\": \"The single most important takeaway\"\n }\n },\n \"what_to_extract\": \"Extract the main topics and any product names mentioned\",\n \"transcribe\": true,\n \"include_usage\": false\n}"
response = http.request(request)
puts response.read_body{
"status": "success",
"data": {},
"video_info": {
"title": "<string>",
"description": "<string>",
"thumbnail": "<string>",
"url": "<string>",
"channel": "<string>",
"channel_url": "<string>",
"duration": 123,
"views": 123,
"likes": 123,
"published_date": "<string>",
"keywords": [
"<string>"
],
"category": "<string>",
"available_languages": [
"<string>"
],
"selected_language": "<string>",
"carousel_info": {
"total_items": 123,
"video_count": 123,
"image_count": 123,
"selected_index": 123
}
},
"file_info": {
"id": "<string>",
"name": "<string>",
"size": 123,
"type": "<string>",
"duration": 123,
"status": "pending",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"original_file_date": "2023-11-07T05:31:56Z",
"has_transcript": true,
"error_message": "<string>",
"namespace_ids": [
"<string>"
],
"namespaces": [
{
"id": "<string>",
"name": "<string>"
}
]
},
"usage": {
"charges": [
{
"service_type": "standard_request",
"quantity": 123,
"credits": 123,
"waived": true,
"credits_saved": 123,
"tokens": {
"prompt_tokens": 123,
"completion_tokens": 123,
"total_tokens": 123
}
}
],
"total_credits": 123,
"waived": {
"credits_saved": 123
}
}
}{
"status": "error",
"error": "missing_parameter",
"message": "<string>"
}{
"status": "error",
"error": "limit_exceeded",
"message": "<string>"
}{
"status": "error",
"error": "video_not_found",
"message": "<string>"
}{
"status": "error",
"error": "internal_server_error",
"message": "<string>"
}{
"status": "error",
"error": "system_overload",
"message": "<string>",
"retry_after_seconds": 123,
"charge_user": true
}Extract Data from Video
Extract structured data from an online video’s transcript using a custom schema.
Provide a video_url and a schema describing the fields to extract. Optionally include what_to_extract to guide the extraction.
Auto-transcription: For non-YouTube videos without an existing transcript (e.g. Instagram, TikTok, Facebook), the API automatically transcribes the video audio when transcribe is true (the default). This uses speech-to-text credits (transcription_hour usage). YouTube videos rely on platform captions and cannot be auto-transcribed. Set transcribe=false to disable this behavior.
Schema format: Each field must have type and description. Supported types: String, Number, Boolean, Integer, Object, Array, Enum. Max 10 root fields, max 3 nesting levels.
Content-Type: Accepts application/json, YAML (application/yaml, application/x-yaml, text/yaml), or multipart/form-data. For multipart requests, send video_url as a form field and schema as either a JSON/YAML form value or an uploaded JSON/YAML file (for example, schema=@fact-check.yaml). If the uploaded schema file contains a full request body with a nested schema property, the nested schema is used and the form video_url takes precedence.
Token usage: Set include_usage=true to include prompt/completion token counts in the response.
Billing: Each extraction consumes at least 1 analysis_request unit. For longer transcripts, billing scales as ceil(total_tokens / 15000) analysis_request units. If auto-transcription is triggered, transcription_hour usage is also charged based on video duration. All charges are reverted if the request fails.
Long videos: this endpoint is synchronous and holds the connection open for the whole transcription. For media longer than ~10 minutes use POST /extract/video/async instead, which returns a task_id and can call your webhook when it finishes. Media longer than 10 minutes is rejected here with video_too_long (HTTP 400). The metadata fetch needed to read the video’s duration is billed (standard_request or residential_request) and is not refunded: the limit is documented, so the proxy call was spent answering a request that could not be served. No transcription_hour is charged — no audio is processed. Send long media to the async endpoint, which has no cap. See https://docs.vidnavigator.com/guides/async-jobs
curl --request POST \
--url https://api.vidnavigator.com/v1/extract/video \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"video_url": "https://youtube.com/watch?v=dQw4w9WgXcQ",
"schema": {
"main_topics": {
"type": "Array",
"description": "List of main topics discussed",
"items": {
"type": "String",
"description": "A topic"
}
},
"sentiment": {
"type": "Enum",
"description": "Overall sentiment of the video",
"enum": [
"positive",
"negative",
"neutral"
]
},
"key_takeaway": {
"type": "String",
"description": "The single most important takeaway"
}
},
"what_to_extract": "Extract the main topics and any product names mentioned",
"transcribe": true,
"include_usage": false
}
'import requests
url = "https://api.vidnavigator.com/v1/extract/video"
payload = {
"video_url": "https://youtube.com/watch?v=dQw4w9WgXcQ",
"schema": {
"main_topics": {
"type": "Array",
"description": "List of main topics discussed",
"items": {
"type": "String",
"description": "A topic"
}
},
"sentiment": {
"type": "Enum",
"description": "Overall sentiment of the video",
"enum": ["positive", "negative", "neutral"]
},
"key_takeaway": {
"type": "String",
"description": "The single most important takeaway"
}
},
"what_to_extract": "Extract the main topics and any product names mentioned",
"transcribe": True,
"include_usage": False
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
video_url: 'https://youtube.com/watch?v=dQw4w9WgXcQ',
schema: {
main_topics: {
type: 'Array',
description: 'List of main topics discussed',
items: {type: 'String', description: 'A topic'}
},
sentiment: {
type: 'Enum',
description: 'Overall sentiment of the video',
enum: ['positive', 'negative', 'neutral']
},
key_takeaway: {type: 'String', description: 'The single most important takeaway'}
},
what_to_extract: 'Extract the main topics and any product names mentioned',
transcribe: true,
include_usage: false
})
};
fetch('https://api.vidnavigator.com/v1/extract/video', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vidnavigator.com/v1/extract/video",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'video_url' => 'https://youtube.com/watch?v=dQw4w9WgXcQ',
'schema' => [
'main_topics' => [
'type' => 'Array',
'description' => 'List of main topics discussed',
'items' => [
'type' => 'String',
'description' => 'A topic'
]
],
'sentiment' => [
'type' => 'Enum',
'description' => 'Overall sentiment of the video',
'enum' => [
'positive',
'negative',
'neutral'
]
],
'key_takeaway' => [
'type' => 'String',
'description' => 'The single most important takeaway'
]
],
'what_to_extract' => 'Extract the main topics and any product names mentioned',
'transcribe' => true,
'include_usage' => false
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vidnavigator.com/v1/extract/video"
payload := strings.NewReader("{\n \"video_url\": \"https://youtube.com/watch?v=dQw4w9WgXcQ\",\n \"schema\": {\n \"main_topics\": {\n \"type\": \"Array\",\n \"description\": \"List of main topics discussed\",\n \"items\": {\n \"type\": \"String\",\n \"description\": \"A topic\"\n }\n },\n \"sentiment\": {\n \"type\": \"Enum\",\n \"description\": \"Overall sentiment of the video\",\n \"enum\": [\n \"positive\",\n \"negative\",\n \"neutral\"\n ]\n },\n \"key_takeaway\": {\n \"type\": \"String\",\n \"description\": \"The single most important takeaway\"\n }\n },\n \"what_to_extract\": \"Extract the main topics and any product names mentioned\",\n \"transcribe\": true,\n \"include_usage\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.vidnavigator.com/v1/extract/video")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"video_url\": \"https://youtube.com/watch?v=dQw4w9WgXcQ\",\n \"schema\": {\n \"main_topics\": {\n \"type\": \"Array\",\n \"description\": \"List of main topics discussed\",\n \"items\": {\n \"type\": \"String\",\n \"description\": \"A topic\"\n }\n },\n \"sentiment\": {\n \"type\": \"Enum\",\n \"description\": \"Overall sentiment of the video\",\n \"enum\": [\n \"positive\",\n \"negative\",\n \"neutral\"\n ]\n },\n \"key_takeaway\": {\n \"type\": \"String\",\n \"description\": \"The single most important takeaway\"\n }\n },\n \"what_to_extract\": \"Extract the main topics and any product names mentioned\",\n \"transcribe\": true,\n \"include_usage\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vidnavigator.com/v1/extract/video")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"video_url\": \"https://youtube.com/watch?v=dQw4w9WgXcQ\",\n \"schema\": {\n \"main_topics\": {\n \"type\": \"Array\",\n \"description\": \"List of main topics discussed\",\n \"items\": {\n \"type\": \"String\",\n \"description\": \"A topic\"\n }\n },\n \"sentiment\": {\n \"type\": \"Enum\",\n \"description\": \"Overall sentiment of the video\",\n \"enum\": [\n \"positive\",\n \"negative\",\n \"neutral\"\n ]\n },\n \"key_takeaway\": {\n \"type\": \"String\",\n \"description\": \"The single most important takeaway\"\n }\n },\n \"what_to_extract\": \"Extract the main topics and any product names mentioned\",\n \"transcribe\": true,\n \"include_usage\": false\n}"
response = http.request(request)
puts response.read_body{
"status": "success",
"data": {},
"video_info": {
"title": "<string>",
"description": "<string>",
"thumbnail": "<string>",
"url": "<string>",
"channel": "<string>",
"channel_url": "<string>",
"duration": 123,
"views": 123,
"likes": 123,
"published_date": "<string>",
"keywords": [
"<string>"
],
"category": "<string>",
"available_languages": [
"<string>"
],
"selected_language": "<string>",
"carousel_info": {
"total_items": 123,
"video_count": 123,
"image_count": 123,
"selected_index": 123
}
},
"file_info": {
"id": "<string>",
"name": "<string>",
"size": 123,
"type": "<string>",
"duration": 123,
"status": "pending",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"original_file_date": "2023-11-07T05:31:56Z",
"has_transcript": true,
"error_message": "<string>",
"namespace_ids": [
"<string>"
],
"namespaces": [
{
"id": "<string>",
"name": "<string>"
}
]
},
"usage": {
"charges": [
{
"service_type": "standard_request",
"quantity": 123,
"credits": 123,
"waived": true,
"credits_saved": 123,
"tokens": {
"prompt_tokens": 123,
"completion_tokens": 123,
"total_tokens": 123
}
}
],
"total_credits": 123,
"waived": {
"credits_saved": 123
}
}
}{
"status": "error",
"error": "missing_parameter",
"message": "<string>"
}{
"status": "error",
"error": "limit_exceeded",
"message": "<string>"
}{
"status": "error",
"error": "video_not_found",
"message": "<string>"
}{
"status": "error",
"error": "internal_server_error",
"message": "<string>"
}{
"status": "error",
"error": "system_overload",
"message": "<string>",
"retry_after_seconds": 123,
"charge_user": true
}Overview
The extraction endpoint lets you pull structured, typed data from any video transcript by providing a JSON schema describing the fields you need. This is ideal for building automated pipelines that need consistent, machine-readable output from video content.How It Works
- Provide a
video_urland aschemadefining the fields to extract - VidNavigator fetches the platform transcript when available
- For supported non-YouTube sources, it can auto-transcribe audio when no transcript exists
- VidNavigator runs AI extraction against your schema
- You receive structured JSON matching your schema definition, plus
video_info
Schema Rules
- Each field must have
typeanddescription - Supported types:
String,Number,Boolean,Integer,Object,Array,Enum - Maximum 10 root-level fields
- Maximum 3 nesting levels
Content-Type to application/x-yaml or text/yaml.Automatic Transcription
Thetranscribe parameter controls whether VidNavigator should automatically fall back to speech-to-text when a transcript is not available.
transcribe=trueby default- applies to non-YouTube videos only
- useful for platforms like Instagram, TikTok, Facebook, X, and similar sources
- YouTube extraction relies on platform captions and does not support speech-to-text fallback through this endpoint
transcribe=false, the request will fail when no transcript is available instead of triggering speech-to-text processing.
Synchronous or async?
The extraction itself is fast; the speech-to-text step in front of it is what takes time on long videos. This endpoint therefore comes in two modes, with the same request body and the same result:| Mode | Endpoint | Media duration (with speech-to-text) | How you get the result |
|---|---|---|---|
| Synchronous | POST /extract/video | Up to 10 minutes | In the HTTP response |
| Async | POST /extract/video/async | Any length | Poll GET /extract/video/{task_id} or receive a webhook |
transcribe is on and the video is longer than 10 minutes, the synchronous endpoint rejects it with 400 video_too_long. Use the async mode whenever the video may run past 10 minutes — it also works for short videos.Example Usage
Basic Extraction
curl -X POST "https://api.vidnavigator.com/v1/extract/video" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://youtube.com/watch?v=dQw4w9WgXcQ",
"schema": {
"main_topics": {
"type": "Array",
"description": "List of main topics discussed",
"items": { "type": "String", "description": "A topic" }
},
"sentiment": {
"type": "Enum",
"description": "Overall sentiment of the video",
"enum": ["positive", "negative", "neutral"]
},
"key_takeaway": {
"type": "String",
"description": "The single most important takeaway"
}
}
}'
import requests
url = "https://api.vidnavigator.com/v1/extract/video"
headers = {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
}
data = {
"video_url": "https://youtube.com/watch?v=dQw4w9WgXcQ",
"schema": {
"main_topics": {
"type": "Array",
"description": "List of main topics discussed",
"items": {"type": "String", "description": "A topic"}
},
"sentiment": {
"type": "Enum",
"description": "Overall sentiment of the video",
"enum": ["positive", "negative", "neutral"]
},
"key_takeaway": {
"type": "String",
"description": "The single most important takeaway"
}
}
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
print(result["data"])
const response = await fetch('https://api.vidnavigator.com/v1/extract/video', {
method: 'POST',
headers: {
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
video_url: 'https://youtube.com/watch?v=dQw4w9WgXcQ',
schema: {
main_topics: {
type: 'Array',
description: 'List of main topics discussed',
items: { type: 'String', description: 'A topic' }
},
sentiment: {
type: 'Enum',
description: 'Overall sentiment of the video',
enum: ['positive', 'negative', 'neutral']
},
key_takeaway: {
type: 'String',
description: 'The single most important takeaway'
}
}
})
});
const result = await response.json();
With Extraction Guidance
Usewhat_to_extract to provide additional context to the AI about what to focus on:
curl -X POST "https://api.vidnavigator.com/v1/extract/video" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://youtube.com/watch?v=dQw4w9WgXcQ",
"what_to_extract": "Focus on product names and pricing mentioned in the video",
"schema": {
"products": {
"type": "Array",
"description": "Products mentioned in the video",
"items": {
"type": "Object",
"description": "A product",
"properties": {
"name": { "type": "String", "description": "Product name" },
"price": { "type": "String", "description": "Price if mentioned" }
}
}
}
},
"include_usage": true
}'
Disable Auto-Transcription
Usetranscribe=false when you want extraction to run only if a platform transcript already exists:
curl -X POST "https://api.vidnavigator.com/v1/extract/video" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://www.instagram.com/reel/example/",
"transcribe": false,
"schema": {
"main_claim": {
"type": "String",
"description": "Main claim made in the video"
}
}
}'
Response Example
{
"status": "success",
"data": {
"main_topics": ["machine learning", "neural networks", "data preprocessing"],
"sentiment": "positive",
"key_takeaway": "Start with clean data before choosing a model architecture"
},
"video_info": {
"title": "Machine Learning Fundamentals",
"description": "An introduction to practical machine learning workflows.",
"thumbnail": "https://example.com/thumbnail.jpg",
"url": "https://youtube.com/watch?v=example123",
"channel": "AI Academy",
"duration": 4520.0,
"views": 152340,
"likes": 8100,
"published_date": "2026-03-05",
"keywords": ["machine learning", "ai", "data science"],
"category": "Education"
},
"usage": {
"prompt_tokens": 2150,
"completion_tokens": 85,
"total_tokens": 2235
}
}
usage field is only included when include_usage=true in the request. video_info is included in the response metadata.Billing
- AI extraction consumes
analysis_requestunits in blocks of 15,000 total tokens - Formula:
ceil(total_tokens / 15000) - Examples:
14,000tokens ->1analysis_requestunit17,000tokens ->2analysis_requestunits31,000tokens ->3analysis_requestunits
- If
transcribe=truetriggers speech-to-text fallback, speech-to-text is charged separately astranscription_hourusage based on video/audio duration - Failed requests are not charged
- Set
include_usage: trueto receive ausageblock with the per-charge breakdown (theanalysis_requestentry carries a nestedtokensobject) - The async mode is billed exactly the same way
- A
video_too_longrejection on the synchronous endpoint still bills the metadata fetch that read the duration (standard_requestorresidential_request, not refunded), but notranscription_hourand noanalysis_request
Error Responses
| Status | error | Description |
|---|---|---|
400 | missing_parameter, request_body_required, invalid_schema, input_too_large | Invalid request or schema. |
400 | video_too_long | Speech-to-text is needed and the media is longer than 10 minutes. Use POST /extract/video/async. |
402 | limit_exceeded | Not enough credits. |
404 | video_not_found, video_unavailable, transcript_not_available | The video can’t be found or accessed, or no transcript is available. |
500 | extraction_failed, transcription_failed, internal_server_error | Processing failed. Charges are reverted. |
503 | system_overload | Temporarily overloaded. Retry later. |
Use Cases
Data Pipelines
Content Cataloging
Market Research
Compliance Monitoring
Authorizations
API key authentication. Include your VidNavigator API key in the X-API-Key header.
Body
URL of the video to extract data from
"https://youtube.com/watch?v=dQw4w9WgXcQ"
Custom extraction schema defining the fields to extract. Max 10 root-level fields, max 3 nesting levels. Each field must have type and description.
Show child attributes
Show child attributes
{ "main_topics": { "type": "Array", "description": "List of main topics discussed", "items": { "type": "String", "description": "A topic" } }, "sentiment": { "type": "Enum", "description": "Overall sentiment of the video", "enum": ["positive", "negative", "neutral"] }, "key_takeaway": { "type": "String", "description": "The single most important takeaway" } }
Optional guidance for what to extract from the transcript
"Extract the main topics and any product names mentioned"
When true, automatically transcribes the video audio if no platform transcript is available. Applies to non-YouTube videos only (Instagram, TikTok, Facebook, X, etc.). Uses speech-to-text credits based on video duration.
When true, includes token usage statistics in the response
Response
Data extracted successfully
success Extracted data matching the provided schema. The shape of this object mirrors the input schema fields.
Video metadata (title, channel, duration, views, etc.). Only present for /extract/video requests.
Show child attributes
Show child attributes
File metadata (name, size, type, duration, etc.). Only present for /extract/file requests.
Show child attributes
Show child attributes
Per-call billing + LLM token usage. Only present when include_usage=true. For /extract/*, the block carries the credit-charge fields (charges, total_credits, credits_remaining_after, waived) AND the LLM token fields (prompt_tokens, completion_tokens, total_tokens) in a single object.
Show child attributes
Show child attributes

