# YouTube Channel Videos Scraper (`lightmoon/youtube-channel-videos-scraper`) Actor

Export every video of any YouTube channel to CSV or Excel: title, duration, link, exact view and like counts and a publish timestamp to the second, not "3 weeks ago". From $0.45 per 1,000 videos. Filter by date to track new uploads and monitor channels - filtered videos are free.

- **URL**: https://apify.com/lightmoon/youtube-channel-videos-scraper.md
- **Developed by:** [Stable](https://apify.com/lightmoon) (community)
- **Categories:** Social media, Lead generation, Videos
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.45 / 1,000 videos

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/actors/running/actors-in-store.md#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

> **Unofficial.** This Actor is not affiliated with, endorsed by or sponsored by YouTube or Google. It reads only publicly available pages, does not log in and does not bypass any access control. All product names and trademarks belong to their respective owners.

### One row of output

Paste channel handles; get one flat table. This is a real row from a real run,
not a mock-up:

```json
{
  "videoId": "xs5iOwkX9fU",
  "videoUrl": "https://www.youtube.com/watch?v=xs5iOwkX9fU",
  "title": "Why CPU Time ≠ Wall Clock Time! - Computerphile",
  "channelName": "Computerphile",
  "channelHandle": "@Computerphile",
  "channelId": "UC9-y-6csu5WGm29I7JiwpnA",
  "publishedAt": "2026-08-27T13:00:19+00:00",
  "publishedText": "18 hours ago",
  "updatedAt": "2026-08-27T13:04:33+00:00",
  "viewCount": 51230,
  "viewCountText": "51K views",
  "likeCount": 835,
  "durationSeconds": 1181,
  "durationText": "19:41",
  "isShort": false,
  "thumbnailUrl": "https://i.ytimg.com/vi/xs5iOwkX9fU/hq720.jpg",
  "statsSource": "feed"
}
```

**Look at `viewCount` and `viewCountText` sitting side by side.** One is the
number YouTube keeps; the other is the words YouTube shows. Both ship, under
different names, and `statsSource` says which of them the exact one came from.
No other listing in this category tells you that.

### What you get

**22 columns per row**, all flat — one CSV, no nested cells to unpick.

| | |
|---|---|
| Identity | `videoId`, `videoUrl`, `title`, `isShort` |
| Channel | `channelName`, `channelHandle`, `channelId`, `channelUrl` |
| Timing | `publishedAt` (exact, to the second), `publishedDateText` (to the day), `publishedText` (YouTube's own wording), `updatedAt` |
| Reach | `viewCount`, `likeCount` (exact integers) · `viewCountText` (YouTube's wording) |
| Shape | `durationSeconds`, `durationText`, `thumbnailUrl`, `description` |
| Provenance | `statsSource`, `recordType`, `scrapedAt` |

Export to CSV, Excel, JSON or read it from the API. No account, no API key, no
cookies.

### Three things this does that are worth knowing

**1. Every number says where it came from.** `statsSource` is `feed` for an
exact figure straight from the channel's own feed, `video-page` for one read
off the video, and `list-only` when all YouTube offered was `"51K views"`. A
table that mixes exact and rounded numbers without labelling them is a table
you cannot safely sort. This one labels them.

**2. A video you filtered out is never charged for.** Set a date range, or turn
Shorts off, and the videos that fall outside are dropped **before** billing.
The run report tells you how many, and why.

**3. Nothing is guessed.** A field YouTube did not publish comes back empty —
never a zero, never `"N/A"`, never a date reconstructed from "3 weeks ago". If
`viewCount` is missing, `viewCountText` is there instead and `statsSource` says
so.

### Input

```json
{
  "channels": ["@Computerphile", "https://www.youtube.com/@veritasium"],
  "maxVideosPerChannel": 100,
  "includeShorts": true,
  "publishedAfter": "2026-08-01"
}
```

Channels are accepted as a handle (`@Computerphile`), a URL, or a channel id
(`UC9-y-6csu5WGm29I7JiwpnA`). Up to 200 channels per run.

### Price

**$0.45 per 1,000 videos** on the Store card. A typical run — 3 channels, 200
videos each — is 600 rows for **$0.27**.

Exact figures for the **fifteen newest videos of every channel** are included at
that price. They come from the channel's own feed, which is small and cheap, so
there is no reason to charge extra for them.

Exact figures for **older** videos are optional
(`exactStatsForOlderVideos`) and billed separately, because each one means
reading that video's own page — about 240 times the data. Leave it off and older
videos still arrive, with YouTube's own rounded figures in their own columns.

**Free trial: 100 videos.** Free-plan runs work in full; only the volume is
smaller.

### Limits, stated plainly

- **Exact timestamps and exact counts are free for the fifteen newest videos of
  each channel.** That is the size of YouTube's own channel feed and it cannot
  be widened. For older videos you either accept YouTube's rounded wording or
  switch on the paid option.
- **Shorts carry no duration.** They never appear on a channel's Videos tab, so
  they reach you through the feed, and the feed does not publish a length. They
  are flagged with `isShort` either way, and you can exclude them.
- **Date filtering is exact for videos the feed covers** and approximate for
  older ones, because YouTube only says "3 weeks ago". When the wording could
  fall inside your window, the video is kept rather than dropped — you can see
  its date and decide.
- **Videos arrive 30 at a time**, newest first.
- This reads what YouTube shows the public. Private, unlisted and
  members-only videos are not visible and are not returned.

### Typical uses

- Export a channel's back catalogue to a spreadsheet with real numbers in it.
- Watch a list of channels and pull only what went up since last week — the
  date filter runs before billing, so a quiet week costs almost nothing.
- Compare upload cadence across channels using timestamps you can subtract,
  rather than "2 months ago".
- Separate Shorts from long-form and measure them apart.

# Actor input Schema

## `channels` (type: `array`):

One per line. A handle (@Computerphile), a channel URL (https://www.youtube.com/@Computerphile) or a channel id (UC9-y-6csu5WGm29I7JiwpnA) all work. A channel's display name is not always its handle, so paste the URL if you are unsure.

## `maxVideosPerChannel` (type: `integer`):

How far back to go on each channel, newest first. Videos arrive 30 at a time.

## `includeShorts` (type: `boolean`):

Shorts are marked in their own column either way. Turn this off to get long-form videos only.

## `publishedAfter` (type: `string`):

Skip anything older. Videos excluded here are never charged for. Exact for the fifteen newest videos of each channel; for older ones YouTube only says "3 weeks ago", so a video is kept whenever that wording could fall inside your window.

## `publishedBefore` (type: `string`):

Skip anything newer. Same accuracy note as above.

## `exactStatsForOlderVideos` (type: `boolean`):

The fifteen newest videos of every channel always come with an exact publish time and exact view and like counts, at no extra charge. Turn this on to fetch the same exact figures for older videos too - it reads each video's own page, which is far heavier, so those rows are charged at the higher rate shown on the Pricing tab. Leave it off and older videos keep YouTube's own rounded figures in their own columns.

## Actor input object example

```json
{
  "channels": [
    "@Computerphile"
  ],
  "maxVideosPerChannel": 100,
  "includeShorts": true,
  "exactStatsForOlderVideos": false
}
```

# Actor output Schema

## `videos` (type: `string`):

No description

## `exact` (type: `string`):

No description

# 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 = {
    "channels": [
        "@Computerphile"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lightmoon/youtube-channel-videos-scraper").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 = { "channels": ["@Computerphile"] }

# Run the Actor and wait for it to finish
run = client.actor("lightmoon/youtube-channel-videos-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "channels": [
    "@Computerphile"
  ]
}' |
apify call lightmoon/youtube-channel-videos-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lightmoon/youtube-channel-videos-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/AQGnfgTrFeqXOBNKX/builds/VmY45Tv8GhoKBTO2R/openapi.json
