# YouTube Video Scraper · 5 datasets per URL (`doesaiknow/youtube-scraper-5-datasets-from-one-video-url`) Actor

One video URL in, five joined datasets out: video metadata, channel profile, comments, transcript and the YouTube search results for the video's own title. One flat row per video, joined on video\_id and channel\_id. Switch off any section you do not need. One delivered row is one billed row.

- **URL**: https://apify.com/doesaiknow/youtube-scraper-5-datasets-from-one-video-url.md
- **Developed by:** [David S](https://apify.com/doesaiknow) (community)
- **Categories:** Videos, Social media, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.06 / youtube video report

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## YouTube Video Scraper — video, channel, comments, transcript and search in one row

Paste **one YouTube video URL** and get **five joined datasets in a single row**: video metadata, the
channel profile behind it, the comments, the full transcript, and the YouTube search results for the
video's own title — with the rank the video holds on that query.

Built for agencies and competitive-intelligence teams who today run three or four separate actors and
glue the exports together by hand. Here every section arrives in **one flat row**, joined on
`video_id` and `channel_id`, at **$0.60 per delivered video** on the Free plan — from the Console,
the API, the CLI or the Apify MCP server (`mcp.apify.com`).

### What does the YouTube Video Scraper do?

For each unique video it fetches up to five sections in one pass: **video** (title, counters,
duration, keywords, key moments), **channel** (handle, subscribers, lifetime views, video count, join
date), **comments** (top-level comments with likes and reply counts), **transcript** (timestamped
segments plus one plain-text string) and **search** (the results page for the video's own title, and
where the video ranks on it).

Every section lands in the same row, always with the same 36 keys, so the warehouse join is one line
instead of four exports with four field naming schemes. Switch a section off and it is not fetched at
all: its fields come back `null` and the section is listed in `sections_skipped`. Nothing is
summarised, translated or scored — the row is what YouTube published, measured at one moment.

### Why use the YouTube Video Scraper

- **Five datasets, one run, one join key** — one row joined on `video_id` and `channel_id`, so no
  cross-actor field mapping.
- **Competitive rank included** — `search_self_rank` shows where the video sits on the results page
  for its own title, next to the competing videos in `search_results`.
- **Duplicates merged before anything is fetched** — the same video pasted three ways (`watch?v=`,
  `youtu.be/`, bare ID) is one row and one charge.
- **Missing data is reported, not faked** — a video without subtitles is a delivered row with
  `status: "partial"` and `transcript_unavailable` in `partial_reasons`, not a failed run.
- **Free repeats for 24 hours** — a video processed in the last 24 hours is re-delivered from cache
  at no charge, keeping its original `fetched_at`.
- **A hard spending limit you set** — `maxTotalChargeUsd` stops the run **before** its first request.

### How to scrape a YouTube video, its channel, comments and transcript

1. Paste links into **Video URLs or IDs** — watch URLs, `youtu.be` links, Shorts links, embed links
   and bare 11-character IDs all work.
2. Leave the five **Sections** switches on for the full pack, or turn off what you do not need.
3. Pick the **Language** for the transcript (English by default, 28 languages).
4. Optionally pick a **Country** to request the data from one market; "Auto" lets YouTube decide.
5. Raise **Comment pages per video** (about 20 top-level comments per page, up to 10 pages).
6. Optionally set **Maximum charge per run (USD)** as a hard ceiling.
7. Run the Actor, then open the **Overview** dataset view or export to JSON, CSV or Excel. The
   **Issues** view lists only rows that came back `partial` or `not_found`.

Minimal input:

```json
{ "videoUrls": ["https://www.youtube.com/watch?v=rfscVS0vtbw"] }
```

Transcript and comments only, Spanish, two comment pages, capped budget:

```json
{ "videoUrls": ["rfscVS0vtbw", "https://youtu.be/UF8uR6Z6KLc"], "includeChannel": false,
  "includeSearch": false, "language": "es", "commentsPages": 2, "maxTotalChargeUsd": 0.05 }
```

### What data you get per video

One row = one video, always the same 36 keys. Example row, long lists truncated:

```json
{
  "video_id": "rfscVS0vtbw",
  "video_url": "https://www.youtube.com/watch?v=rfscVS0vtbw",
  "status": "ok",
  "fetched_at": "2026-07-30T09:14:02.371Z",
  "title": "Learn Python - Full Course for Beginners [Tutorial]",
  "description": "This course will give you a full introduction into the core concepts ...",
  "views": 49046089, "likes": 1100000, "published_date": "Jul 11, 2018", "duration_seconds": 16012,
  "keywords": ["python", "python tutorial", "python full course"],
  "thumbnail": "https://i.ytimg.com/vi/rfscVS0vtbw/maxresdefault.jpg",
  "comments_total": 46111, "chapters": [],
  "key_moments": [{ "start": "1:45", "title": "Installing Python & PyCharm" }],
  "channel_id": "UCWv7vMbMWH4-V0ZXdmDpPBA", "channel_handle": "@freecodecamp",
  "channel_title": "freeCodeCamp.org", "channel_subscribers": 11800000,
  "channel_views": 1252445166, "channel_videos_count": 1900, "channel_joined_date": "2014-12-16",
  "channel_description": "We're a community of millions of people learning to code ...",
  "comments": [
    { "comment_id": "Ugxqcek3RUzxWv-4VqB4AaABAg", "author": "@freecodecamp", "text": "Want more from Mike?",
      "likes": 4700, "replies": 147, "published_date": "5 years ago" }
  ],
  "transcript": [{ "text": "Welcome to this Python course.", "start": 1.36, "duration": 3.2, "end": 4.56, "lang": "en" }],
  "transcript_text": "Welcome to this Python course. In this video we will cover ...",
  "transcript_language": "en", "transcript_segment_count": 4212, "transcript_word_count": 61840,
  "search_query": "Learn Python - Full Course for Beginners [Tutorial]",
  "search_results": [
    { "position": 1, "video_id": "UF8uR6Z6KLc", "title": "Python for Everybody",
      "url": "https://www.youtube.com/watch?v=UF8uR6Z6KLc", "channel_name": "freeCodeCamp.org",
      "channel_handle": "@freecodecamp", "views": 1200000, "published_date": "5 years ago", "duration": "13:39:11" }
  ],
  "search_self_rank": 2,
  "sections_included": ["video", "channel", "comments", "transcript", "search"],
  "sections_skipped": [], "partial_reasons": [],
  "source": { "video": "primary", "channel": "primary", "comments": "primary", "transcript": "primary", "search": "primary" }
}
```

| Field | Type | What it tells you |
|---|---|---|
| `video_id` / `video_url` | string | Canonical 11-character ID and watch URL — the join key |
| `status` / `fetched_at` | string | `ok`, `partial` or `not_found`, and when the row was produced |
| `title` / `description` | string | null | Title and description, decoded to plain text |
| `views` / `likes` | integer | null | View and like counts as integers |
| `published_date` / `duration_seconds` | string | integer | Publish label as listed, length in seconds |
| `keywords` / `thumbnail` | array | string | Keyword tags, highest-resolution thumbnail URL |
| `comments_total` | integer | null | Exact comment count on the video |
| `key_moments` / `chapters` | array | Timeline markers `{start, title}`; `chapters` is the structured field, often empty |
| `channel_id` / `channel_handle` / `channel_title` | string | null | `UC…` ID, `@handle`, name — second join key |
| `channel_subscribers` / `channel_views` / `channel_videos_count` | integer | null | Channel counters |
| `channel_joined_date` / `channel_description` | string | null | Creation date and About text |
| `comments` | array | null | `{comment_id, author, text, likes, replies, published_date}` |
| `transcript` | array | null | `{text, start, end, duration, lang}` in seconds, `end = start + duration` |
| `transcript_text` / `transcript_segment_count` / `transcript_word_count` | string | integer | Whole transcript as plain text (entities and markup removed), plus its counters |
| `transcript_language` | string | null | Language **actually returned**, never an echo of your request |
| `search_query` / `search_results` | string | array | The video's own title, and the results page for it |
| `search_self_rank` | integer | null | Rank of this video on that page; `null` when it is not on it |
| `sections_included` / `sections_skipped` | array | Which of the five sections delivered data, and which did not |
| `partial_reasons` | array | Fixed codes: `transcript_unavailable`, `channel_unavailable`, `video_not_found`, … |
| `source` | object | Per section: `primary`, `fallback`, or `null` when there was no response |

### Input parameters

| Field | Required | Notes |
|---|---|---|
| `videoUrls` | yes | Up to 500 video URLs or IDs; duplicates merge into one row |
| `includeVideo` | no | Video metadata section, on by default |
| `includeChannel` | no | Channel profile section, on by default |
| `includeComments` | no | Comments section, on by default |
| `includeTranscript` | no | Transcript section, on by default |
| `includeSearch` | no | Search + `search_self_rank` section, on by default |
| `language` | no | Transcript language, 28 options, `en` by default |
| `country` | no | Market the data is requested from; "Auto" lets YouTube choose |
| `commentsPages` | no | Comment pages per video, 1-10 (default 1, ~20 comments per page) |
| `maxTotalChargeUsd` | no | Hard ceiling; the run stops before its first request |

### How much does the YouTube Video Scraper cost?

Pay-per-event billing: you pay per **delivered row**, never per request or per section.

| Event | When | Price |
|---|---|---|
| Run start | Once per run | $0.002 |
| YouTube video report | Per delivered video | $0.60 Free → $0.10 Bronze → $0.08 Silver → $0.06 Gold+ |

The whole pack is one price: five sections, up to 10 comment pages and retries sit inside the
per-video price, and turning sections off does not change it. 100 videos cost $60.20 on the Free plan, $10.20 or less on any paid plan.

You are not charged for cache hits (a video processed within 24 hours is re-delivered free), for
failures (no row, no charge), or for duplicate URLs of the same video. A `not_found` video **is**
charged as one row — "this video does not exist" is a delivered answer. A `partial` row is one row
too: measured data plus an explicit list of what was missing.

### YouTube Video Scraper vs single-purpose YouTube actors

| | This actor | Separate metadata / comments / transcript actors |
|---|---|---|
| Input | One video URL | The same URL pasted into 3-4 actors |
| Datasets per run | 5, in one row | 3-4 exports, 3-4 schemas |
| Join key | `video_id` + `channel_id` | Whatever each actor calls its ID |
| Rank for the video's title | Included | Usually another actor |
| Billing unit | One delivered video | One per actor, per model |

### What this actor does not do

- It does **not** summarise, translate, score or sentiment-tag anything.
- It does **not** promise a filled `chapters` array: YouTube often exposes the chapter list only as
  `key_moments`, and nothing is copied between the two fields.
- It does **not** return a commenter's display name (`author` is the handle the comment carries), and
  it returns top-level comments only, with a `replies` count.
- It does **not** list a channel's back catalogue, its Shorts or its upload cadence.
- It does **not** touch private, members-only or age-gated content, downloads no media, and does not
  go past 500 videos per run.

### FAQ

#### What exactly is one billed row?

One unique video that came back with data — five sections or one, it is one charge. Duplicates, cache
hits and failures are not charged.

#### What happens to a video without a transcript?

You get a normal row with `status: "partial"`, `null` transcript fields, `transcript` in
`sections_skipped` and `transcript_unavailable` in `partial_reasons`. The other four sections are
still delivered, so a captionless video never breaks a batch.

#### Why is search\_self\_rank sometimes null?

Because the video is not on the returned results page for its own title. `null` means "not on this
page" — the field never returns `0` or a negative number to mean "missing".

#### Can I get more than 20 comments per video?

Yes. Set **Comment pages per video** up to 10; every page lands in the same `comments` array of the
same row, at no extra charge.

#### Does the requested language guarantee that transcript language?

No, and the row says so. `transcript_language` reports the language actually returned; a video with
no subtitles in your language yields `transcript_unavailable`, not a silent substitution.

#### Can I run this from an AI agent or on a schedule?

Yes — Apify API, CLI, or the Apify MCP server (`mcp.apify.com`). Schedule runs to track how counters,
comments and search rank move over time.

### Related actors

- [YouTube Transcript Scraper](https://apify.com/doesaiknow/youtube-transcript-scraper-500-videos-per-run)
  — transcripts for a whole channel or playlist.
- [YouTube Influencer Finder](https://apify.com/doesaiknow/youtube-influencer-discovery-contact-api)
  — find channels worth analysing, with subscriber stats and public contact profiles.
- [YouTube Research Digest](https://apify.com/doesaiknow/youtube-research-digest) — an AI digest of
  what the top videos for a keyword say.

### Legal & support

- This actor collects **publicly available video information**: what a video page, a channel page, a
  public comment thread, a published subtitle track and a results page show to any visitor. It does
  not access private, members-only or log-in-gated content and downloads no media files.
- Comments and transcripts are returned **verbatim**, with timestamps as published, so every line can
  be verified against the source video.
- Video metadata, comments and transcripts are **third-party content**. You remain responsible for
  how you use them, including copyright, YouTube's terms and any attribution or storage rules that
  apply to you — especially when this data feeds a public product or an AI index.
- Comment rows can contain **personal data** (handles, free text). Handle them under your own GDPR or
  equivalent obligations and keep only what your purpose requires.
- Output is **as-is**: every counter and ranking is a point-in-time value.
- Questions or a bug? Open an issue on the Actor's **Issues** tab, or see the **API** tab.

### SEO keywords

youtube scraper, youtube video scraper, youtube data api alternative, scrape youtube video data,
youtube comments scraper, youtube transcript scraper, youtube channel scraper, youtube search
scraper, youtube metadata extraction, youtube video statistics, youtube subscriber count api,
youtube competitor analysis, youtube seo tool, youtube ranking checker, video engagement data,
youtube comment export, youtube captions api, bulk youtube data extraction, youtube dataset json
csv, youtube influencer research.

Built by doesaiknow.

# Actor input Schema

## `videoUrls` (type: `array`):

Videos to process — one delivered row per video. Accepts watch URLs (https://www.youtube.com/watch?v=ID), short links (https://youtu.be/ID), Shorts links (/shorts/ID), embed links (/embed/ID) and bare 11-character video IDs. Duplicates of the same video are merged into one row before any data is fetched, so you are never billed twice for the same video.

## `includeVideo` (type: `boolean`):

Video title, description, views, likes, publish date, duration, keywords, thumbnail, chapters and key moments. Turn a section off and its fields are returned as null and listed in "sections\_skipped".

## `includeChannel` (type: `boolean`):

Channel ID, handle, title, subscribers, total views, video count, join date and description of the channel that published the video.

## `includeComments` (type: `boolean`):

Top-level comments with author, text, likes, reply count and publish date, plus the total comment count.

## `includeTranscript` (type: `boolean`):

Timestamped transcript segments, the full transcript text, the language actually returned, the segment count and the word count.

## `includeSearch` (type: `boolean`):

YouTube search results for the video title, plus the rank of the video itself among them — competitive context for the same query the video competes on.

## `language` (type: `string`):

Preferred language for the transcript and for the language-dependent text fields. When a video has no transcript in this language, the row is returned with the transcript section marked as unavailable — the language actually returned is always reported in "transcript\_language".

## `country` (type: `string`):

Market the video, channel, comment and search data is requested from. Leave on "Auto" to let YouTube pick the market.

## `commentsPages` (type: `integer`):

How many pages of comments to load per video. One page is roughly 20 top-level comments. Ignored when the comments section is turned off.

## `maxTotalChargeUsd` (type: `number`):

Hard spending limit for this run. When the videos in the input would cost more than this, the run stops before fetching anything and tells you how many videos fit the limit. Leave empty to run without a limit.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://youtu.be/UF8uR6Z6KLc",
    "kJQP7kiw5Fk"
  ],
  "includeVideo": true,
  "includeChannel": true,
  "includeComments": true,
  "includeTranscript": true,
  "includeSearch": true,
  "language": "en",
  "country": "",
  "commentsPages": 1
}
```

# Actor output Schema

## `results` (type: `string`):

All delivered rows: video\_id, video\_url, status, video metadata, channel profile, comments, transcript with timestamps, search results and search\_self\_rank, joined on video\_id and channel\_id.

## `cache` (type: `string`):

Rows, channel profiles and search results cached for 24 hours. A cache hit re-delivers the row free of charge.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "videoUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://youtu.be/UF8uR6Z6KLc",
        "kJQP7kiw5Fk"
    ],
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("doesaiknow/youtube-scraper-5-datasets-from-one-video-url").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "videoUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://youtu.be/UF8uR6Z6KLc",
        "kJQP7kiw5Fk",
    ],
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("doesaiknow/youtube-scraper-5-datasets-from-one-video-url").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://youtu.be/UF8uR6Z6KLc",
    "kJQP7kiw5Fk"
  ],
  "language": "en"
}' |
apify call doesaiknow/youtube-scraper-5-datasets-from-one-video-url --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=doesaiknow/youtube-scraper-5-datasets-from-one-video-url",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/AWI0aUStlvMec8Q8O/builds/fvzWXAAUUDwBWyL4F/openapi.json
