# YouTube Video API > Source: https://scrape.do/documentation/google-scraper-api/youtube-video/ Fetch YouTube video details, channels, comments, chapters, related videos, and publication timestamps as structured JSON The YouTube Video API returns structured details for one video, including its channel, description, chapters, related and end-screen videos, comments, and pagination tokens. It does not require JavaScript rendering or add a render fee. > [!NOTE] > **Credit Usage:** Each request costs **10 credits**, including continuation requests. For bulk processing, use the [Async API with plugins](/documentation/async-api/plugins/). ## Key Features - **Machine-readable publication time**: `published_at` is an RFC 3339 timestamp in UTC, suitable for sorting and video-age calculations. - **Stable channel identifiers**: `channel.channel_id` and `comments[].author.channel_id` remain stable when a channel changes its display name or handle. - **Exact numeric counts**: `extracted_views`, `extracted_likes`, and `extracted_subscribers` complement YouTube's formatted display strings. - **Complete video metadata**: Retrieve the description and links, chapters, related videos, end-screen videos, and transcript availability. - **Comments and replies**: Use continuation tokens to load comments, sort by newest or top, and fetch replies. - **Localization**: Control display strings with `hl` and influence related-video ranking with `gl`. --- ## Endpoint ```text GET https://api.scrape.do/plugin/google/youtube/video ``` ## Request Parameters ### Required | Parameter | Type | Description | |-----------|------|-------------| | `token` | string | Your Scrape.do API authentication token | | `v` | string | The 11-character YouTube video ID from a `watch?v=...` URL. Required for initial and continuation requests | ### Localization | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `hl` | string | `en` | Interface language, such as `en`, `de`, `fr`, `ja`, `tr`, or `pt-br`. Controls localized dates and count suffixes | | `gl` | string | `us` | Two-letter country code, such as `us`, `gb`, `de`, `fr`, or `jp`. Influences related-video ranking | ### Pagination | Parameter | Type | Description | |-----------|------|-------------| | `next_page_token` | string | A continuation token from a previous response. Accepts related-video, comment, comment-sorting, and reply tokens | The endpoint detects the token type automatically and returns the corresponding collection. --- ## Example Requests ### Video Details ```bash curl "https://api.scrape.do/plugin/google/youtube/video?v=dQw4w9WgXcQ&token=$TOKEN" ``` ### Localized Details ```bash curl "https://api.scrape.do/plugin/google/youtube/video?v=dQw4w9WgXcQ&hl=fr&gl=fr&token=$TOKEN" ``` ### More Related Videos Pass `related_videos_next_page_token` from the previous response: ```bash curl "https://api.scrape.do/plugin/google/youtube/video?v=dQw4w9WgXcQ&next_page_token=CBQSDRIL...&token=$TOKEN" ``` ### Comments or Replies Pass `comments_next_page_token`, a token from `comments_sorting_token`, or a comment's `replies_next_page_token`: ```bash curl "https://api.scrape.do/plugin/google/youtube/video?v=dQw4w9WgXcQ&next_page_token=Eg0SC2RR...&token=$TOKEN" ``` --- ## Response Modes The endpoint uses one response schema with three modes. Fields that do not apply to the current mode are omitted. | Mode | Trigger | Populated fields | |------|---------|------------------| | Video details | No `next_page_token` | Video metadata, channel, description, chapters, related videos, end-screen videos, comment tokens, and transcript token | | Related videos | `related_videos_next_page_token` | `related_videos` and a new `related_videos_next_page_token` | | Comments or replies | Comment, sorting, or reply token | `comments` and, when available, `comments_next_page_token` | ## Video Details Response ```json { "search_parameters": { "engine": "google_youtube_video", "v": "dQw4w9WgXcQ", "gl": "us", "hl": "en" }, "title": "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)", "thumbnail": "https://i.ytimg.com/vi_webp/dQw4w9WgXcQ/maxresdefault.webp", "channel": { "name": "Rick Astley", "channel_id": "UCuAXFkgsw1L7xaCfnd5JJOw", "link": "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw", "thumbnail": "https://yt3.ggpht.com/...", "subscribers": "4.51M subscribers", "extracted_subscribers": 4510000, "verified": true }, "views": "1,790,053,431 views", "extracted_views": 1790053431, "likes": "19M", "extracted_likes": 19222757, "published_date": "Oct 24, 2009", "published_at": "2009-10-25T06:57:33Z", "description": { "content": "The official video...", "links": [] }, "chapters": [], "related_videos": [], "related_videos_next_page_token": "CBQSDRILZFF3NHc5V2dYY1E...", "end_screen_videos": [], "comments_next_page_token": "Eg0SC2RRdzR3OVdnWGNR...", "comments_sorting_token": [], "transcript": { "token": "CgtkUXc0dzlXZ1hjUQ..." } } ``` ### Publication Fields | Field | Type | Description | |-------|------|-------------| | `published_date` | string | YouTube's day-precision display date, localized by `hl`, such as `Oct 24, 2009` or `3 Nis 2016` | | `published_at` | string | RFC 3339 publication timestamp, always in UTC, such as `2009-10-25T06:57:33Z` | Use `published_at` for chronological sorting, precise video age, and rate-per-hour calculations. Use `published_date` when you need the text shown for the requested locale. On rare videos where YouTube does not provide an exact timestamp, `published_at` is omitted while `published_date` can still be present. ### `channel` | Field | Type | Description | |-------|------|-------------| | `name` | string | Channel display name | | `channel_id` | string | Stable `UC...` channel identifier | | `link` | string | Absolute channel URL. YouTube may return either an `@handle` or `/channel/` URL | | `thumbnail` | string | Channel avatar URL | | `subscribers` | string | Formatted subscriber count, localized by `hl` | | `extracted_subscribers` | number | Parsed numeric subscriber count | | `verified` | boolean | `true` for verified channels and official artist channels. Omitted when `false` | Use `channel_id` as the durable identifier instead of parsing `link`, because channel handles and display names can change. ### Views and Likes | Field | Type | Description | |-------|------|-------------| | `views` | string | Formatted view count as displayed by YouTube | | `extracted_views` | number | Exact numeric view count | | `likes` | string | Compact like count as displayed on the like button, such as `19M` | | `extracted_likes` | number | Exact numeric like count | ### `description` ```json { "content": "The official video for Never Gonna Give You Up...", "links": [ { "start_index": 180, "length": 16, "text": "#rickastleynever", "url": "https://www.youtube.com/hashtag/rickastleynever" } ] } ``` `links[].start_index` and `links[].length` use UTF-16 code units, matching JavaScript string indexing. External targets use YouTube's redirect URL when that is what appears on the page. ### `chapters` Present only when the creator has defined chapters. ```json [ { "title": "Introduction", "thumbnail": "https://i.ytimg.com/vi/...", "time_start": 0 }, { "title": "Variables", "thumbnail": "https://i.ytimg.com/vi/...", "time_start": 208 } ] ``` `time_start` is the chapter's start offset in seconds. ### `related_videos` The initial response usually includes about 20 sidebar suggestions. Use `related_videos_next_page_token` to retrieve more. ```json [ { "video_id": "u_cLVh73u_o", "link": "https://www.youtube.com/watch?v=u_cLVh73u_o", "thumbnail": { "static": "https://i.ytimg.com/vi/u_cLVh73u_o/hqdefault.jpg", "rich": "https://i.ytimg.com/an_webp/u_cLVh73u_o/mqdefault_6s.webp" }, "title": "80'S MUSIC ON THE ROAD", "published_date": "6 days ago", "views": "421K views", "extracted_views": 421000, "length": "2:16:49", "channel": { "name": "Every Song Is A Scar", "link": "https://www.youtube.com/@everysongisascar", "verified": true } } ] ``` `thumbnail.rich` is an animated preview and is omitted when unavailable. A live suggestion has `live: true` and a watcher count, so `views`, `extracted_views`, and `published_date` are omitted. Shorts shelves between suggestions are not included. ### `end_screen_videos` End-screen cards include fields such as `video_id`, `link`, `title`, `thumbnail`, `views`, `extracted_views`, and `length`. YouTube does not display a publication date or channel on these cards, so those fields are absent. ### `comments_sorting_token` ```json [ { "title": "Top", "token": "Eg0SC2RRdzR3OVdnWGNR..." }, { "title": "Newest", "token": "Eg0SC2RRdzR3OVdnWGNR..." } ] ``` Pass either token as `next_page_token` to load comments in that order. The initial `comments_next_page_token` uses the default Top ordering. ### `transcript` ```json { "token": "CgtkUXc0dzlXZ1hjUQ..." } ``` This opaque token indicates that the video has a transcript. It is reserved for future use; this endpoint does not return transcript text. --- ## Comments Response Comment pages contain 20 items per batch. Reply pages contain 10 items per batch. ```json { "search_parameters": { "engine": "google_youtube_video", "v": "dQw4w9WgXcQ", "gl": "us", "hl": "en", "next_page_token": "Eg0SC2RR..." }, "comments": [ { "comment_id": "UgzB3ZO9YOWY0PJqmZR4AaABAg", "content": "can confirm: he never gave us up", "published_date": "1 year ago", "likes": "265K", "extracted_likes": 265000, "replies_count": 961, "pinned": true, "author": { "name": "@YouTube", "link": "https://www.youtube.com/@YouTube", "channel_id": "UCBR8-60-B28hp2BmDPdntcQ", "thumbnail": "https://yt3.ggpht.com/...", "verified": true }, "replies_next_page_token": "Eg0SC2RRdzR3OVdnWGNR..." } ], "comments_next_page_token": "Eg0SC2RRdzR3OVdnWGNR..." } ``` | Field | Type | Description | |-------|------|-------------| | `comment_id` | string | Stable comment identifier | | `content` | string | Comment text | | `published_date` | string | Relative date localized by `hl`; may include an `(edited)` suffix | | `likes` | string | Formatted like count | | `extracted_likes` | number | Parsed numeric like count | | `replies_count` | number | Number of replies. Omitted when `0` | | `pinned` | boolean | `true` for a creator-pinned comment. Omitted when `false` | | `author.channel_id` | string | Stable identifier for the comment author's channel | | `author.is_creator` | boolean | `true` when the video's creator wrote the comment. Omitted when `false` | | `replies_next_page_token` | string | Pass as `next_page_token` to fetch replies | Reply batches use the same `comments` item shape. They omit `replies_next_page_token` and use `comments_next_page_token` for additional replies in the same thread. --- ## Pagination Guidelines - Treat every continuation token as opaque and pass it back unchanged. - Tokens belong to a specific video, collection, and position. Do not reuse them across videos. - Stop when the response no longer includes the relevant next-page token. - Keep `v` on every continuation request. The continuation token selects the underlying video content. - Tokens containing percent sequences can be passed as returned or URL-encoded with `curl -G --data-urlencode`. --- ## Error Handling | Status | Error | Cause | |--------|-------|-------| | `400` | `token is required` | Missing API token | | `400` | `v is required` | Missing video ID | | `400` | `v must be an 11-character YouTube video id` | Malformed video ID | | `400` | `gl must be a 2-letter country code` | Invalid country code | | `400` | `hl must be a valid language code (e.g., en, de, pt-br)` | Invalid language code | | `401` | Gateway authorization error | Invalid or inactive API token | | `429` | Gateway rate-limit error | Concurrent-request or monthly quota limit reached | | `502` | `upstream returned truncated page` | YouTube returned a partial page. Retry the request | | `502` | `failed to parse video results` | Invalid or expired continuation token, unavailable video, or unexpected upstream response | | `502` | `unexpected response` | YouTube returned a non-200 status. Retry the request | | `502` | `request failed` | Network-level failure. Retry the request | | `500` | `decompression failed` | Response decompression failed | | `500` | `internal server error` | Unhandled server error. Report it if persistent | ## Notes - Private, removed, age-gated, or region-blocked videos can return `502 failed to parse video results` and are not charged. - Optional fields are omitted when YouTube does not provide them; one unavailable field does not fail an otherwise valid response. - Display strings follow `hl`, while `extracted_*` fields are normalized to integers when the value can be determined safely. - Match `hl` and `gl`, such as `hl=fr&gl=fr`, for consistent localized metadata and regional ranking.