{
  "data": {
    "id": "BIEUgPg9mnee8138o",
    "actId": "Z3oBut4UdVlAAsORu",
    "userId": "9Um4NEFR7z42j35AD",
    "startedAt": "2026-08-16T18:01:52.899Z",
    "finishedAt": "2026-08-16T18:02:06.328Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CLI"
    },
    "stats": {
      "durationMillis": 13274,
      "runTimeSecs": 13.274,
      "computeUnits": 0.01474888888888889,
      "imageSizeBytes": 547307520
    },
    "options": {
      "useCache": false,
      "betaPackages": false,
      "tag": "latest",
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"YouTube Transcript Scraper input\",\n  \"description\": \"Paste up to 1,000 public YouTube video URLs or video IDs. The Actor returns one fresh dataset row per successful unique video and reports failures in OUTPUT. Playlists, channels, and search inputs are not supported.\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"additionalProperties\": false,\n  \"properties\": {\n    \"startUrls\": {\n      \"title\": \"YouTube video URLs or IDs\",\n      \"type\": \"array\",\n      \"description\": \"Paste direct video, Shorts, live, embed, or youtu.be URLs, or 11-character video IDs. Duplicate video IDs are processed once. Invalid non-empty inputs are reported in OUTPUT without creating billable dataset rows.\",\n      \"editor\": \"stringList\",\n      \"sectionCaption\": \"Videos\",\n      \"sectionDescription\": \"Add the public YouTube videos whose captions you want. Each successful unique video becomes one dataset row.\",\n      \"placeholderValue\": \"https://www.youtube.com/watch?v=... or an 11-character video ID\",\n      \"prefill\": [\n        \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\"\n      ],\n      \"minItems\": 1,\n      \"maxItems\": 1000,\n      \"items\": {\n        \"type\": \"string\",\n        \"pattern\": \"^\\\\s*\\\\S[\\\\s\\\\S]*$\"\n      },\n      \"errorMessage\": {\n        \"minItems\": \"Add at least one YouTube video URL or video ID.\",\n        \"maxItems\": \"Add no more than 1,000 YouTube video URLs or video IDs.\"\n      }\n    },\n    \"preferredLanguages\": {\n      \"title\": \"Transcript languages (optional)\",\n      \"type\": \"array\",\n      \"description\": \"Leave empty to use the best available caption track. When set, languages are tried in order. If none match, the Actor reports a typed non-billable language-unavailable failure instead of another language.\",\n      \"editor\": \"select\",\n      \"sectionCaption\": \"Transcript output\",\n      \"sectionDescription\": \"Choose the caption language policy and transcript formats. The defaults work well for most AI and data jobs.\",\n      \"default\": [],\n      \"uniqueItems\": true,\n      \"items\": {\n        \"type\": \"string\",\n        \"enumSuggestedValues\": [\n          \"en\",\n          \"es\",\n          \"fr\",\n          \"de\",\n          \"pt\",\n          \"it\",\n          \"ja\",\n          \"ko\",\n          \"zh-Hans\",\n          \"zh-Hant\",\n          \"ar\",\n          \"hi\"\n        ],\n        \"enumTitles\": [\n          \"English\",\n          \"Spanish\",\n          \"French\",\n          \"German\",\n          \"Portuguese\",\n          \"Italian\",\n          \"Japanese\",\n          \"Korean\",\n          \"Chinese (Simplified)\",\n          \"Chinese (Traditional)\",\n          \"Arabic\",\n          \"Hindi\"\n        ]\n      }\n    },\n    \"outputFormats\": {\n      \"title\": \"Transcript formats\",\n      \"type\": \"array\",\n      \"description\": \"Choose one or more transcript renderings. JSON gives timestamped segments. Text gives clean plain text. SRT and VTT are subtitle formats. LLM gives prompt-ready text.\",\n      \"editor\": \"select\",\n      \"default\": [\n        \"json\",\n        \"text\"\n      ],\n      \"minItems\": 1,\n      \"uniqueItems\": true,\n      \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n          \"json\",\n          \"text\",\n          \"srt\",\n          \"vtt\",\n          \"llm\"\n        ],\n        \"enumTitles\": [\n          \"Timestamped JSON\",\n          \"Plain text\",\n          \"SRT subtitles\",\n          \"WebVTT subtitles\",\n          \"LLM-ready text\"\n        ]\n      },\n      \"errorMessage\": {\n        \"minItems\": \"Choose at least one transcript format.\"\n      }\n    },\n    \"includeFailedInputDetails\": {\n      \"title\": \"Include failed input details\",\n      \"type\": \"boolean\",\n      \"description\": \"Add safe per-input failure details to the run OUTPUT record. Failed inputs never become billable dataset rows.\",\n      \"editor\": \"checkbox\",\n      \"default\": true\n    }\n  },\n  \"required\": [\n    \"startUrls\"\n  ]\n}",
    "readme": "# YouTube Transcript Scraper\n\n## 🚀 What does YouTube Transcript Scraper do?\n\nPaste YouTube video URLs. Get clean transcript text and timestamped segments\nthat are ready for AI, research, spreadsheets, and automated workflows.\n\nThe Actor extracts existing public captions from videos and Shorts. It also\nreturns video context, selected language details, and clear result states. No\nYouTube API key, account, or cookies are required from you.\n\n## 🎯 What can you use it for?\n\n- 🤖 Send clean transcript text into ChatGPT, Claude, AI agents, RAG pipelines,\n  embeddings, and LLM prompts.\n- ✂️ Pull out key points, summaries, quotes, clips, and content ideas without\n  watching every video first.\n- 🔎 SEO, competitive content analysis, media monitoring, and creator research.\n- 🎓 Academic, market, podcast, lecture, interview, and training-data workflows.\n- ♿ Accessibility review and subtitle/caption export.\n- 📊 Load stable rows into warehouses, Google Sheets, no-code automations, and\n  repeatable batch jobs.\n\nThe Actor is built for direct video objects. Each successful YouTube video or\nShort becomes one billable transcript row. Failed inputs stay non-billable and\nare counted in the run `OUTPUT` record.\n\n## ✨ Why use this Actor?\n\n- ✅ **Clean output without formatting fluff**: timestamped `segments` plus one\n  joined `text` field.\n- 🔗 **Easy to integrate**: use stable dataset rows with the Apify API, webhooks,\n  schedules, Make, Zapier, n8n, or your own code.\n- 📺 **Video and channel context**: title, publish date, duration, channel,\n  and thumbnail when YouTube exposes them.\n- 📈 **Transcript quality signals**: word count, character count, segment count,\n  timing coverage, and coverage ratio.\n- 🌍 **Language clarity**: requested languages, selected language, available\n  language codes, auto-generated/manual flag, and match reason.\n- 🩳 **Shorts and long videos**: works with normal videos, Shorts, and long\n  public videos when captions are available.\n- 🔑 **No API key required from you**: use direct video URLs, Shorts URLs,\n  `youtu.be`, embed URLs, or raw video IDs.\n- 💸 **Non-billable failures**: invalid, unsupported, unavailable, age-restricted,\n  login-required, and no-transcript outcomes are reported in `OUTPUT`, not\n  written as charged dataset rows.\n- 🧾 **Clear billing unit**: one successful transcript equals one dataset row and\n  one billable event. A failed lookup costs no result event.\n- 🆕 **Fresh on every run**: each public run fetches the current public caption\n  track instead of reusing an older transcript result.\n\n## ⚙️ Can I use this Actor through an API?\n\nYes. You can run YouTube Transcript Scraper manually in Apify Console or use it\nthrough:\n\n- Apify API\n- Python SDK\n- Node.js SDK\n- Webhooks\n- Scheduled runs\n- Apify integrations\n\nThis makes it useful for AI pipelines, research tools, spreadsheets, data\nwarehouses, and no-code automations.\n\n## 🚀 How do I use YouTube Transcript Scraper?\n\nPaste one or more direct YouTube video URLs, Shorts URLs, `youtu.be` links,\nembed URLs, or raw video IDs into `startUrls`.\n\n```json\n{\n    \"startUrls\": [\"https://www.youtube.com/watch?v=dQw4w9WgXcQ\"]\n}\n```\n\nThat is enough for most jobs:\n\n1. Open **YouTube Transcript Scraper** in Apify Console.\n2. Paste one or more YouTube video URLs or IDs.\n3. Leave the default language and output settings for your first run.\n4. Click **Start**.\n5. Open **Output** to inspect the transcript rows and run summary.\n6. Download the dataset or send it to another tool through an integration.\n\n## 🧩 Input\n\n| Option                      | What it controls                                                                                               |\n| --------------------------- | -------------------------------------------------------------------------------------------------------------- |\n| `startUrls`                 | One to 1,000 direct video, Shorts, live, embed, `youtu.be`, or raw video ID inputs. Duplicate videos run once. |\n| `preferredLanguages`        | Optional language codes in priority order. Empty means best available. A filled list is strict.                |\n| `outputFormats`             | One or more of `json`, `text`, `srt`, `vtt`, and `llm`. Defaults to `json` and `text`.                         |\n| `includeFailedInputDetails` | Include safe per-input failure details in `OUTPUT`. Defaults to `true`. Failures are never dataset rows.       |\n\nWhen `preferredLanguages` is set and no requested language exists, the Actor\nrecords a typed non-billable `LANGUAGE_UNAVAILABLE` failure in `OUTPUT`. It\ndoes not silently return another language.\n\n## 📦 Output\n\nEach default-dataset row represents one successful unique YouTube video or\nShort. The fields are ordered for clean loading into spreadsheets, APIs, and\nwarehouses.\n\n| Group      | Fields                                                                                                                                            |\n| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Input      | `platform`, `inputIndex`, `inputUrl`                                                                                                              |\n| Video      | `videoUrl`, `videoId`, `title`, `publishedAt`, `videoDurationSeconds`, `thumbnailUrl`                                                             |\n| Channel    | `channelId`, `channelName`, `channelUrl`                                                                                                          |\n| Language   | `requestedLanguageCodes`, `transcriptLanguageCode`, `transcriptLanguageName`, `availableLanguageCodes`, `languageMatch`, `isAutoGenerated`        |\n| Transcript | `segments`, `text`, optional `srt`, optional `vtt`, optional `llmText`                                                                            |\n| Quality    | `segmentCount`, `wordCount`, `characterCount`, `firstSegmentStartSeconds`, `lastSegmentEndSeconds`, `transcriptSpanSeconds`, `videoCoverageRatio` |\n| Result     | `status`, `statusReason`, `errorCategory`, `errorCode`, `isRetryable`, `scrapedAt`                                                                |\n\n### ✅ Successful row sample\n\n```json\n{\n    \"platform\": \"youtube\",\n    \"inputIndex\": 0,\n    \"inputUrl\": \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\",\n    \"videoUrl\": \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\",\n    \"videoId\": \"dQw4w9WgXcQ\",\n    \"title\": \"Example video title\",\n    \"publishedAt\": \"2024-04-30\",\n    \"videoDurationSeconds\": 212,\n    \"thumbnailUrl\": \"https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg\",\n    \"channelId\": \"UCexample123\",\n    \"channelName\": \"Example Channel\",\n    \"channelUrl\": \"https://www.youtube.com/@example\",\n    \"requestedLanguageCodes\": [\"en\"],\n    \"transcriptLanguageCode\": \"en\",\n    \"transcriptLanguageName\": \"English\",\n    \"availableLanguageCodes\": [\"en\", \"es\"],\n    \"languageMatch\": \"exact\",\n    \"isAutoGenerated\": false,\n    \"segments\": [\n        {\n            \"startSeconds\": 0,\n            \"endSeconds\": 2.4,\n            \"durationSeconds\": 2.4,\n            \"text\": \"Example transcript text\"\n        }\n    ],\n    \"text\": \"Example transcript text\",\n    \"srt\": null,\n    \"vtt\": null,\n    \"llmText\": null,\n    \"segmentCount\": 61,\n    \"wordCount\": 534,\n    \"characterCount\": 3180,\n    \"firstSegmentStartSeconds\": 0,\n    \"lastSegmentEndSeconds\": 210.4,\n    \"transcriptSpanSeconds\": 210.4,\n    \"videoCoverageRatio\": 0.9925,\n    \"status\": \"succeeded\",\n    \"statusReason\": \"Transcript parsed from public YouTube caption tracks.\",\n    \"errorCategory\": null,\n    \"errorCode\": null,\n    \"isRetryable\": false,\n    \"scrapedAt\": \"2026-07-08T21:43:38.000Z\"\n}\n```\n\n### ⚠️ Failed input detail\n\nWhen enabled, `OUTPUT.failedInputDetails` preserves safe input and canonical\nidentity details without creating a billable dataset row.\n\n```json\n{\n    \"inputIndex\": 1,\n    \"inputUrl\": \"https://www.youtube.com/watch?v=example1234\",\n    \"videoUrl\": \"https://www.youtube.com/watch?v=example1234\",\n    \"videoId\": \"example1234\",\n    \"status\": \"failed\",\n    \"statusReason\": \"No public transcript was available.\",\n    \"errorCategory\": \"no_transcript\",\n    \"errorCode\": \"TRANSCRIPT_NOT_FOUND\",\n    \"isRetryable\": false\n}\n```\n\nCommon failure codes:\n\n- `TRANSCRIPT_NOT_FOUND`: public video resolved, but no public caption track was available.\n- `VIDEO_UNAVAILABLE`: the video was unavailable.\n- `AGE_RESTRICTED`: YouTube required age-confirmed access.\n- `LOGIN_REQUIRED`: YouTube required login for the lookup.\n- `LANGUAGE_UNAVAILABLE`: none of the requested transcript languages were available.\n- `INVALID_INPUT` and `UNSUPPORTED_INPUT`: the input was not a supported direct video object.\n- `ACCESS_BLOCKED`, `TEMPORARY_FAILURE`, and `TRANSCRIPT_PARSE_FAILED`: the public lookup could not produce a transcript and may succeed later when `isRetryable` is true.\n\n## 🧾 Run summary\n\nThe `OUTPUT` record shows:\n\n- inputs received;\n- unique videos processed;\n- successful transcript rows;\n- duplicate videos skipped;\n- unavailable or unsupported inputs;\n- error-code counts;\n- optional safe details for inputs that did not produce a transcript.\n\nUse this summary to check the whole run before loading the dataset.\n\n## 💵 Pricing Event\n\nThe Actor is designed for Pay Per Event pricing. One billable event is one\nsuccessful transcript row written to the dataset. Failed, invalid, unsupported,\nage-restricted, unavailable, language-unavailable, and no-transcript rows are\nnon-billable. Public runs always fetch a fresh caption result.\n\n## 🚫 What this Actor is not\n\n- It does not generate AI speech-to-text when YouTube has no public captions.\n- It does not download video or audio files.\n- It does not use your YouTube account, cookies, OAuth, or private session.\n- It does not access private, deleted, members-only, or account-only videos.\n- It does not expand playlists, channels, search keywords, recommendations, or\n  comments. Use a discovery Actor first, then pass direct video URLs here.\n- It does not guarantee every public video has captions. When captions are\n  unavailable, the row explains the outcome and stays non-billable.\n\n## 🏆 Best practices\n\n- 🎯 Pass direct video or Shorts URLs whenever possible.\n- 🧠 Keep `outputFormats` to `[\"json\", \"text\"]` for most AI and data workflows.\n- 📝 Add `srt` or `vtt` only when you need subtitle files.\n- 🌐 Leave `preferredLanguages` empty for the best available track. Add language\n  codes in priority order when the result must use one of those languages.\n- 🔗 For channel, playlist, or keyword workflows, run discovery first and send the\n  resulting direct video URLs into this Actor.\n\n## 🔗 Related social media scrapers\n\nContinue the same workflow on this platform or compare public data across\nplatforms.\n\n### Continue on YouTube\n\n- [YouTube Channel Scraper](https://apify.com/chronometrica/youtube-channel-scraper)\n  — collect public channel details, links, and audience stats.\n- [YouTube Search Scraper](https://apify.com/chronometrica/youtube-search-scraper)\n  — find public videos, Shorts, channels, and metrics by keyword.\n- [YouTube Metrics Scraper](https://apify.com/chronometrica/youtube-metrics-scraper)\n  — collect public video, Short, channel, and engagement metrics.\n- [YouTube Comments Scraper](https://apify.com/chronometrica/youtube-comments-scraper)\n  — collect public comments, replies, authors, likes, pins, and creator\n  hearts.\n\n### Compare transcripts across platforms\n\n- [TikTok Transcript Scraper](https://apify.com/chronometrica/tiktok-transcript-scraper)\n  — extract public caption text and timestamped segments.\n",
    "changelog": "# Changelog\n\n## 0.1.1 — 2026-07-15\n\n- Add links to the other published social media scrapers.\n\n## 0.1.0\n\n- Launched transcript extraction for public YouTube videos and Shorts.\n- Added batch input for up to 1,000 video URLs or IDs with automatic duplicate\n  removal.\n- Added timestamped JSON, plain text, SRT, WebVTT, and LLM-ready transcript\n  formats.\n- Added ordered language preferences with selected and available language\n  details.\n- Added video and channel context, transcript counts, timing coverage, and clear\n  result reasons.\n- Added run summaries with optional details for inputs that do not produce a\n  transcript.\n- Set billing to one event per successful transcript. Inputs without a usable\n  public transcript do not create dataset rows or result charges.\n",
    "actorDefinition": {
      "$schema": "https://apify.com/schemas/v1/actor.ide.json",
      "actorSpecification": 1,
      "name": "youtube-transcript-scraper",
      "title": "YouTube Transcript Scraper – Clean Text & JSON",
      "description": "Extract clean, timestamped transcripts from public YouTube videos and Shorts. Batch up to 1,000 URLs, choose caption languages, and export text or structured segments for AI, research, SEO, and automation. Pay only for successful transcripts.",
      "seoTitle": "YouTube Transcript Scraper – JSON & Timestamps",
      "seoDescription": "Extract YouTube transcripts from videos and Shorts in clean text, timestamped JSON, SRT, VTT, or LLM-ready formats. Pay only for successful results.",
      "categories": [
        "SOCIAL_MEDIA",
        "VIDEOS",
        "AI"
      ],
      "version": "0.1",
      "buildTag": "latest",
      "defaultRunOptions": {
        "build": "latest",
        "timeoutSecs": 3600,
        "memoryMbytes": 512
      },
      "exampleRunInput": {
        "contentType": "application/json; charset=utf-8",
        "body": "{\n    \"startUrls\": [\"https://www.youtube.com/watch?v=dQw4w9WgXcQ\"]\n}"
      },
      "input": {
        "title": "YouTube Transcript Scraper input",
        "description": "Paste up to 1,000 public YouTube video URLs or video IDs. The Actor returns one fresh dataset row per successful unique video and reports failures in OUTPUT. Playlists, channels, and search inputs are not supported.",
        "type": "object",
        "schemaVersion": 1,
        "additionalProperties": false,
        "properties": {
          "startUrls": {
            "title": "YouTube video URLs or IDs",
            "type": "array",
            "description": "Paste direct video, Shorts, live, embed, or youtu.be URLs, or 11-character video IDs. Duplicate video IDs are processed once. Invalid non-empty inputs are reported in OUTPUT without creating billable dataset rows.",
            "editor": "stringList",
            "sectionCaption": "Videos",
            "sectionDescription": "Add the public YouTube videos whose captions you want. Each successful unique video becomes one dataset row.",
            "placeholderValue": "https://www.youtube.com/watch?v=... or an 11-character video ID",
            "prefill": [
              "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
            ],
            "minItems": 1,
            "maxItems": 1000,
            "items": {
              "type": "string",
              "pattern": "^\\s*\\S[\\s\\S]*$"
            },
            "errorMessage": {
              "minItems": "Add at least one YouTube video URL or video ID.",
              "maxItems": "Add no more than 1,000 YouTube video URLs or video IDs."
            }
          },
          "preferredLanguages": {
            "title": "Transcript languages (optional)",
            "type": "array",
            "description": "Leave empty to use the best available caption track. When set, languages are tried in order. If none match, the Actor reports a typed non-billable language-unavailable failure instead of another language.",
            "editor": "select",
            "sectionCaption": "Transcript output",
            "sectionDescription": "Choose the caption language policy and transcript formats. The defaults work well for most AI and data jobs.",
            "default": [],
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enumSuggestedValues": [
                "en",
                "es",
                "fr",
                "de",
                "pt",
                "it",
                "ja",
                "ko",
                "zh-Hans",
                "zh-Hant",
                "ar",
                "hi"
              ],
              "enumTitles": [
                "English",
                "Spanish",
                "French",
                "German",
                "Portuguese",
                "Italian",
                "Japanese",
                "Korean",
                "Chinese (Simplified)",
                "Chinese (Traditional)",
                "Arabic",
                "Hindi"
              ]
            }
          },
          "outputFormats": {
            "title": "Transcript formats",
            "type": "array",
            "description": "Choose one or more transcript renderings. JSON gives timestamped segments. Text gives clean plain text. SRT and VTT are subtitle formats. LLM gives prompt-ready text.",
            "editor": "select",
            "default": [
              "json",
              "text"
            ],
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "json",
                "text",
                "srt",
                "vtt",
                "llm"
              ],
              "enumTitles": [
                "Timestamped JSON",
                "Plain text",
                "SRT subtitles",
                "WebVTT subtitles",
                "LLM-ready text"
              ]
            },
            "errorMessage": {
              "minItems": "Choose at least one transcript format."
            }
          },
          "includeFailedInputDetails": {
            "title": "Include failed input details",
            "type": "boolean",
            "description": "Add safe per-input failure details to the run OUTPUT record. Failed inputs never become billable dataset rows.",
            "editor": "checkbox",
            "default": true
          }
        },
        "required": [
          "startUrls"
        ]
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "YouTube Transcript Scraper output",
        "description": "Successful transcript rows are stored in the default dataset. OUTPUT contains buyer-facing result, failure, duplicate, and optional failed-input details.",
        "properties": {
          "results": {
            "type": "string",
            "title": "Transcript results",
            "template": "{{links.apiDefaultDatasetUrl}}/items"
          },
          "output": {
            "type": "string",
            "title": "Run summary",
            "template": "{{links.apiDefaultKeyValueStoreUrl}}/records/OUTPUT"
          }
        }
      },
      "storages": {
        "dataset": {
          "actorSpecification": 1,
          "fields": {
            "$schema": "http://json-schema.org/draft-07/schema#",
            "type": "object",
            "properties": {
              "platform": {
                "type": "string",
                "title": "Platform"
              },
              "inputIndex": {
                "type": "integer",
                "title": "Input #"
              },
              "inputUrl": {
                "type": "string",
                "title": "Input URL"
              },
              "videoUrl": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Video URL"
              },
              "videoId": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Video ID"
              },
              "title": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Title"
              },
              "publishedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date",
                "title": "Published At"
              },
              "videoDurationSeconds": {
                "type": [
                  "integer",
                  "null"
                ],
                "title": "Video Duration (Seconds)"
              },
              "thumbnailUrl": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Thumbnail"
              },
              "channelId": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Channel ID"
              },
              "channelName": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Channel Name"
              },
              "channelUrl": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Channel URL"
              },
              "requestedLanguageCodes": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": "string"
                },
                "title": "Language Preferences"
              },
              "transcriptLanguageCode": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Transcript Language"
              },
              "transcriptLanguageName": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Transcript Language Name"
              },
              "availableLanguageCodes": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": "string"
                },
                "title": "Available Languages"
              },
              "languageMatch": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "exact",
                  "prefix",
                  "fallback",
                  null
                ],
                "title": "Language Match"
              },
              "isAutoGenerated": {
                "type": [
                  "boolean",
                  "null"
                ],
                "title": "Auto-generated"
              },
              "segments": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": "object",
                  "properties": {
                    "startSeconds": {
                      "type": "number"
                    },
                    "endSeconds": {
                      "type": "number"
                    },
                    "durationSeconds": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "text": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "startSeconds",
                    "endSeconds",
                    "durationSeconds",
                    "text"
                  ]
                },
                "title": "Segments"
              },
              "text": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Text"
              },
              "srt": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "SRT"
              },
              "vtt": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "VTT"
              },
              "llmText": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "LLM Text"
              },
              "segmentCount": {
                "type": [
                  "integer",
                  "null"
                ],
                "title": "Segments"
              },
              "wordCount": {
                "type": [
                  "integer",
                  "null"
                ],
                "title": "Words"
              },
              "characterCount": {
                "type": [
                  "integer",
                  "null"
                ],
                "title": "Characters"
              },
              "firstSegmentStartSeconds": {
                "type": [
                  "number",
                  "null"
                ],
                "title": "First Segment Start (Seconds)"
              },
              "lastSegmentEndSeconds": {
                "type": [
                  "number",
                  "null"
                ],
                "title": "Last Segment End (Seconds)"
              },
              "transcriptSpanSeconds": {
                "type": [
                  "number",
                  "null"
                ],
                "title": "Transcript Span (Seconds)"
              },
              "videoCoverageRatio": {
                "type": [
                  "number",
                  "null"
                ],
                "title": "Video Coverage Ratio"
              },
              "status": {
                "type": "string",
                "title": "Status"
              },
              "statusReason": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Status Reason"
              },
              "errorCategory": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Error Category"
              },
              "errorCode": {
                "type": [
                  "string",
                  "null"
                ],
                "title": "Error Code"
              },
              "isRetryable": {
                "type": "boolean",
                "title": "Retryable"
              },
              "scrapedAt": {
                "type": "string",
                "format": "date-time",
                "title": "Scraped At"
              }
            },
            "required": [
              "platform",
              "inputIndex",
              "inputUrl",
              "status",
              "isRetryable",
              "scrapedAt"
            ]
          },
          "views": {
            "overview": {
              "title": "Transcript results",
              "description": "One row per attempted unique YouTube video or Short.",
              "transformation": {
                "fields": [
                  "platform",
                  "inputIndex",
                  "inputUrl",
                  "videoUrl",
                  "videoId",
                  "title",
                  "publishedAt",
                  "videoDurationSeconds",
                  "thumbnailUrl",
                  "channelId",
                  "channelName",
                  "channelUrl",
                  "requestedLanguageCodes",
                  "transcriptLanguageCode",
                  "transcriptLanguageName",
                  "availableLanguageCodes",
                  "languageMatch",
                  "isAutoGenerated",
                  "segments",
                  "text",
                  "srt",
                  "vtt",
                  "llmText",
                  "segmentCount",
                  "wordCount",
                  "characterCount",
                  "firstSegmentStartSeconds",
                  "lastSegmentEndSeconds",
                  "transcriptSpanSeconds",
                  "videoCoverageRatio",
                  "status",
                  "statusReason",
                  "errorCategory",
                  "errorCode",
                  "isRetryable",
                  "scrapedAt"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "platform": {
                    "label": "Platform",
                    "format": "text"
                  },
                  "inputIndex": {
                    "label": "Input #",
                    "format": "number"
                  },
                  "inputUrl": {
                    "label": "Input URL",
                    "format": "text"
                  },
                  "videoUrl": {
                    "label": "Video URL",
                    "format": "link"
                  },
                  "videoId": {
                    "label": "Video ID",
                    "format": "text"
                  },
                  "title": {
                    "label": "Title",
                    "format": "text"
                  },
                  "publishedAt": {
                    "label": "Published At",
                    "format": "date"
                  },
                  "videoDurationSeconds": {
                    "label": "Video Duration (Seconds)",
                    "format": "number"
                  },
                  "thumbnailUrl": {
                    "label": "Thumbnail",
                    "format": "link"
                  },
                  "channelId": {
                    "label": "Channel ID",
                    "format": "text"
                  },
                  "channelName": {
                    "label": "Channel Name",
                    "format": "text"
                  },
                  "channelUrl": {
                    "label": "Channel URL",
                    "format": "link"
                  },
                  "requestedLanguageCodes": {
                    "label": "Language Preferences",
                    "format": "object"
                  },
                  "transcriptLanguageCode": {
                    "label": "Transcript Language",
                    "format": "text"
                  },
                  "transcriptLanguageName": {
                    "label": "Transcript Language Name",
                    "format": "text"
                  },
                  "availableLanguageCodes": {
                    "label": "Available Languages",
                    "format": "object"
                  },
                  "languageMatch": {
                    "label": "Language Match",
                    "format": "text"
                  },
                  "isAutoGenerated": {
                    "label": "Auto-generated",
                    "format": "boolean"
                  },
                  "segments": {
                    "label": "Segments",
                    "format": "object"
                  },
                  "text": {
                    "label": "Text",
                    "format": "text"
                  },
                  "srt": {
                    "label": "SRT",
                    "format": "text"
                  },
                  "vtt": {
                    "label": "VTT",
                    "format": "text"
                  },
                  "llmText": {
                    "label": "LLM Text",
                    "format": "text"
                  },
                  "segmentCount": {
                    "label": "Segments",
                    "format": "number"
                  },
                  "wordCount": {
                    "label": "Words",
                    "format": "number"
                  },
                  "characterCount": {
                    "label": "Characters",
                    "format": "number"
                  },
                  "firstSegmentStartSeconds": {
                    "label": "First Segment Start (Seconds)",
                    "format": "number"
                  },
                  "lastSegmentEndSeconds": {
                    "label": "Last Segment End (Seconds)",
                    "format": "number"
                  },
                  "transcriptSpanSeconds": {
                    "label": "Transcript Span (Seconds)",
                    "format": "number"
                  },
                  "videoCoverageRatio": {
                    "label": "Video Coverage Ratio",
                    "format": "number"
                  },
                  "status": {
                    "label": "Status",
                    "format": "text"
                  },
                  "statusReason": {
                    "label": "Status Reason",
                    "format": "text"
                  },
                  "errorCategory": {
                    "label": "Error Category",
                    "format": "text"
                  },
                  "errorCode": {
                    "label": "Error Code",
                    "format": "text"
                  },
                  "isRetryable": {
                    "label": "Retryable",
                    "format": "boolean"
                  },
                  "scrapedAt": {
                    "label": "Scraped At",
                    "format": "date"
                  }
                }
              }
            }
          }
        }
      },
      "dockerfile": "../Dockerfile",
      "changelog": "# Changelog\n\n## 0.1.1 — 2026-07-15\n\n- Add links to the other published social media scrapers.\n\n## 0.1.0\n\n- Launched transcript extraction for public YouTube videos and Shorts.\n- Added batch input for up to 1,000 video URLs or IDs with automatic duplicate\n  removal.\n- Added timestamped JSON, plain text, SRT, WebVTT, and LLM-ready transcript\n  formats.\n- Added ordered language preferences with selected and available language\n  details.\n- Added video and channel context, transcript counts, timing coverage, and clear\n  result reasons.\n- Added run summaries with optional details for inputs that do not produce a\n  transcript.\n- Set billing to one event per successful transcript. Inputs without a usable\n  public transcript do not create dataset rows or result charges.\n",
      "readme": "# YouTube Transcript Scraper\n\n## 🚀 What does YouTube Transcript Scraper do?\n\nPaste YouTube video URLs. Get clean transcript text and timestamped segments\nthat are ready for AI, research, spreadsheets, and automated workflows.\n\nThe Actor extracts existing public captions from videos and Shorts. It also\nreturns video context, selected language details, and clear result states. No\nYouTube API key, account, or cookies are required from you.\n\n## 🎯 What can you use it for?\n\n- 🤖 Send clean transcript text into ChatGPT, Claude, AI agents, RAG pipelines,\n  embeddings, and LLM prompts.\n- ✂️ Pull out key points, summaries, quotes, clips, and content ideas without\n  watching every video first.\n- 🔎 SEO, competitive content analysis, media monitoring, and creator research.\n- 🎓 Academic, market, podcast, lecture, interview, and training-data workflows.\n- ♿ Accessibility review and subtitle/caption export.\n- 📊 Load stable rows into warehouses, Google Sheets, no-code automations, and\n  repeatable batch jobs.\n\nThe Actor is built for direct video objects. Each successful YouTube video or\nShort becomes one billable transcript row. Failed inputs stay non-billable and\nare counted in the run `OUTPUT` record.\n\n## ✨ Why use this Actor?\n\n- ✅ **Clean output without formatting fluff**: timestamped `segments` plus one\n  joined `text` field.\n- 🔗 **Easy to integrate**: use stable dataset rows with the Apify API, webhooks,\n  schedules, Make, Zapier, n8n, or your own code.\n- 📺 **Video and channel context**: title, publish date, duration, channel,\n  and thumbnail when YouTube exposes them.\n- 📈 **Transcript quality signals**: word count, character count, segment count,\n  timing coverage, and coverage ratio.\n- 🌍 **Language clarity**: requested languages, selected language, available\n  language codes, auto-generated/manual flag, and match reason.\n- 🩳 **Shorts and long videos**: works with normal videos, Shorts, and long\n  public videos when captions are available.\n- 🔑 **No API key required from you**: use direct video URLs, Shorts URLs,\n  `youtu.be`, embed URLs, or raw video IDs.\n- 💸 **Non-billable failures**: invalid, unsupported, unavailable, age-restricted,\n  login-required, and no-transcript outcomes are reported in `OUTPUT`, not\n  written as charged dataset rows.\n- 🧾 **Clear billing unit**: one successful transcript equals one dataset row and\n  one billable event. A failed lookup costs no result event.\n- 🆕 **Fresh on every run**: each public run fetches the current public caption\n  track instead of reusing an older transcript result.\n\n## ⚙️ Can I use this Actor through an API?\n\nYes. You can run YouTube Transcript Scraper manually in Apify Console or use it\nthrough:\n\n- Apify API\n- Python SDK\n- Node.js SDK\n- Webhooks\n- Scheduled runs\n- Apify integrations\n\nThis makes it useful for AI pipelines, research tools, spreadsheets, data\nwarehouses, and no-code automations.\n\n## 🚀 How do I use YouTube Transcript Scraper?\n\nPaste one or more direct YouTube video URLs, Shorts URLs, `youtu.be` links,\nembed URLs, or raw video IDs into `startUrls`.\n\n```json\n{\n    \"startUrls\": [\"https://www.youtube.com/watch?v=dQw4w9WgXcQ\"]\n}\n```\n\nThat is enough for most jobs:\n\n1. Open **YouTube Transcript Scraper** in Apify Console.\n2. Paste one or more YouTube video URLs or IDs.\n3. Leave the default language and output settings for your first run.\n4. Click **Start**.\n5. Open **Output** to inspect the transcript rows and run summary.\n6. Download the dataset or send it to another tool through an integration.\n\n## 🧩 Input\n\n| Option                      | What it controls                                                                                               |\n| --------------------------- | -------------------------------------------------------------------------------------------------------------- |\n| `startUrls`                 | One to 1,000 direct video, Shorts, live, embed, `youtu.be`, or raw video ID inputs. Duplicate videos run once. |\n| `preferredLanguages`        | Optional language codes in priority order. Empty means best available. A filled list is strict.                |\n| `outputFormats`             | One or more of `json`, `text`, `srt`, `vtt`, and `llm`. Defaults to `json` and `text`.                         |\n| `includeFailedInputDetails` | Include safe per-input failure details in `OUTPUT`. Defaults to `true`. Failures are never dataset rows.       |\n\nWhen `preferredLanguages` is set and no requested language exists, the Actor\nrecords a typed non-billable `LANGUAGE_UNAVAILABLE` failure in `OUTPUT`. It\ndoes not silently return another language.\n\n## 📦 Output\n\nEach default-dataset row represents one successful unique YouTube video or\nShort. The fields are ordered for clean loading into spreadsheets, APIs, and\nwarehouses.\n\n| Group      | Fields                                                                                                                                            |\n| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Input      | `platform`, `inputIndex`, `inputUrl`                                                                                                              |\n| Video      | `videoUrl`, `videoId`, `title`, `publishedAt`, `videoDurationSeconds`, `thumbnailUrl`                                                             |\n| Channel    | `channelId`, `channelName`, `channelUrl`                                                                                                          |\n| Language   | `requestedLanguageCodes`, `transcriptLanguageCode`, `transcriptLanguageName`, `availableLanguageCodes`, `languageMatch`, `isAutoGenerated`        |\n| Transcript | `segments`, `text`, optional `srt`, optional `vtt`, optional `llmText`                                                                            |\n| Quality    | `segmentCount`, `wordCount`, `characterCount`, `firstSegmentStartSeconds`, `lastSegmentEndSeconds`, `transcriptSpanSeconds`, `videoCoverageRatio` |\n| Result     | `status`, `statusReason`, `errorCategory`, `errorCode`, `isRetryable`, `scrapedAt`                                                                |\n\n### ✅ Successful row sample\n\n```json\n{\n    \"platform\": \"youtube\",\n    \"inputIndex\": 0,\n    \"inputUrl\": \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\",\n    \"videoUrl\": \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\",\n    \"videoId\": \"dQw4w9WgXcQ\",\n    \"title\": \"Example video title\",\n    \"publishedAt\": \"2024-04-30\",\n    \"videoDurationSeconds\": 212,\n    \"thumbnailUrl\": \"https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg\",\n    \"channelId\": \"UCexample123\",\n    \"channelName\": \"Example Channel\",\n    \"channelUrl\": \"https://www.youtube.com/@example\",\n    \"requestedLanguageCodes\": [\"en\"],\n    \"transcriptLanguageCode\": \"en\",\n    \"transcriptLanguageName\": \"English\",\n    \"availableLanguageCodes\": [\"en\", \"es\"],\n    \"languageMatch\": \"exact\",\n    \"isAutoGenerated\": false,\n    \"segments\": [\n        {\n            \"startSeconds\": 0,\n            \"endSeconds\": 2.4,\n            \"durationSeconds\": 2.4,\n            \"text\": \"Example transcript text\"\n        }\n    ],\n    \"text\": \"Example transcript text\",\n    \"srt\": null,\n    \"vtt\": null,\n    \"llmText\": null,\n    \"segmentCount\": 61,\n    \"wordCount\": 534,\n    \"characterCount\": 3180,\n    \"firstSegmentStartSeconds\": 0,\n    \"lastSegmentEndSeconds\": 210.4,\n    \"transcriptSpanSeconds\": 210.4,\n    \"videoCoverageRatio\": 0.9925,\n    \"status\": \"succeeded\",\n    \"statusReason\": \"Transcript parsed from public YouTube caption tracks.\",\n    \"errorCategory\": null,\n    \"errorCode\": null,\n    \"isRetryable\": false,\n    \"scrapedAt\": \"2026-07-08T21:43:38.000Z\"\n}\n```\n\n### ⚠️ Failed input detail\n\nWhen enabled, `OUTPUT.failedInputDetails` preserves safe input and canonical\nidentity details without creating a billable dataset row.\n\n```json\n{\n    \"inputIndex\": 1,\n    \"inputUrl\": \"https://www.youtube.com/watch?v=example1234\",\n    \"videoUrl\": \"https://www.youtube.com/watch?v=example1234\",\n    \"videoId\": \"example1234\",\n    \"status\": \"failed\",\n    \"statusReason\": \"No public transcript was available.\",\n    \"errorCategory\": \"no_transcript\",\n    \"errorCode\": \"TRANSCRIPT_NOT_FOUND\",\n    \"isRetryable\": false\n}\n```\n\nCommon failure codes:\n\n- `TRANSCRIPT_NOT_FOUND`: public video resolved, but no public caption track was available.\n- `VIDEO_UNAVAILABLE`: the video was unavailable.\n- `AGE_RESTRICTED`: YouTube required age-confirmed access.\n- `LOGIN_REQUIRED`: YouTube required login for the lookup.\n- `LANGUAGE_UNAVAILABLE`: none of the requested transcript languages were available.\n- `INVALID_INPUT` and `UNSUPPORTED_INPUT`: the input was not a supported direct video object.\n- `ACCESS_BLOCKED`, `TEMPORARY_FAILURE`, and `TRANSCRIPT_PARSE_FAILED`: the public lookup could not produce a transcript and may succeed later when `isRetryable` is true.\n\n## 🧾 Run summary\n\nThe `OUTPUT` record shows:\n\n- inputs received;\n- unique videos processed;\n- successful transcript rows;\n- duplicate videos skipped;\n- unavailable or unsupported inputs;\n- error-code counts;\n- optional safe details for inputs that did not produce a transcript.\n\nUse this summary to check the whole run before loading the dataset.\n\n## 💵 Pricing Event\n\nThe Actor is designed for Pay Per Event pricing. One billable event is one\nsuccessful transcript row written to the dataset. Failed, invalid, unsupported,\nage-restricted, unavailable, language-unavailable, and no-transcript rows are\nnon-billable. Public runs always fetch a fresh caption result.\n\n## 🚫 What this Actor is not\n\n- It does not generate AI speech-to-text when YouTube has no public captions.\n- It does not download video or audio files.\n- It does not use your YouTube account, cookies, OAuth, or private session.\n- It does not access private, deleted, members-only, or account-only videos.\n- It does not expand playlists, channels, search keywords, recommendations, or\n  comments. Use a discovery Actor first, then pass direct video URLs here.\n- It does not guarantee every public video has captions. When captions are\n  unavailable, the row explains the outcome and stays non-billable.\n\n## 🏆 Best practices\n\n- 🎯 Pass direct video or Shorts URLs whenever possible.\n- 🧠 Keep `outputFormats` to `[\"json\", \"text\"]` for most AI and data workflows.\n- 📝 Add `srt` or `vtt` only when you need subtitle files.\n- 🌐 Leave `preferredLanguages` empty for the best available track. Add language\n  codes in priority order when the result must use one of those languages.\n- 🔗 For channel, playlist, or keyword workflows, run discovery first and send the\n  resulting direct video URLs into this Actor.\n\n## 🔗 Related social media scrapers\n\nContinue the same workflow on this platform or compare public data across\nplatforms.\n\n### Continue on YouTube\n\n- [YouTube Channel Scraper](https://apify.com/chronometrica/youtube-channel-scraper)\n  — collect public channel details, links, and audience stats.\n- [YouTube Search Scraper](https://apify.com/chronometrica/youtube-search-scraper)\n  — find public videos, Shorts, channels, and metrics by keyword.\n- [YouTube Metrics Scraper](https://apify.com/chronometrica/youtube-metrics-scraper)\n  — collect public video, Short, channel, and engagement metrics.\n- [YouTube Comments Scraper](https://apify.com/chronometrica/youtube-comments-scraper)\n  — collect public comments, replies, authors, likes, pins, and creator\n  hearts.\n\n### Compare transcripts across platforms\n\n- [TikTok Transcript Scraper](https://apify.com/chronometrica/tiktok-transcript-scraper)\n  — extract public caption text and timestamped segments.\n"
    },
    "buildNumber": "0.1.43",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "0.1"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.01474888888888889
    }
  }
}