Skip to Content

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). 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.

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). Send long media to the async endpoint, which has no cap. See https://docs.vidnavigator.com/guides/async-jobs

POST
/extract/video

Extract structured data from an online video's transcript using a custom schema you define.

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

  1. Provide a video_url and a schema defining the fields to extract
  2. VidNavigator fetches the platform transcript when available
  3. For supported non-YouTube sources, it can auto-transcribe audio when no transcript exists
  4. VidNavigator runs AI extraction against your schema
  5. You receive structured JSON matching your schema definition, plus video_info

Schema Rules

  • Each field must have type and description
  • Supported types: String, Number, Boolean, Integer, Object, Array, Enum
  • Maximum 10 root-level fields
  • Maximum 3 nesting levels

You can also send the request body as YAML by setting Content-Type to application/x-yaml or text/yaml.

Automatic Transcription

The transcribe parameter controls whether VidNavigator should automatically fall back to speech-to-text when a transcript is not available.

  • transcribe=true by 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

If you set 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:

ModeEndpointMedia duration (with speech-to-text)How you get the result
SynchronousPOST /extract/videoUp to 10 minutesIn the HTTP response
AsyncPOST /extract/video/asyncAny lengthPoll GET /extract/video/{task_id} or receive a webhook

When 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"
      }
    }
  }'

With Extraction Guidance

Use what_to_extract to provide additional context to the AI about what to focus on:

cURL
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

Use transcribe=false when you want extraction to run only if a platform transcript already exists:

cURL
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
  }
}

The 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_request units in blocks of 15,000 total tokens
  • Formula: ceil(total_tokens / 15000)
  • Examples:
    • 14,000 tokens -> 1 analysis_request unit
    • 17,000 tokens -> 2 analysis_request units
    • 31,000 tokens -> 3 analysis_request units
  • If transcribe=true triggers speech-to-text fallback, speech-to-text is charged separately as transcription_hour usage based on video/audio duration
  • Failed requests are not charged
  • Set include_usage: true to receive a usage block with the per-charge breakdown (the analysis_request entry carries a nested tokens object)
  • The async mode is billed exactly the same way
  • A video_too_long rejection on the synchronous endpoint still bills the metadata fetch that read the duration (standard_request or residential_request, not refunded), but no transcription_hour and no analysis_request

Error Responses

StatuserrorDescription
400missing_parameter, request_body_required, invalid_schema, input_too_largeInvalid request or schema.
400video_too_longSpeech-to-text is needed and the media is longer than 10 minutes. Use POST /extract/video/async.
402limit_exceededNot enough credits.
404video_not_found, video_unavailable, transcript_not_availableThe video can't be found or accessed, or no transcript is available.
500extraction_failed, transcription_failed, internal_server_errorProcessing failed. Charges are reverted.
503system_overloadTemporarily overloaded. Retry later.

See Errors for the full list.

Use Cases

Data Pipelines

Build automated pipelines that extract consistent structured data from video content at scale

Content Cataloging

Automatically tag and categorize videos with custom taxonomies

Market Research

Extract product mentions, sentiment, and competitive insights from video reviews

Compliance Monitoring

Pull specific compliance-relevant data points from training or policy videos

API reference

Authorization

ApiKeyAuth
headerX-API-Key<token>

API key authentication. Include your VidNavigator API key in the X-API-Key header.

Request Body

  1. body
video_url*string

URL of the video to extract data from

Formaturi
schema*

Custom extraction schema defining the fields to extract. Max 10 root-level fields, max 3 nesting levels. Each field must have type and description.

what_to_extract?string

Optional guidance for what to extract from the transcript

transcribe?boolean

When true, automatically transcribes the video audio if no platform transcript is available. Applies to non-YouTube videos only (Instagram, TikTok, Facebook, X, etc.).

Defaulttrue
include_usage?boolean

When true, includes token usage statistics in the response

Defaultfalse

Response Body

Data extracted successfully

application/json
  1. response
status?"success"
Value in"success"
data?

Extracted data matching the provided schema. The shape of this object mirrors the input schema fields.

video_info?

Video metadata (title, channel, duration, views, etc.). Only present for /extract/video requests.

file_info?

File metadata (name, size, type, duration, etc.). Only present for /extract/file requests.

usage?

Per-call usage, only present when include_usage=true: the charges (charges, total_credits, credits_remaining_after, waived) and the token counts (prompt_tokens, completion_tokens, total_tokens) in one object.

Example Request
curl -X POST 'https://api.vidnavigator.com/v1/extract/video' \  -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"    }  }}'
Example Response
{  "status": "success",  "data": {},  "video_info": {    "title": "string",    "description": "string",    "thumbnail": "http://example.com",    "url": "http://example.com",    "channel": "string",    "channel_url": "http://example.com",    "duration": 0,    "views": 0,    "likes": 0,    "published_date": "string",    "keywords": [      "string"    ],    "category": "string",    "available_languages": [      "string"    ],    "selected_language": "string",    "carousel_info": {      "total_items": 0,      "video_count": 0,      "image_count": 0,      "selected_index": 0    }  },  "file_info": {    "id": "string",    "name": "string",    "size": 0,    "type": "string",    "duration": 0,    "status": "pending",    "created_at": "2019-08-24T14:15:22Z",    "updated_at": "2019-08-24T14:15:22Z",    "original_file_date": "2019-08-24T14:15:22Z",    "has_transcript": true,    "error_message": "string",    "namespace_ids": [      "string"    ],    "namespaces": [      {        "id": "string",        "name": "string"      }    ]  },  "usage": {    "charges": [      {        "service_type": "standard_request",        "quantity": 0,        "credits": 0,        "waived": true,        "credits_saved": 0,        "tokens": {          "prompt_tokens": 0,          "completion_tokens": 0,          "total_tokens": 0        }      }    ],    "total_credits": 0,    "waived": {      "credits_saved": 0    }  }}

On this page