# YouTube Channel Scraper: Latest Videos, Views, New Uploads (`actose/youtube-channel-rss`) Actor

Latest videos of YouTube channels (URL, @handle, ID): title, date, description, views, likes, thumbnail, Shorts, LLM-ready Markdown. onlyNew for schedules. No API key, no login. MCP-ready for AI agents. YouTube Data API alternative, no quota. Pay per result, errors free. $0.24 per 1,000 videos

- **URL**: https://apify.com/actose/youtube-channel-rss.md
- **Developed by:** [ABM](https://apify.com/actose) (community)
- **Categories:** Videos, Social media, Agents
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.20 / 1,000 video returneds

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## YouTube Channel Scraper: Latest Videos, Views & New Uploads

**$0.24 per 1,000 videos** ($0.00024 per video returned). Pay per result, no monthly rental. Errors, blocked channels, empty feeds and already-seen videos are **free**.

Get the latest videos of any list of YouTube channels — title, publication date, description, view count, like count, thumbnail, Shorts flag and an **LLM-ready Markdown** block — from YouTube's **official public RSS feeds**, with an **automatic fallback to the channel's Videos / Shorts / Live tab** when a feed is unavailable. Schedule it with **`onlyNew`** and it becomes a lightweight **new-video monitor**: each run returns only the uploads published since the previous run.

- ✅ **No API key, no login, no quota** — a YouTube Data API alternative for recent uploads
- ✅ Input: channel URLs, `@handles` or `UC...` channel IDs (mixed in one list, bulk up to 5,000)
- ✅ Output: one flat JSON item per video (export to JSON, CSV, Excel), camelCase fields
- ✅ Filter: all uploads, long videos only, Shorts only, or past live streams
- ✅ `onlyNew`: remembers seen videos, outputs (and charges) only new ones
- ✅ MCP-ready for Claude, Cursor, ChatGPT and AI agents (ready-made `markdown` field for RAG)
- ✅ Fast and light: small HTTP/JSON requests, no browser
- ✅ Reliable: RSS feed → uploads playlist feed → channel page data, with retries and proxy fallback; one failing channel never stops the others

### How much does it cost?

You pay **$0.00024 per video** delivered to the dataset — **$0.24 per 1,000 videos**. Nothing else: proxy and compute are included.

| Example | Videos | Cost |
|---|---|---|
| 100 channels × 5 latest videos | 500 | **$0.12** |
| 1,000 channels × 1 latest video | 1,000 | **$0.24** |
| 200 channels monitored hourly with `onlyNew`, ~2 uploads/day each | ~400/day | **~$0.10/day** |

Not charged: channels that fail or are blocked, invalid inputs, empty feeds, the first-run baseline of `onlyNew`, videos already returned in earlier runs. Set a maximum cost per run and the Actor stops cleanly when it is reached — it never returns unpaid "preview" results beyond it.

**About proxies:** you never pay for proxies separately. The Actor tries direct requests first, then the Apify datacenter proxy. A residential proxy (which costs the developer $8/GB) is only used as a last resort, for small RSS/JSON requests (never full pages, images or media), with a hard per-run cap. The bytes used are written to the log and to the `SUMMARY` record.

### What does it do?

For each channel, the Actor:

1. Converts `@handles`, `/c/` and `/user/` URLs to the `UC...` channel ID (one small JSON request, or the channel page's `externalId` / canonical link).
2. Reads the official feed `youtube.com/feeds/videos.xml?channel_id=UC...` — the same feed RSS readers have used for 15+ years. If YouTube refuses it (it sometimes returns 404 to cloud servers), it retries after a pause, tries the uploads playlist feed (`playlist_id=UU...`), then the datacenter proxy.
3. If no feed is served, it reads the latest videos from the channel's **Videos**, **Shorts** or **Live** tab (the JSON data embedded in the public page) and returns the **same fields**. In that case `publishedAt` is computed from YouTube's relative date ("3 days ago", `dateIsApproximate: true`), the description is the short snippet, and `likes` is empty.

`feedSource` tells you which source each video came from. The tool returns up to the **15 most recent uploads** per channel — built for **tracking recent uploads** quickly and cheaply, not for downloading a channel's full history.

### Input example

```json
{
  "channels": [
    "https://www.youtube.com/@MrBeast",
    "@mkbhd",
    "UCBJycsmduvYEL83R_U4JriQ"
  ],
  "contentType": "videos",
  "maxVideosPerChannel": 5,
  "maxAgeDays": 30,
  "onlyNew": false
}
```

| Field | Description |
|---|---|
| `channels` | Channel URLs (`/@handle`, `/channel/UC...`, `/c/name`, `/user/name`), `@handles` or `UC...` IDs |
| `contentType` | `all` (default), `videos` (no Shorts), `shorts`, `live` (past live streams) |
| `maxVideosPerChannel` | 1–15 (the RSS feed holds the 15 latest uploads) |
| `maxAgeDays` | Only videos published in the last N days (0 = no filter) |
| `onlyNew` | Only output videos not returned in previous runs (for scheduled runs). `monitoringMode` is the older name and still works |
| `firstRunOutputsAll` | With `onlyNew`, also output current videos on the first run (default: no, just save a baseline) |
| `stateStoreName` | Name of the key-value store holding the seen videos (one per watch list) |

### Output example

One dataset item per video:

```json
{
  "videoId": "aNI2jv7lBPQ",
  "url": "https://www.youtube.com/shorts/aNI2jv7lBPQ",
  "title": "Giving $10,000 To A Random Subscriber",
  "description": "",
  "publishedAt": "2026-10-09T16:00:01Z",
  "updatedAt": "2026-10-13T09:10:32Z",
  "views": 27748638,
  "likes": 817728,
  "thumbnailUrl": "https://i3.ytimg.com/vi/aNI2jv7lBPQ/hqdefault.jpg",
  "isShort": true,
  "channelId": "UCX6OQ3DkcsbYNE6H8uQQuVA",
  "channelTitle": "MrBeast",
  "channelUrl": "https://www.youtube.com/channel/UCX6OQ3DkcsbYNE6H8uQQuVA",
  "channelHandle": "@MrBeast",
  "position": 1,
  "contentType": "all",
  "isNew": null,
  "input": "https://www.youtube.com/@MrBeast",
  "feedSource": "channel",
  "publishedTimeText": null,
  "dateIsApproximate": false,
  "markdown": "## Giving $10,000 To A Random Subscriber\n\nChannel: MrBeast | Published: 2026-10-09T16:00:01Z | Views: 27748638 | Likes: 817728 | Type: Short\nURL: https://www.youtube.com/shorts/aNI2jv7lBPQ",
  "scrapedAt": "2026-10-15T08:00:00Z"
}
```

`isNew` is `true` with `onlyNew`, `null` otherwise. `markdown` is a compact block (description capped at 1,500 characters) ready to paste into a prompt or index as a RAG chunk. A `SUMMARY` record in the run's key-value store lists the channels processed, the source used (`channelsBySource`), the inputs that failed and why, and monitoring stats.

### Use cases

#### 1. Daily competitor watch for a YouTube agency

A channel manager follows 40 competitor channels and wants every new long-form video in a Google Sheet each morning, to brief scriptwriters on trending topics.

Input (scheduled daily at 7:00):

```json
{ "channels": ["@mkbhd", "@LinusTechTips", "@UnboxTherapy"], "contentType": "videos", "onlyNew": true }
```

Output (extract):

```json
[{ "channelTitle": "Marques Brownlee", "title": "iPhone 18 Pro Review: ...", "publishedAt": "2026-10-26T14:00:05Z", "views": 1843211, "url": "https://www.youtube.com/watch?v=...", "isNew": true }]
```

Next: the Google Sheets integration appends the rows; ~40 channels × ~1 video/day ≈ 40 videos ≈ **$0.01/day**.

#### 2. Influencer shortlist check before a campaign

An influencer-marketing manager vets 150 creators: posting frequency and recent views on the last 10 videos.

Input:

```json
{ "channels": ["https://www.youtube.com/@veritasium", "UCsBjURrPoezykLs9EqgamOA", "..."], "maxVideosPerChannel": 10, "maxAgeDays": 90 }
```

Output (extract):

```json
[{ "channelTitle": "Fireship", "title": "...", "publishedAt": "2026-10-20T17:12:01Z", "views": 612004, "likes": 31877 }]
```

Next: a pivot table gives average views per video and uploads per month per creator. 150 × 10 = 1,500 videos ≈ **$0.36**.

#### 3. AI news digest for a media team

An editor runs an AI agent that summarizes what 25 news and brand channels published in the last 24 hours.

Input:

```json
{ "channels": ["@BBCNews", "@CNBCtelevision", "@Bloomberg"], "contentType": "all", "maxAgeDays": 1, "maxVideosPerChannel": 15 }
```

Output (extract):

```json
[{ "channelTitle": "BBC News", "markdown": "## ...\n\nChannel: BBC News | Published: 2026-10-27T06:30:00Z | Views: 40211 | Type: video\nURL: ...", "isShort": false }]
```

Next: the `markdown` fields are concatenated into the LLM prompt; ~200 videos/day ≈ **$0.05/day**.

#### Call it from the API

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<USERNAME>/youtube-channel-rss").call(run_input={
    "channels": ["@mkbhd", "UCBJycsmduvYEL83R_U4JriQ"], "maxVideosPerChannel": 5,
})
for video in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(video["publishedAt"], video["title"], video["views"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('<USERNAME>/youtube-channel-rss').call({
    channels: ['@mkbhd', 'UCBJycsmduvYEL83R_U4JriQ'], maxVideosPerChannel: 5,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((v) => `${v.publishedAt} ${v.title}`));
```

#### Automation example (Make, n8n or Zapier)

Create an Apify **Schedule** (e.g. every hour) with `"onlyNew": true`. In Make or Zapier, use the Apify trigger **"Actor run finished"**, then **"Get dataset items"**, then send each new video to Slack, Discord, Notion or Google Sheets. In n8n, use the Apify node the same way. Runs with no new upload cost nothing in results.

### Use with AI agents (MCP)

The Actor is available as a tool through the Apify MCP server, so Claude, Cursor, ChatGPT and other AI agents can call it directly: give it a `channels` list, get flat JSON back. Use the `markdown` field as context for summaries, digests or alerts ("what did these 20 channels publish this week?"). It is cheap enough for agents to call often.

### Integrations

- **Apify API** — run synchronously and get the dataset in JSON, CSV or Excel in one call.
- **Make, Zapier, n8n** — trigger a scenario on each run with new videos.
- **Google Sheets** — append new uploads to a sheet automatically.
- **Webhooks / Slack / email** — notify on "run succeeded" when `onlyNew` found something.

### How to monitor new videos

1. Turn on **Only new videos (`onlyNew`)** and add your channels.
2. Run once: a baseline of current videos is saved (no results, no charge).
3. Create a **Schedule** (e.g. every hour). Each run outputs only new uploads, flagged `isNew: true`.
4. Add an integration or webhook to push new videos wherever you need.

Use a different `stateStoreName` for each independent watch list.

### FAQ

**Do I need a YouTube account or API key?** No. Only public data is used: no login, no API key, no daily quota.

**Why at most 15 videos per channel?** The official RSS feed contains the 15 latest uploads. That's ideal for monitoring; for a full back-catalog use a full channel crawler.

**YouTube's RSS feed returns 404 for my channel — will it work?** Yes. YouTube sometimes refuses its feed to cloud servers. The Actor retries, tries the uploads playlist feed and a proxy, then reads the channel's Videos tab instead. Check `feedSource` to see which source was used.

**Are view and like counts exact?** They come from the feed and can lag a little behind the live counter. When the channel page fallback is used, views are those displayed by YouTube (rounded for Shorts, e.g. "1.2M") and likes are empty. Dislikes are not available.

**Are Shorts included?** Yes by default, flagged with `isShort`. Choose `videos` to exclude them or `shorts` to get only Shorts.

**Does it need a proxy?** No configuration needed. Requests go out directly; if YouTube refuses them, the Actor automatically falls back to a proxy. The cost is included in the price.

**What if a channel fails?** It is skipped with a clear log message and listed in the `SUMMARY` record; the other channels continue and you are not charged for it. The run only fails if no channel at all could be read.

**What happens when my maximum cost per run is reached?** The run stops cleanly with a status message. Videos not delivered are not charged and, with `onlyNew`, are not marked as seen, so the next run picks them up.

### Limits

- Max 15 latest uploads per channel; no comments, tags, duration or subscriber count.
- With the channel page fallback: approximate dates (`dateIsApproximate: true`), short description snippet, no likes; Shorts have no date (so `maxAgeDays` skips them).
- Video URLs are not accepted as input — give the channel.
- Private, deleted or terminated channels return nothing (reported in `SUMMARY`, not charged).
- The `live` filter returns past live streams only (no "currently live" detection).
- Up to 5,000 channels per run.

# Actor input Schema

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

One channel per line. Accepted formats: channel URL (https://www.youtube.com/@MrBeast, /channel/UC..., /c/name, /user/name), @handle, or channel ID starting with UC. Video URLs are not accepted.

## `contentType` (type: `string`):

Which uploads to return. 'Long videos only', 'Shorts only' and 'Past live streams only' use the channel's dedicated upload feeds (or its Videos / Shorts / Live tab when the feed is unavailable), so you still get up to 15 items of that type.

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

Maximum number of videos returned per channel. The official YouTube RSS feed contains the 15 most recent uploads, so 15 is the maximum.

## `maxAgeDays` (type: `integer`):

Skip videos published more than N days ago. 0 = no date filter.

## `onlyNew` (type: `boolean`):

Remember the videos already returned (in a named key-value store) and only output videos that were not seen in previous runs. Schedule the Actor (e.g. every hour) to get a feed of new uploads. You only pay for new videos; a run with no new upload costs nothing in results.

## `monitoringMode` (type: `boolean`):

Older name of 'Only new videos', kept so existing schedules and API calls keep working. Turning on either option enables monitoring.

## `firstRunOutputsAll` (type: `boolean`):

Only used with 'Only new videos'. If off (default), the first run for a channel just saves its current videos as a baseline (nothing output, nothing charged) and later runs return only new uploads. If on, the first run returns the current videos too.

## `stateStoreName` (type: `string`):

Name of the key-value store that keeps the already-seen videos. Use a different name for each independent watch list.

## `maxConcurrency` (type: `integer`):

How many channels are fetched at the same time.

## `allowResidentialFallback` (type: `boolean`):

Requests go out directly first, then through the Apify datacenter proxy if YouTube refuses the feed (404/403/429). If even that fails, a residential proxy is used for the light RSS/JSON requests only (never full pages). Its cost is included in the price per video, never billed separately.

## `proxyConfiguration` (type: `object`):

Leave empty for automatic handling (recommended). If set, this proxy is used for every request.

## Actor input object example

```json
{
  "channels": [
    "https://www.youtube.com/@MrBeast",
    "@mkbhd",
    "UCBJycsmduvYEL83R_U4JriQ"
  ],
  "contentType": "all",
  "maxVideosPerChannel": 5,
  "maxAgeDays": 0,
  "onlyNew": false,
  "monitoringMode": false,
  "firstRunOutputsAll": false,
  "stateStoreName": "youtube-channel-rss-state",
  "maxConcurrency": 5,
  "allowResidentialFallback": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One item per video

## `summary` (type: `string`):

Channels processed, failed inputs with reasons, monitoring stats

# 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": [
        "https://www.youtube.com/@MrBeast",
        "@mkbhd",
        "UCBJycsmduvYEL83R_U4JriQ"
    ],
    "contentType": "all",
    "maxVideosPerChannel": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("actose/youtube-channel-rss").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": [
        "https://www.youtube.com/@MrBeast",
        "@mkbhd",
        "UCBJycsmduvYEL83R_U4JriQ",
    ],
    "contentType": "all",
    "maxVideosPerChannel": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("actose/youtube-channel-rss").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": [
    "https://www.youtube.com/@MrBeast",
    "@mkbhd",
    "UCBJycsmduvYEL83R_U4JriQ"
  ],
  "contentType": "all",
  "maxVideosPerChannel": 5
}' |
apify call actose/youtube-channel-rss --silent --output-dataset

```

## MCP server setup

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

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/2Yp7otk1O1zfD7Ouz/builds/awtegA04bGgAcIEO2/openapi.json
