Code Examples

Working examples to help you integrate The SubKit API quickly. All examples are copy-pasteable—just replace YOUR_API_KEY with your actual key.

Quick Start

The simplest way to extract subtitles from a YouTube video. Returns timed segments by default.

# Extract subtitles with timestamps (default)
curl -X POST https://api.ytsubs.dev/api/v1/extract \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  }'

Timed Mode (with Timestamps)

Get subtitles with timing information for each segment. Useful for video players, search indexing, or synchronized displays.

# Extract with timestamps (explicit)
curl -X POST https://api.ytsubs.dev/api/v1/extract \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "include_timestamps": true
  }' | jq '.subtitles[:3]'

# Response includes timed segments:
# [
#   { "text": "We're no strangers to love", "start": 18.0, "duration": 3.5 },
#   { "text": "You know the rules", "start": 21.5, "duration": 2.1 },
#   ...
# ]

Plain Text Mode

Get the full transcript as a single text string. Ideal for AI processing, summarization, or text analysis.

# Extract as plain text (no timestamps)
curl -X POST https://api.ytsubs.dev/api/v1/extract \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "include_timestamps": false
  }' | jq '.text[:200]'

# Response includes plain text:
# "We're no strangers to love You know the rules and so do I..."

Language Selection

Request subtitles in a specific language using ISO 639-1 codes. If the requested language isn't available, the API returns available alternatives.

# Extract Spanish subtitles
curl -X POST https://api.ytsubs.dev/api/v1/extract \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "language": "es"
  }'

# Common language codes:
# en - English, es - Spanish, fr - French, de - German
# pt - Portuguese, it - Italian, ja - Japanese, ko - Korean
# zh - Chinese, ar - Arabic, hi - Hindi, ru - Russian

Force Refresh (Bypass Cache)

Use force_refresh: true to bypass the cache and fetch fresh subtitles from YouTube. Useful when subtitles have been updated.

# Force fresh extraction (bypass cache)
curl -X POST https://api.ytsubs.dev/api/v1/extract \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "force_refresh": true
  }' | jq '{cached: .cached, extracted_at: .extracted_at}'

# Response shows fresh extraction:
# { "cached": false, "extracted_at": "2024-12-25T..." }

Rate Limit Note

Force refresh requests are limited to 10 per hour per API key to prevent abuse.

Error Handling

Production-ready error handling with automatic retry for rate limits. See the error reference for all error codes.

# Handle errors with proper status codes
# 401 - Invalid API key
# 404 - Video not found or no subtitles
# 429 - Rate limit exceeded

curl -X POST https://api.ytsubs.dev/api/v1/extract \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"url": "https://www.youtube.com/watch?v=invalid"}' \
  -w "\nStatus: %{http_code}\n"

# Error response format:
# {
#   "success": false,
#   "error": {
#     "code": "VIDEO_NOT_FOUND",
#     "message": "The video could not be found",
#     "docs_url": "/docs/errors#video-not-found"
#   },
#   "request_id": "req_abc123"
# }

AI Summary

Generate AI-powered summaries of video content. Requires Pro tier. See credits for pricing.

# Generate AI summary of video (Pro tier required)
curl -X POST https://api.ytsubs.dev/api/v1/summarize \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "style": "key_points"
  }'

# Cost: 2-6 credits depending on video duration
# Styles: "brief", "detailed", "key_points"

Comments Download

Download video comments with sorting options. Requires Pro tier. Cost: 1 credit per 500 comments.

# Download comments (Pro tier required)
curl "https://api.ytsubs.dev/api/v1/comments?url=https://www.youtube.com/watch?v=dQw4w9WgXcQ&max=100&sort=time" \
  -H "X-API-Key: YOUR_API_KEY"

# Parameters:
# max: 1-2000 (default 500)
# sort: "relevance" or "time" (newest first)
# Cost: 1 credit per 500 comments

Batch Extraction

Extract subtitles from multiple videos in a single request (up to 10). Failed extractions are free—only successful extractions are charged.

# Extract from multiple videos at once (up to 10)
curl -X POST https://api.ytsubs.dev/api/v1/batch \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "urls": [
      "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
      "https://www.youtube.com/watch?v=9bZkp7q19f0"
    ],
    "language": "en",
    "format": "json"
  }'

# Cost: 1 credit per successful extraction
# Failed extractions are free

Pre-flight Validation

Check if subtitles are available before extraction. This endpoint is free—no API key or credits needed.

# Check if subtitles are available (FREE - no auth required)
curl "https://api.ytsubs.dev/api/v1/validate?url=https://www.youtube.com/watch?v=dQw4w9WgXcQ"

# No API key needed! Great for validating URLs before extraction

TypeScript Type Definitions

Copy these type definitions into your TypeScript project for full type safety.

types.tstypescript
// TypeScript type definitions for The SubKit API

interface SubtitleSegment {
  text: string;
  start: number;
  duration: number;
}

interface RateLimit {
  remaining: number;
  limit: number;
  reset_at: string;
}

interface ExtractResponseTimed {
  video_id: string;
  title: string;
  language: string;
  subtitle_type: 'manual' | 'auto';
  subtitles: SubtitleSegment[];
  cached: boolean;
  extracted_at: string;
  rate_limit: RateLimit | null;
  request_id: string;
}

interface ExtractResponsePlainText {
  video_id: string;
  title: string;
  language: string;
  subtitle_type: 'manual' | 'auto';
  text: string;
  segment_count: number;
  cached: boolean;
  extracted_at: string;
  rate_limit: RateLimit | null;
  request_id: string;
}

interface ExtractRequest {
  url: string;
  language?: string;
  include_timestamps?: boolean;
  force_refresh?: boolean;
}

interface APIErrorResponse {
  success: false;
  error: {
    code: string;
    message: string;
    docs_url: string;
    details?: Record<string, unknown>;
  };
  request_id: string;
}

Next Steps