# YouTube Playlists Scraper (`beautifulscrape/youtube-playlists`) Actor

Extract playlists from YouTube channels and expand each playlist into its videos. Accepts channel URLs/handles and direct playlist URLs.

- **URL**: https://apify.com/beautifulscrape/youtube-playlists.md
- **Developed by:** [Beautiful Scrape](https://apify.com/beautifulscrape) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 results

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

## What is YouTube Playlists Scraper?

YouTube Playlists Scraper lets you extract playlists from YouTube channels and expand each playlist into its videos — helping you analyze curated content, track series, and gather playlist engagement data with just a few clicks.

**Discover channel playlists**: list every playlist on a channel's Playlists tab
**Expand playlist contents**: get each video inside a playlist with title, duration, views, and position
**Scrape direct playlist URLs**: process individual playlists without needing the channel tab
**Analyze curated content**: understand how creators organize videos into playlists and series
**Automate playlist collection**: replace manual browsing with repeatable workflows that keep datasets fresh and consistent

The scraper opens each channel's Playlists tab, discovers playlists, then expands each one into individual video rows with parent playlist metadata attached.

### What data does YouTube Playlists Scraper extract?

📝 **Title** - The video title

🆔 **Video ID** - The unique YouTube video ID

🔗 **URL** - Direct link to the video (includes playlist + index when available)

⏱️ **Duration** - Length of the video

👁️ **View Count** - Number of views on the video

📅 **Date** - Upload date when available

🖼️ **Thumbnail URL** - Thumbnail image for the video

📺 **Channel Name** - Name of the channel that owns the playlist

🌐 **Channel URL** - Link to the channel page

🆔 **Channel ID** - YouTube channel ID

📋 **Playlist Title** - Title of the parent playlist

🆔 **Playlist ID** - YouTube playlist ID

🔗 **Playlist URL** - Direct link to the playlist

🔢 **Playlist Video Count** - Number of videos in the playlist (when shown on the tab)

🔢 **Order** - 1-based position of the video in the playlist

🏷️ **Type** - Always `"video"` for items from this actor

### Features

For maximum usefulness, YouTube Playlists Scraper has the following abilities:

**List and expand**: discover playlists on a channel, then emit one row per video inside each playlist

**Flexible input**: scrape from channel handles/URLs and/or direct playlist URLs in one run

**Result limits**: control how many playlists per channel (`maxResultsPlaylists`) and how many videos per playlist (`maxResultsVideosPerPlaylist`)

**Automatic pagination**: handles Playlists tab continuation pages and playlist video enumeration

**Error resilience**: continues processing remaining inputs even if one fails

**Structured output**: export data in JSON, CSV, Excel, or HTML with a consistent schema

### ⬇️ Input

Provide at least one of: channels or playlist URLs. You can set up the input programmatically or use the fields in the Actor's interface.

#### Channels

You can provide one or more YouTube channels using the `channels` array. The actor opens each channel's Playlists tab.

**Supported channel formats**:

- Username: `MrBeastGaming`
- Handle: `@MrBeastGaming`
- Channel URL: `https://www.youtube.com/@MrBeastGaming`
- Playlists tab URL: `https://www.youtube.com/@MrBeastGaming/playlists`
- Channel ID URL: `https://www.youtube.com/channel/UCxxx`

#### Playlist URLs

Use `playlistUrls` to expand one or more playlists directly.

**Supported URL formats**:

- `https://www.youtube.com/playlist?list=PLxxxxxxxx`

#### Input Parameters

Provide **at least one** of:

- `channels` (array) - Channel usernames or URLs
- `playlistUrls` (array) - Direct playlist URLs

**Optional:**

- `maxResultsPlaylists` (integer, default: 10) - Max playlists to discover per channel
- `maxResultsVideosPerPlaylist` (integer, default: 50) - Max videos to expand per playlist

#### Example Input (channels)

```json
{
  "channels": ["MrBeastGaming"],
  "maxResultsPlaylists": 5,
  "maxResultsVideosPerPlaylist": 20
}
```

#### Example Input (direct playlist)

```json
{
  "playlistUrls": [
    "https://www.youtube.com/playlist?list=PLnYX1qinc5ASs-gDN960p3yo_YOYvialR"
  ],
  "maxResultsVideosPerPlaylist": 10
}
```

#### Example Input (combined)

```json
{
  "channels": ["MrBeastGaming"],
  "playlistUrls": [
    "https://www.youtube.com/playlist?list=PLnYX1qinc5ASs-gDN960p3yo_YOYvialR"
  ],
  "maxResultsPlaylists": 2,
  "maxResultsVideosPerPlaylist": 10
}
```

### ⬆️ Output

The results will be wrapped into a dataset which you can find in the Output or Storage tab. Note that the output is organized in tables and tabs for viewing convenience. You can view results as a table, JSON, or other formats.

Once the run is finished, you can also download the dataset in various data formats (JSON, CSV, Excel, XML, HTML). Before exporting, you can pick or omit specific output fields.

**Important:** the actor does **not** emit one row per playlist. It emits **one row per video** inside each discovered/expanded playlist, with playlist metadata attached.

#### JSON Output

Here's an example of the data structure for a single video inside a playlist:

```json
{
  "id": "PRp5Y543LN0",
  "title": "Exploring My Abandoned Minecraft Server",
  "url": "https://www.youtube.com/watch?v=PRp5Y543LN0&list=PLnYX1qinc5AQUsQ6YCCV_Shtil7zSNThB&index=1",
  "duration": "19:45",
  "viewCount": 72000000,
  "date": null,
  "type": "video",
  "thumbnailUrl": "https://i.ytimg.com/vi/PRp5Y543LN0/hqdefault.jpg",
  "playlistId": "PLnYX1qinc5AQUsQ6YCCV_Shtil7zSNThB",
  "playlistTitle": "Shorts",
  "playlistUrl": "https://www.youtube.com/playlist?list=PLnYX1qinc5AQUsQ6YCCV_Shtil7zSNThB",
  "playlistVideoCount": 3,
  "channelName": "MrBeast Gaming",
  "channelUrl": "https://www.youtube.com/channel/UCIPPMRA040LQr5QPyJEbmXA",
  "channelId": "UCIPPMRA040LQr5QPyJEbmXA",
  "fromYTUrl": "https://www.youtube.com/playlist?list=PLnYX1qinc5AQUsQ6YCCV_Shtil7zSNThB",
  "order": 1,
  "input": "MrBeastGaming"
}
```

#### Output Fields

| Field | Type | Description |
|-------|------|-------------|
| `title` | string | null | The video title |
| `type` | string | Always `"video"` |
| `id` | string | The unique YouTube video ID |
| `url` | string | Direct link to the video (with playlist context when available) |
| `thumbnailUrl` | string | null | Thumbnail image URL |
| `viewCount` | number | null | Number of views on the video |
| `date` | string | null | Upload date (ISO format) when available |
| `duration` | string | null | Length of the video |
| `playlistId` | string | null | YouTube playlist ID |
| `playlistTitle` | string | null | Title of the parent playlist |
| `playlistUrl` | string | null | Direct link to the playlist |
| `playlistVideoCount` | number | null | Number of videos in the playlist |
| `channelName` | string | null | Name of the channel |
| `channelUrl` | string | null | Link to the channel page |
| `channelId` | string | null | YouTube channel ID |
| `fromYTUrl` | string | The playlist URL that was expanded |
| `order` | number | 1-based position in the playlist |
| `input` | string | Original input value (channel or playlist URL) |

### Error items

When the scraper cannot retrieve data for a given input — for example a channel does not exist or a playlist has no videos — it pushes an error item to the dataset instead of silently skipping it. Normal output items are never affected; you can tell them apart by the presence of an `error` field.

#### Error item structure

```json
{
  "url": "https://www.youtube.com/@somechannel",
  "input": "somechannel",
  "error": "CHANNEL_HAS_NO_PLAYLISTS",
  "note": "Channel exists but has no playlists"
}
```

#### Error codes reference

| Error code | Meaning |
|---|---|
| `CHANNEL_DOES_NOT_EXIST` | Channel URL points to a channel that does not exist |
| `CHANNEL_HAS_NO_PLAYLISTS` | Channel exists but has no playlists |
| `NO_VIDEOS` | Playlist exists but has no videos |
| `NOT_FOUND` | Page or playlist was not found |
| `INVALID_INPUT` | Actor failed due to bad configuration or a malformed URL |

# Actor input Schema

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

Channel usernames (with or without @) or channel URLs. The actor opens each channel's Playlists tab.

## `playlistUrls` (type: `array`):

Direct YouTube playlist URLs (e.g. https://www.youtube.com/playlist?list=PLxxx).

## `maxResultsPlaylists` (type: `integer`):

Maximum number of playlists to discover from each channel's Playlists tab.

## `maxResultsVideosPerPlaylist` (type: `integer`):

Maximum number of videos to expand from each playlist.

## Actor input object example

```json
{
  "channels": [
    "MrBeastGaming"
  ],
  "maxResultsPlaylists": 10,
  "maxResultsVideosPerPlaylist": 50
}
```

# Actor output Schema

## `results` (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": [
        "MrBeastGaming"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("beautifulscrape/youtube-playlists").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": ["MrBeastGaming"] }

# Run the Actor and wait for it to finish
run = client.actor("beautifulscrape/youtube-playlists").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": [
    "MrBeastGaming"
  ]
}' |
apify call beautifulscrape/youtube-playlists --silent --output-dataset

```

## MCP server setup

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

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/33MymmNrL5VBc66xj/builds/6ns63Ng1c9TC2lqNc/openapi.json
