YouTube Playlist Scraper - Publish Dates & Full Video Stats
Pricing
$19.99/month + usage
YouTube Playlist Scraper - Publish Dates & Full Video Stats
Extract all videos from any YouTube playlist, including titles, URLs, thumbnails, durations, descriptions, and metadata. Perfect for research, content audits, SEO analysis, archiving, and dataset creation. Fast, reliable, and ideal for automating playlist data collection.
Pricing
$19.99/month + usage
Rating
0.0
(0)
Developer
Scraper Engine
Maintained by CommunityActor stats
0
Bookmarked
43
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
YouTube Playlist Scraper — Publish Dates, Exact Views and Category
YouTube Playlist Scraper reads every video in a playlist and enriches each row with watch-page data the playlist listing never shows: publishDate and uploadDate as ISO-8601 timestamps, viewCountExact as a real integer, category, isLiveContent, and the full description. Output is structured JSON — no HTML, no selectors, no parsing. Below you will find exactly which keys every row carries, what each enrichment costs in requests, and where the real ceilings sit.
What is YouTube Playlist Scraper - Publish Dates & Full Video Stats?
It is an Apify Actor that turns a YouTube playlist into a video dataset and then makes a second, per-video request to attach precise publish dates and exact statistics to each row. The plain playlist page only exposes a rounded view string ("5.7K views") and a relative age ("2 years ago"); this Actor replaces both with machine-readable values pulled straight from YouTube's own video metadata.
No YouTube account, Google login, YouTube Data API key or browser is required. Everything returned is what a signed-out visitor can see. It is built for developers, data teams, content analysts and AI engineers who need dates they can sort on and view counts they can sum.
What YouTube playlist and video data is publicly available to scrape?
A public playlist exposes its video list, and each of those videos exposes its own publication metadata and view count without a sign-in. What YouTube does not expose publicly is anything that belongs to the channel owner's analytics.
| Data category | Public on YouTube | Gated behind sign-in or channel ownership |
|---|---|---|
| Video title, ID, watch URL, duration, thumbnail | Yes | No |
| Publish and upload date, exact view count, category, live flag | Yes | No |
| Full video description | Yes | No |
| Uploader keyword tags | Sometimes — many videos carry none and YouTube omits them from some responses | No |
| Like count | Approximate only, as rendered on the like button | Exact figure — channel owner, in YouTube Studio |
| Dislike count | No — removed from public view in 2021 | Channel owner |
| Watch time, impressions, audience retention, traffic sources | No | Channel owner, in YouTube Studio |
| Private and unlisted playlist contents | No | Sign-in plus a direct link or permission |
YouTube Playlist Scraper - Publish Dates & Full Video Stats only returns publicly visible data — what any visitor sees. Nothing behind a login wall.
What data can I extract with YouTube Playlist Scraper - Publish Dates & Full Video Stats?
Every dataset row is one video, carrying its playlist listing fields, its watch-page statistics, and nested channel and playlist objects.
| Field name | Description |
|---|---|
videoId | YouTube video ID — stable key for diffing runs |
title | Video title as displayed in the playlist |
videoUrl | Full https://www.youtube.com/watch?v=... URL |
duration | Runtime badge text, e.g. 18:42 |
durationLabel | Accessible display form, e.g. 18 minutes, 42 seconds |
isPlayable | Boolean set by the row builder; always true on emitted rows |
thumbnail.url | Highest-resolution thumbnail. A literal dotted key, not a nested object |
viewCount | Rounded view string from the listing, e.g. 142,318 views. Conditional — see below |
videoInfo | The listing's combined views-and-relative-age string, e.g. 142,318 views • 8 months ago |
channel.name / channel.id / channel.url | Publishing channel's public identity, nested on every row |
playlistInfo.playlistId / .playlistUrl / .playlistTitle | Parent playlist identity |
playlistInfo.playlistDescription / .owner / .lastUpdated | Playlist description, owner name and last-updated string when YouTube's sidebar exposes them |
playlistInfo.videoCount / .totalVideosInPlaylist / .totalDuration / .totalDurationMinutes | Playlist size and runtime counters — see the limits section before relying on these |
extractedAt | UTC ISO timestamp of collection, stamped per row |
publishDate | ISO-8601 publication timestamp from YouTube's video microformat, e.g. 2021-06-17T10:46:54-07:00 |
uploadDate | ISO-8601 upload timestamp from the same microformat |
viewCountExact | View count as an integer, converted from YouTube's own integer string |
category | YouTube category, e.g. Music, Education, Science & Technology |
isLiveContent | Boolean — whether the item is or was a live stream |
statsAvailable | Boolean — whether the per-video lookup returned usable data |
description | Full description text, when includeDescription is on |
tags / tagsAvailable | Uploader keyword array plus a flag marking empties, when includeTags is on |
likesApprox / likesAreApproximate | Approximate like count plus its honesty flag, when includeApproxLikes is on |
Publish dates are real timestamps, not parsed relative strings
publishDate and uploadDate are read from playerMicroformatRenderer in YouTube's own video metadata and written into the row untouched. They are not derived from the listing's "8 months ago" text, and nothing is rounded, inferred or reconstructed. The relative string is kept separately in videoInfo so you can see both, but only publishDate is a date you can sort, filter and store.
The cost is one extra request per video. The Actor fetches the playlist page once, then makes one additional metadata request for each video it enriches — so a run over 100 videos issues 1 playlist request plus 100 video requests. Turning includeApproxLikes on adds a second request per video on top of that.
What "full video stats" covers — and what is derived
Published by YouTube and passed through unchanged: publishDate, uploadDate, category, isLiveContent, description, tags. viewCountExact is YouTube's own view figure converted from string to integer — exact, not estimated.
One field is derived and labelled as such. likesApprox is parsed from the like button's accessibility text and expanded from YouTube's shorthand, so 12K becomes 12000. Every row that carries it also carries likesAreApproximate: true. Exact like counts are not public and are not shipped. Comment counts are not returned at all — this Actor makes no comment request.
Two conditional-key behaviours worth coding for
viewCount is written only when YouTube exposes a rounded count for that video in the playlist listing. With includeVideoDetails on it is omitted from the row entirely rather than set to null or 0 — a fabricated zero would silently corrupt any average you computed. Read it with a default: video.get("viewCount"). With includeVideoDetails off, the slim projection writes the key explicitly, so it appears as null instead of vanishing.
includeVideoDetails also toggles a whole block of fields. On, the row carries thumbnail.url, videoInfo, durationLabel, the full channel and playlistInfo objects and extractedAt. Off, the row reduces to videoId, title, videoUrl, duration, viewCount, channel.name and playlistInfo.playlistTitle — the watch-page statistics are still attached either way.
Need more YouTube data?
Four companion Scraper Engine Actors cover the rest of the platform. YouTube Video Details Scraper goes deep on a single video rather than a playlist. YouTube Search Scraper returns search result sets across videos, channels and playlists. YouTube Channel Finder resolves channels from keywords or URLs. YouTube Community Posts Scraper collects the community tab with polls and engagement.
How does this Actor differ from the official YouTube Data API?
The YouTube Data API v3 is public, documented, and genuinely covers playlists — for some jobs it is the right choice. The differences that matter are setup, input shape, and which statistics each route can reach.
| Feature | YouTube Data API v3 | YouTube Playlist Scraper - Publish Dates & Full Video Stats |
|---|---|---|
| Google Cloud project and API key | Required | ❌ Not required |
| Daily quota governs usage | Yes — verify current quota costs against Google's published YouTube Data API documentation | ❌ Apify usage only |
| Exact like count | Documented in the API's video statistics resource — verify against Google's current documentation | ❌ Approximate only, as likesApprox |
| Comment count | Documented in the API's video statistics resource | ❌ Not returned |
Accepts a channel @handle as input | ❌ Needs resolved playlist or channel IDs | ✅ Handle accepted, playlists discovered from it |
| Video, channel and playlist context in one row | ❌ Separate endpoint calls to stitch together | ✅ Joined on every row |
| Output shape | Per-endpoint schemas | ✅ One normalized row schema |
Use the official API when you need exact like or comment counts, authenticated operations on your own channel, or guaranteed terms-of-service alignment for a shipped product. Use this Actor when you want playlist contents with real publish dates and integer view counts without a Google Cloud project, when your input is a handle or a URL rather than a resolved ID, and when you want the video, its statistics, its channel and its playlist in a single row. Verify every API constraint against Google's current published YouTube Data API documentation before committing to either route.
How to use YouTube Playlist Scraper - Publish Dates & Full Video Stats
The Actor runs on Apify. Start it from the Apify Console, or call it through the Apify API with your Apify token — there is no separate signup and no other credential.
- Open the Actor on its Apify Store listing and click Try for free
- Paste one or more entries into Playlists / channels to scan (
playlistInputs) — this is the only required input. Use full playlist URLs, or a channel@handle. A run started with an empty list logs a warning and exits immediately without pushing or charging anything. - Set Videos to enrich per playlist (
maxVideos). The default is10;0means every video - Leave Fetch watch-page stats (
fetchVideoStats) on — it is what producespublishDate,viewCountExact,categoryandisLiveContent. AddincludeTagsorincludeApproxLikesif you need them - Click Start, then export as JSON, CSV or Excel, or read the dataset through the Apify API
How to scale to bulk playlist extraction
playlistInputs is an array, so a single run can take many playlists at once — each entry is processed in turn and every video is pushed to the dataset in real time as it is enriched. maxVideos applies per playlist, not per run: five playlist URLs with maxVideos: 100 can return up to 500 rows. A channel @handle expands further — the Actor opens that channel's playlists page, collects up to 10 playlist links from it, and processes the first 5, so one handle with maxVideos: 50 can reach 250 rows. Videos are not deduplicated across playlists: a video appearing in two of them produces two rows.
What can you do with YouTube playlist video data?
- 📈 A content strategist auditing a competitor's tutorial series uses
publishDateandviewCountExactto plot publishing cadence against traction, andcategoryto confirm how YouTube classifies each upload. - 🔎 A media researcher building a reproducible corpus uses
publishDateto window a playlist to a date range andextractedAtto stamp the snapshot, so the sample frame can be defended and re-run later. - 🎬 A video editor scoping a re-cut uses
duration,isLiveContentanddurationLabelto separate edited uploads from archived live streams before pulling source material. - 🤖 An AI engineer building a RAG index over a course playlist embeds
titleplusdescriptionas the chunk text and attachespublishDate,channel.nameandplaylistInfo.playlistTitleas metadata, so an agent can answer "which lessons on authentication were published after March, and how long are they" against live catalogue data. - 📊 A growth analyst tracking a series over time re-runs the same playlist weekly and diffs
viewCountExactpervideoIdto measure velocity rather than the roundedviewCountstring, which is too coarse to subtract.
Because the Actor is callable over HTTP through the Apify API, any agent framework can invoke it as a tool and receive typed JSON back with no parsing step.
How does YouTube Playlist Scraper handle rate limits and blocking?
The Actor manages its own network escalation, and you do not configure or rotate anything. Playlist page requests start direct with no proxy — the fastest and cheapest path. If that returns nothing usable, it escalates to an Apify datacenter proxy, and if that also fails, to Apify residential proxies with three attempts and exponential backoff between them. Once a run has escalated to residential it stays there for the remaining playlists rather than falling back down. Every request uses a 30-second total timeout, and connections are pooled at 10 concurrent sockets.
Per-video statistics requests take a different path, because YouTube's logged-out watch page is bot-walled from proxy IPs. The Actor asks YouTube's own metadata endpoint using a cascade of three mobile clients in order, rotating to a fresh residential exit for each video. The first client returns the full microformat with dates and category; the two fallbacks bypass stubborn blocks but return statistics without the dates.
There is no browser, no CAPTCHA solving and no login. If every client fails for a video, the stat fields are set to null and statsAvailable is false — nothing is invented. If a whole playlist fails after the full ladder, it is logged as failed and produces no rows.
⚠️ Limits, caps and known behaviour
Documented plainly so nothing surprises you mid-run.
maxVideosaccepts up to 1000, but the real ceiling is around 100 per playlist. The Actor reads the playlist page once and does not follow YouTube's continuation tokens, so only the videos in that first payload are ever seen. Videos beyond it produce no row and cost nothing.statsAvailable: truedoes not guarantee a date. The flag is set when either a view count or a publish date came back. If a fallback client answered, you getviewCountExact,description,tagsandisLiveContentwithpublishDate,uploadDateandcategorystillnull. TestpublishDate is not Nonewhen the date is what you need.proxyConfigurationdoes not change routing. The Actor runs its own direct → datacenter → residential ladder regardless of the groups or country you select, and the per-video statistics requests always use residential exits. The parameter is accepted, and the setting is logged, but it does not override the ladder.- A raw playlist ID on its own does not work, despite the parameter description mentioning it. Any bare token with no slash and no
httpis treated as a channel handle and rewritten to a/@name/playlistsURL. Paste the fullhttps://www.youtube.com/playlist?list=...URL instead. - Which playlists a
@handlereturns is not stable. Discovered playlist links are deduplicated through an unordered set before being capped at 10 and truncated to the first 5, so repeat runs on the same handle may pick a different five. - Search keywords are not supported. A plain word is classified as a channel handle, not a search query, and resolves only if a channel with that handle exists.
playlistInfo.videoCount,.totalVideosInPlaylist,.totalDurationand.totalDurationMinutescarry seeded fallback values (10,0,58 minutes,58) that are only overwritten when YouTube's older sidebar layout is present in the page. Treat them as unreliable and count dataset rows instead.includeDescription,includeTagsandincludeApproxLikesare ignored whenfetchVideoStatsis off. With the master switch off, no per-video request is made at all and the row is a plain playlist listing row.- Every pushed row is charged. See the Output section for exactly what that means.
⬇️ Input
All eight parameters below are read directly from the Actor's input schema. playlistInputs is the only required one.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
playlistInputs | Yes | array | Playlist URLs or channel @handles, one entry each. Minimum 1 item. A watch URL carrying a list= query parameter is also accepted and resolved to its playlist. | ["https://www.youtube.com/playlist?list=PLObrtcm1Kw6Odq5ks2R3bbJUGVVwQF-vw"] |
maxVideos | No | integer | Videos read and enriched per playlist. 0 means every video. Minimum 0, maximum 1000. Default 10. | 100 |
fetchVideoStats | No | boolean | Master switch for per-video enrichment. On, each video gets one extra metadata request adding publishDate, uploadDate, viewCountExact, category, isLiveContent and statsAvailable. Default true. | true |
includeDescription | No | boolean | Add the full description text. Requires fetchVideoStats on. Default true. | true |
includeTags | No | boolean | Add uploader keyword tags plus a tagsAvailable flag. Requires fetchVideoStats on. Default false. | false |
includeApproxLikes | No | boolean | Add likesApprox and likesAreApproximate. Costs a second request per video. Requires fetchVideoStats on. Default false. | false |
includeVideoDetails | No | boolean | On, rows carry thumbnail.url, videoInfo, durationLabel, the full channel and playlistInfo objects and extractedAt. Off, a slim base row. Default true. | true |
proxyConfiguration | No | object | Apify Proxy settings. Accepted, but the Actor applies its own direct → datacenter → residential ladder regardless. Default {"useApifyProxy": false}. | {"useApifyProxy": false} |
Common pitfall: setting maxVideos to 0 expecting zero results. 0 means no limit — it takes the whole playlist. Use 1 for a single-video smoke test.
Example input
{"playlistInputs": ["https://www.youtube.com/playlist?list=PLObrtcm1Kw6Odq5ks2R3bbJUGVVwQF-vw","@GoogleDevelopers"],"maxVideos": 100,"fetchVideoStats": true,"includeDescription": true,"includeTags": true,"includeApproxLikes": true,"includeVideoDetails": true,"proxyConfiguration": { "useApifyProxy": false }}
⬆️ Output
One row per video, with a consistent schema across runs. Export as JSON, CSV or Excel, or read the dataset through the Apify API. The Actor pushes each row in real time as it is enriched, so results appear while the run is still going.
Billing: every row pushed to the dataset is charged as one row_result event, and that is the only push the Actor makes. There are no separate error rows, no diagnostic rows and no accounting rows — nothing is pushed uncharged, so there is no filter expression to exclude. This matters for one case in particular: a video whose statistics lookup fails is still pushed and still charged. It arrives with its base listing fields intact, the stat fields null and statsAvailable: false. Playlists that fail entirely push nothing and cost nothing, and videos past the page ceiling are never fetched.
Example output
{"thumbnail.url": "https://i.ytimg.com/vi/lL2ZwXj1tXM/maxresdefault.jpg","title": "Build a REST API with FastAPI — Part 3: Authentication","videoUrl": "https://www.youtube.com/watch?v=lL2ZwXj1tXM","videoId": "lL2ZwXj1tXM","duration": "18:42","durationLabel": "18 minutes, 42 seconds","isPlayable": true,"channel": {"name": "Google Developers","id": "GoogleDevelopers","url": "https://www.youtube.com/@GoogleDevelopers"},"videoInfo": "142,318 views • 8 months ago","viewCount": "142,318 views","playlistInfo": {"playlistId": "PLObrtcm1Kw6Odq5ks2R3bbJUGVVwQF-vw","playlistUrl": "https://www.youtube.com/playlist?list=PLObrtcm1Kw6Odq5ks2R3bbJUGVVwQF-vw","playlistTitle": "FastAPI from Scratch","playlistDescription": "A complete build-along series covering routing, models and auth.","lastUpdated": "Last updated on Mar 14, 2026","owner": "Google Developers","videoCount": 10,"totalVideosInPlaylist": 0,"totalDuration": "58 minutes","totalDurationMinutes": 58},"extractedAt": "2026-07-25T09:14:02.481932Z","publishDate": "2025-11-08T09:00:04-08:00","uploadDate": "2025-11-08T09:00:04-08:00","viewCountExact": 142318,"category": "Science & Technology","isLiveContent": false,"statsAvailable": true,"description": "In part 3 we add OAuth2 password flow, hash passwords with passlib, and issue JWTs...","tags": ["fastapi", "python", "rest api", "authentication", "jwt"],"tagsAvailable": true,"likesApprox": 12000,"likesAreApproximate": true}
With includeVideoDetails set to false, the row reduces to videoId, title, videoUrl, duration, viewCount, channel.name and playlistInfo.playlistTitle, still carrying all of the watch-page statistics above.
How does it work?
The Actor requests the public playlist page once, with an English-language and US-region preference and a consent cookie so YouTube serves the real page data rather than a consent interstitial. It reads the embedded playlist payload and walks it into one record per video, handling both YouTube's older playlist layout and the current one so a front-end change on YouTube's side does not empty your dataset.
Each video record is then enriched with a second request to YouTube's own public metadata endpoint, which is where the publish date, integer view count, category, live flag, description and keyword tags come from. That request rotates to a fresh residential exit per video and tries three mobile client identities in order until one answers.
Only publicly visible data is returned — no account, no login, no API key. Field names and types are held stable across updates, so your integration keeps reading the same keys regardless of how YouTube restructures its front end.
Integrations
The Actor runs on Apify, so it works with anything that can call the Apify API or consume an Apify dataset — your own code, no-code automation platforms, and agent frameworks.
Calling the Actor programmatically
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("<YOUR_USERNAME>/youtube-playlist-scraper-publish-dates-full-video-stats").call(run_input={"playlistInputs": ["https://www.youtube.com/playlist?list=PLObrtcm1Kw6Odq5ks2R3bbJUGVVwQF-vw"],"maxVideos": 100,"fetchVideoStats": True,"includeDescription": True,})for video in client.dataset(run["defaultDatasetId"]).iterate_items():if video.get("publishDate"): # null when only a fallback client answeredprint(video["publishDate"], video["viewCountExact"], video["title"])
Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request.
No-code tools (n8n, Make, LangChain)
In n8n, use the Apify node, or an HTTP Request node pointed at the Apify run endpoint with your token, and pass the same JSON input shown above; dataset items come back ready to map into the next node. In Make, the Apify module exposes run-and-wait, so a playlist sweep can feed a Google Sheets or Airtable step without code. In LangChain, wrap the run endpoint as a tool and hand the agent the returned rows directly — title, description and publishDate need no preprocessing before they enter a prompt or a vector store.
Is it legal to scrape YouTube playlists?
Scraping publicly available playlist and video metadata is generally lawful, and this Actor collects only what a signed-out visitor sees — no account, no login, no API key.
The output is content and channel metadata rather than personal data: video titles, durations, publish dates, view counts, categories, descriptions, playlist names and the publishing channel's public identity. No viewer information, comments, subscriber lists or watch history is collected, so GDPR and comparable personal-data regimes do not attach to this output the way they would to a profile scraper. The obligations that do apply are contractual — YouTube's terms of service — and copyright-related if you republish titles, thumbnails or descriptions as your own catalogue. One nuance on the channel object: an independent creator's channel is an individual's public identity, while an organisation's channel is not personal data at all, so treat the two differently if you store channel.name at scale.
Consult legal counsel if your use case involves bulk storage of personal data.
❓ Frequently asked questions
What YouTube video fields does this Actor return?
publishDate, viewCountExact, category, isLiveContent and description are the five that distinguish it, on top of the standard listing fields videoId, title, videoUrl, duration and thumbnail.url, plus nested channel and playlistInfo objects. The full list is in the data fields section above.
Does it require a YouTube account, Google login or API key?
No. No YouTube account, no Google Cloud project, no YouTube Data API key and no browser. The only credential involved is your Apify token, used to start the run.
Are the publish dates real timestamps, or parsed from "8 months ago"?
Real timestamps. publishDate and uploadDate come from YouTube's own video microformat as ISO-8601 values with a timezone offset, and are written into the row exactly as received. Nothing is derived from the relative age string — that string is preserved separately in videoInfo so you can compare the two. This is the whole reason the Actor makes a second request per video.
How many videos can I extract in one run, and can I scrape several playlists at once?
Yes to several playlists — playlistInputs is an array and each entry is processed in turn. maxVideos caps videos per playlist, not per run, so three playlists at maxVideos: 100 can return up to 300 rows. The practical ceiling per playlist is around 100 videos, because the Actor reads the playlist page once without following continuation tokens.
What happens if a video is private, deleted or region-blocked mid-playlist?
It depends on whether YouTube still lists it. A video YouTube has dropped from the playlist payload produces no row at all, and the run continues with the rest. A video still listed but not retrievable — private, removed, region-blocked or age-gated — still produces a row: base listing fields intact, publishDate, uploadDate, viewCountExact and category set to null, and statsAvailable: false. That row is pushed and charged like any other, so filter on statsAvailable in your own code if you only want enriched records. Because videoId is stable, diffing today's run against a stored one tells you exactly which videos left the playlist.
Why does viewCount disappear from some rows while viewCountExact is present?
Because they come from different places. viewCount is the rounded string from the playlist listing, written only when YouTube renders one — with includeVideoDetails on it is omitted rather than set to null or 0. viewCountExact is the integer from the video's own metadata and is the field to sum, sort or subtract. Read the string one defensively with video.get("viewCount").
Does it return exact like counts or comment counts?
No to both, deliberately. YouTube removed public exact like counts in 2021, so likesApprox is parsed from the like button and expanded from shorthand — 12K becomes 12000 — and every row carrying it also carries likesAreApproximate: true. Comment counts are not fetched at all. Checked on the Apify Store on 25 July 2026, lurkapi/youtube-channel-videos-stats-scraper documents a paid add-on returning likeCount and commentCount; if exact engagement numbers are the requirement, that is the honest comparison to make.
Does it work with Claude, ChatGPT and other AI agent tools?
Yes. It is callable as a standard HTTP endpoint through the Apify API, so LangChain, CrewAI, n8n or a hand-written tool definition can invoke it and receive typed JSON. No parsing step is needed before a row enters an LLM context window.
How does it compare to other YouTube playlist scrapers?
Checked on the Apify Store on 25 July 2026: apidojo/youtube-playlist-scraper documents a field-availability table listing id, title, url, views, likes, duration, channel.id, channel.name, thumbnails and isLive as always present, with description and keywords as sometimes present — no publish-date field appears in that table or in its sample output. apidojo/youtube-scraper-api is a broader multi-surface YouTube Actor whose video output does document publishDate in ISO-8601 form. lurkapi/youtube-channel-videos-stats-scraper is channel-first and states that its free publishedText field is relative, with an exact publishedDate available through a paid Video Stats add-on. This Actor is narrower on purpose: playlist input, an ISO-8601 publishDate and an integer viewCountExact on every row by default, with the per-video request cost stated up front.
Does it return data LLMs can use directly, and which fields suit RAG?
Yes — typed, normalized JSON with stable field names, no HTML and no selectors. For RAG indexing, description and title are the high-information text fields to embed, with publishDate, category, channel.name and playlistInfo.playlistTitle as filterable metadata. For training data and time-series work, videoId, publishDate, viewCountExact, duration and isLiveContent are the most consistently structured across records, all returned as typed primitives.
What happens when YouTube changes its layout, and do I have to manage proxies?
The Actor is maintained and the output schema is held stable across updates — field names and types do not change on your end. It already parses both YouTube's older playlist layout and the current one. On proxies: no, you manage nothing. The direct → datacenter → residential ladder runs automatically, including per-video residential rotation for the statistics requests, with no proxy account and no IP rotation on your side.
🔗 Related scrapers
| Scraper name | What it extracts |
|---|---|
| YouTube Video Details Scraper | Full metadata for individual videos rather than a playlist |
| YouTube Search Scraper | Search result sets across videos, channels and playlists |
| YouTube Channel Finder | Channel discovery by keyword or URL |
| YouTube Community Posts Scraper | Community tab posts, polls and engagement |
| YouTube Shorts Scraper With Creator Lead Enrichment | Shorts plus creator contact enrichment |
| Google Search Autocomplete Scraper — YouTube Suggestions | YouTube autocomplete suggestions for keyword research |
💬 Your feedback
Found a bug, or missing a field YouTube exposes that is not in the output? Open an issue on the Actor's Issues tab. Reports that include the exact input JSON and the playlist URL are the fastest to reproduce and fix.