curl --request POST \
--url https://api.vidnavigator.com/v1/transcribe \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"video_url": "https://www.instagram.com/reel/C86ZvEaqRmo/",
"transcript_text": false,
"all_videos": false,
"include_usage": false
}
'import requests
url = "https://api.vidnavigator.com/v1/transcribe"
payload = {
"video_url": "https://www.instagram.com/reel/C86ZvEaqRmo/",
"transcript_text": False,
"all_videos": False,
"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://www.instagram.com/reel/C86ZvEaqRmo/',
transcript_text: false,
all_videos: false,
include_usage: false
})
};
fetch('https://api.vidnavigator.com/v1/transcribe', 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/transcribe",
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://www.instagram.com/reel/C86ZvEaqRmo/',
'transcript_text' => false,
'all_videos' => false,
'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/transcribe"
payload := strings.NewReader("{\n \"video_url\": \"https://www.instagram.com/reel/C86ZvEaqRmo/\",\n \"transcript_text\": false,\n \"all_videos\": false,\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/transcribe")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"video_url\": \"https://www.instagram.com/reel/C86ZvEaqRmo/\",\n \"transcript_text\": false,\n \"all_videos\": false,\n \"include_usage\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vidnavigator.com/v1/transcribe")
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://www.instagram.com/reel/C86ZvEaqRmo/\",\n \"transcript_text\": false,\n \"all_videos\": false,\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
}
},
"transcript": [
{
"text": "<string>",
"start": 123,
"end": 123
}
]
},
"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": "internal_server_error",
"message": "<string>"
}Transcribe Online Video
Transcribe online videos (e.g., Instagram, TikTok) using speech-to-text models when a transcript is not available.
Instagram Carousel Posts:
- For posts with multiple videos, the URL can include
?img_index=Nto select a specific video - Example:
https://www.instagram.com/p/ABC123/?img_index=2transcribes the second video - Without
img_index, the first video is transcribed - Set
all_videos=trueto transcribe ALL videos in a carousel post
Options:
transcript_text=true: Returns transcript as a single text string instead of segmentsall_videos=true: For carousel posts, returns all videos with their transcripts
Billing: on cache miss, one standard_request or residential_request is charged for the metadata fetch (residential for Instagram, Facebook-watch, Rumble; standard otherwise), plus transcription_hour proportional to the audio duration. On cache hit (same URL transcribed before for any user), only transcription_hour is charged — the metadata fetch is skipped. Users with the free_on_cache_hit sponsorship flag get the cache-hit transcription_hour waived (waived: true in the per-charge entry). Set include_usage=true to see the breakdown.
curl --request POST \
--url https://api.vidnavigator.com/v1/transcribe \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"video_url": "https://www.instagram.com/reel/C86ZvEaqRmo/",
"transcript_text": false,
"all_videos": false,
"include_usage": false
}
'import requests
url = "https://api.vidnavigator.com/v1/transcribe"
payload = {
"video_url": "https://www.instagram.com/reel/C86ZvEaqRmo/",
"transcript_text": False,
"all_videos": False,
"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://www.instagram.com/reel/C86ZvEaqRmo/',
transcript_text: false,
all_videos: false,
include_usage: false
})
};
fetch('https://api.vidnavigator.com/v1/transcribe', 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/transcribe",
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://www.instagram.com/reel/C86ZvEaqRmo/',
'transcript_text' => false,
'all_videos' => false,
'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/transcribe"
payload := strings.NewReader("{\n \"video_url\": \"https://www.instagram.com/reel/C86ZvEaqRmo/\",\n \"transcript_text\": false,\n \"all_videos\": false,\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/transcribe")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"video_url\": \"https://www.instagram.com/reel/C86ZvEaqRmo/\",\n \"transcript_text\": false,\n \"all_videos\": false,\n \"include_usage\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vidnavigator.com/v1/transcribe")
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://www.instagram.com/reel/C86ZvEaqRmo/\",\n \"transcript_text\": false,\n \"all_videos\": false,\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
}
},
"transcript": [
{
"text": "<string>",
"start": 123,
"end": 123
}
]
},
"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": "internal_server_error",
"message": "<string>"
}Overview
This endpoint is designed for videos where a pre-existing transcript or caption file cannot be retrieved. It downloads the video content and processes it through an AI speech-to-text model to generate a new transcript. This is particularly useful for social media platforms where direct transcript extraction is not possible, such as Instagram Reels that don’t have captions.Billing
Speech-to-text processing consumestranscription_hour usage. 1 credit covers 3 hours of video/audio transcription.
On a cache miss, one standard_request or residential_request is also charged for the metadata fetch (residential for Instagram, Facebook-watch, Rumble; standard otherwise), plus transcription_hour proportional to the audio duration. On a cache hit (same URL transcribed before, by any user), only transcription_hour is charged — the metadata fetch is skipped. Users with the free_on_cache_hit sponsorship flag get the cache-hit transcription_hour waived (waived: true in the per-charge entry).
Set include_usage: true to receive a usage block with the breakdown.
Supported Platforms
VidNavigator can generate transcripts from these platforms using speech-to-text:- X / Twitter (just copy the tweet video link)
- Facebook (public videos only)
- TikTok
- Dailymotion
- Loom
- Vimeo
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
video_url | string | Yes | URL of the video to transcribe. For Instagram carousel posts, append ?img_index=N to select a specific video. |
transcript_text | boolean | No | When true, returns the transcript as a single plain-text string instead of an array of segments. |
all_videos | boolean | No | For Instagram carousel posts only. When true, transcribes ALL videos in the post and returns them in an array. Ignored for non-carousel URLs (reels, TikTok, etc.). |
Instagram Carousel Behavior
Instagram carousel posts (e.g.https://www.instagram.com/p/.../) may contain multiple videos and/or images.
- Select a specific item: Append
?img_index=Nto the URL to select a specific item (1-based).
Example:https://www.instagram.com/p/ABC123/?img_index=2selects the second item. - Transcribe all videos: Set
all_videos=trueto transcribe all videos in the carousel. The response format changes (see “Success Response”).
400 with error=no_videos_found.Example Usage
curl -X POST "https://api.vidnavigator.com/v1/transcribe" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://www.instagram.com/reel/C86ZvEaqRmo/"
}'
from vidnavigator import VidNavigatorClient, VidNavigatorError
client = VidNavigatorClient()
try:
result = client.transcribe_video(
video_url="https://www.instagram.com/reel/C86ZvEaqRmo/"
)
print("Video Title:", result.data.video_info.title)
for segment in result.data.transcript:
print(f"[{segment.start:.2f}s - {segment.end:.2f}s] {segment.text}")
except VidNavigatorError as e:
print(f"An error occurred: {e.message}")
const { VidNavigatorClient, VidNavigatorError } = require('vidnavigator');
const client = new VidNavigatorClient({
apiKey: process.env.VIDNAVIGATOR_API_KEY,
});
async function transcribeVideo() {
try {
const { video_info, transcript } = await client.transcribeVideo({
video_url: "https://www.instagram.com/reel/C86ZvEaqRmo/"
});
console.log("Video Title:", video_info.title);
transcript.forEach(segment => {
console.log(`[${segment.start.toFixed(2)}s - ${segment.end.toFixed(2)}s] ${segment.text}`);
});
} catch (error) {
if (error instanceof VidNavigatorError) {
console.error(`An error occurred: ${error.message}`);
} else {
console.error("An unexpected error occurred:", error);
}
}
}
transcribeVideo();
Instagram Carousel (select a specific video with ?img_index=2)
curl -X POST "https://api.vidnavigator.com/v1/transcribe" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://www.instagram.com/p/ABC123/?img_index=2"
}'
Instagram Carousel (transcribe all videos with all_videos=true)
curl -X POST "https://api.vidnavigator.com/v1/transcribe" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://www.instagram.com/p/ABC123/",
"all_videos": true
}'
Success Response (200 OK)
This endpoint has two success response shapes (aoneOf), depending on whether you set all_videos=true:
- Single-video response (default): returns
data.video_info+data.transcript - All-videos response (
all_videos=true): returnsdata.carousel_info+data.videos[]
transcript_text=true affects the shape of each returned transcript (string vs segments) in both response types.Single-video response (default)
{
"status": "success",
"data": {
"video_info": {
"title": "A Reel Interesting Video",
"description": "An example description for the video.",
"thumbnail": "https://example.com/thumbnail.jpg",
"url": "https://www.instagram.com/reel/C86ZvEaqRmo/",
"channel": "Example Creator",
"duration": 58.5,
"views": 123456,
"likes": 7890,
"published_date": "2024-07-01",
"keywords": ["example", "social media", "video"],
"category": "Entertainment"
},
"transcript": [
{
"text": "This is the first sentence of the video.",
"start": 0.5,
"end": 3.2
},
{
"text": "And this is the second.",
"start": 3.5,
"end": 5.1
}
]
}
}
All-videos response (all_videos=true)
{
"status": "success",
"data": {
"carousel_info": {
"total_items": 5,
"video_count": 2,
"image_count": 3,
"transcribed_count": 2,
"total_duration": 123.4
},
"videos": [
{
"index": 1,
"status": "success",
"video_info": {
"title": "Video 1",
"description": "Example description",
"thumbnail": "https://example.com/thumb1.jpg",
"url": "https://www.instagram.com/p/ABC123/?img_index=1",
"channel": "Example Creator",
"duration": 60.0,
"views": 123,
"likes": 45,
"published_date": "2024-07-01",
"keywords": ["example"],
"category": "Entertainment"
},
"transcript": [
{ "text": "First line", "start": 0.0, "end": 2.0 }
]
},
{
"index": 2,
"status": "error",
"error": "transcript_not_available",
"message": "Transcript could not be generated for this video."
}
]
}
}
Error Responses
400 can include (per OpenAPI): missing_parameter, invalid_parameter, no_videos_found, unsupported_platform.Authorizations
API key authentication. Include your VidNavigator API key in the X-API-Key header.
Body
URL of the video to transcribe. For Instagram carousel posts, append ?img_index=N to select a specific video.
"https://www.instagram.com/reel/C86ZvEaqRmo/"
When true, returns the transcript as a single plain-text string instead of an array of segments.
For carousel posts only. When true, transcribes ALL videos in the post and returns them in an array. Ignored for non-carousel URLs (reels, TikTok, etc.).
When true, the response includes a usage block listing every meter charged during this request, the total credits deducted, and the user's remaining balance.
Response
Video transcribed successfully. Response format depends on all_videos parameter.
- Option 1
- Option 2
Single video response (default)
success Show child attributes
Show child attributes
Per-call usage disclosure. Returned only when the caller passes include_usage=true in the request body. Lists every meter that fired during this request and the credits actually deducted. Multiple charges of the same meter inside one request are consolidated into a single entry (their quantities and credits are summed). When a charge was waived through a cache-hit sponsorship (e.g. NGO), it carries waived: true + credits_saved, and a top-level waived.credits_saved summary appears.
For endpoints that involve LLM analysis (/extract/video, /extract/file, /analyze/video, /analyze/file, /youtube/search), the consolidated analysis_request charge entry carries a nested tokens object reporting the LLM input/output token tally for the request.
Show child attributes
Show child attributes

