YouTube Channel Videos Scraper — Metadata & Metrics avatar

YouTube Channel Videos Scraper — Metadata & Metrics

Pricing

from $5.00 / 1,000 video scrapeds

Go to Apify Store
YouTube Channel Videos Scraper — Metadata & Metrics

YouTube Channel Videos Scraper — Metadata & Metrics

Scrape public YouTube channel videos and Shorts with titles, descriptions, dates, views, likes, comments, duration, thumbnails, and channel metadata. No cookies required.

Pricing

from $5.00 / 1,000 video scrapeds

Rating

0.0

(0)

Developer

Khadin Akbar

Khadin Akbar

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

2 days ago

Last modified

Share

YouTube Channel Videos Scraper

Turn known YouTube channels into a clean, analysis-ready inventory of public videos and Shorts. Give the Actor channel URLs, @handles, or channel IDs; it returns one validated dataset row per video with its URL, title, description, publish time, duration, thumbnail, public engagement metrics, channel identity, and collection provenance.

This YouTube channel video scraper is for a precise job: you already know which channels matter and need their recent or popular public content as structured data. It does not require your YouTube cookies, Google login, browser session, or personal YouTube API key.

Use the prefilled Actor input page when you want to verify one channel with a bounded 10-video run.

Decide in 30 seconds

Your jobUse this Actor?Recommended route
Export videos or Shorts from known channelsYesAdd channel URLs or handles to channelUrls.
Monitor new uploads from a fixed creator or competitor listYesUse sortBy: "latest" and a bounded date window.
Compare public views, likes, comments, duration, and posting patternsYesKeep maxTotalVideos small first, then export the dataset.
Discover channels from a topic or keywordNot firstStart with YouTube Search Scraper, then pass its channelUrl or channelId values here.
Collect comments after selecting videosNot directlySend this Actor's videoUrl or videoId values to YouTube Comments Scraper.
Download media, audio, captions, or transcriptsNoUse a purpose-built downloader or transcript Actor.
Access private, deleted, age-gated, or login-only contentNoThose surfaces are outside this Actor's public-data scope.

A real workflow: from channel list to editorial decision

Imagine a content strategist starts Monday with 12 competitor channels and one question: “What did they publish in the last 30 days, and which formats earned visible engagement?” Search results are the wrong source because ranking changes by query, location, and personalization. The strategist already has the channel list.

They run this Actor with contentType: "all", a start date, maxVideosPerChannel: 25, and a whole-run cap. The dataset becomes the evidence table: titles show recurring themes, durationSeconds separates short and long formats, publishedAt reveals cadence, and the public metric fields support a current-snapshot comparison. When a high-interest video needs audience analysis, its videoUrl flows directly into the comments Actor. The decision is no longer based on opening 12 channel tabs by hand.

That workflow is intentionally bounded. It does not pretend a public metric snapshot is historical performance data, and it does not interpret a missing like count as zero.

What one dataset row contains

Each row represents one public long-form video or YouTube Short. The flat record works in CSV, JSON, spreadsheets, BI tools, databases, Make, n8n, and AI-agent pipelines.

Field groupFieldsWhat it answers
Video identityvideoId, videoUrl, title, descriptionWhat is the item and where is its public page?
Channel identitychannelId, channelHandle, channelName, channelUrl, channelSubscriberCountWhich channel published it?
Time and formatpublishedAt, durationSeconds, durationText, contentType, isShort, isLive, isUpcomingWhen and in what format was it published?
Public metricsviewCount, likeCount, commentCount, engagementRateWhat visible engagement snapshot did the provider return?
Media and labelsthumbnailUrl, badges, genreWhat display and classification metadata is available?
Provenanceprovider, input, sortBy, resultPosition, page, scrapedAtHow, where, and when was the row collected?

engagementRate is calculated as (likeCount + commentCount) / viewCount only when all three usable public counts exist and views are greater than zero. If YouTube or the provider omits a count, the Actor omits the rate instead of understating it.

Optional fields vary by video, channel, region, and provider response. Missing data stays missing; the Actor does not invent placeholder values or write error rows into the dataset.

Quick start recipes

Recipe 1: ten recent long-form videos

Use this first to verify the channel and inspect the output shape at a bounded cost.

{
"channelUrls": ["https://www.youtube.com/@MrBeast"],
"contentType": "videos",
"maxVideosPerChannel": 10,
"maxPagesPerContentType": 1,
"maxTotalVideos": 10,
"sortBy": "latest"
}

Recipe 2: recent uploads across a reporting window

publishedAfter is inclusive; publishedBefore is exclusive. Both accept real UTC calendar dates in YYYY-MM-DD form.

{
"channelUrls": [
"https://www.youtube.com/@TED",
"https://www.youtube.com/@NASA"
],
"contentType": "all",
"maxVideosPerChannel": 25,
"maxPagesPerContentType": 2,
"maxTotalVideos": 50,
"sortBy": "latest",
"publishedAfter": "2026-06-01",
"publishedBefore": "2026-07-01"
}

When contentType is all, the long-form feed is processed before the Shorts feed and both share the per-channel cap. Raise maxVideosPerChannel if you need room for both formats.

{
"channelUrls": ["UCX6OQ3DkcsbYNE6H8uQQuVA"],
"contentType": "shorts",
"maxVideosPerChannel": 20,
"maxPagesPerContentType": 2,
"maxTotalVideos": 20,
"sortBy": "popular"
}

Provider rankings can differ slightly. Treat popular as the selected provider's current feed order, not as an immutable YouTube-wide ranking.

Input reference and cost controls

InputType and defaultUse it forImportant boundary
channelUrlsarray, requiredChannel URLs, @handles, or IDs beginning UC1–100 entries; video and playlist URLs are rejected.
contentTypevideosvideos, shorts, or allall shares one per-channel result cap.
maxVideosPerChannelinteger, 50Cap saved rows for each channel1–500.
maxPagesPerContentTypeinteger, 10Bound provider pagination per selected feed1–50; this is not a row count.
maxTotalVideosinteger, 500Cap all saved and billable rows in the run1–5,000; strongest whole-run event-cost control.
sortBylatestRequest recent-first or popularity-oriented orderinglatest or popular.
publishedAfteromittedKeep records on or after a UTC dateReal YYYY-MM-DD date; rows without a machine-readable date are excluded.
publishedBeforeomittedKeep records before a UTC dateExclusive upper bound; must be later than publishedAfter.
providerOrderscrapecreators-firstSelect fallback order or isolate a provider for diagnosisSingle-provider modes remove fallback resilience.
includeRawDatafalseDiagnose provider field driftAdds a capped raw object and makes rows less convenient for agents and sheets.

API inputs are validated without coercion. For example, "10" is not accepted where the schema declares the integer 10, "true" is not accepted as a boolean, and a rollover date such as 2025-02-30 is rejected. This keeps UI, API, and agent behavior consistent.

Output example

{
"recordType": "video",
"contentType": "videos",
"provider": "scrapecreators",
"input": "https://www.youtube.com/@MrBeast",
"channelId": "UCX6OQ3DkcsbYNE6H8uQQuVA",
"channelHandle": "MrBeast",
"channelName": "MrBeast",
"channelUrl": "https://www.youtube.com/@MrBeast",
"videoId": "xvFZjo5PgG0",
"videoUrl": "https://www.youtube.com/watch?v=xvFZjo5PgG0",
"title": "A public video title",
"description": "A public video description returned by the provider.",
"publishedAt": "2026-07-01T00:00:00.000Z",
"durationSeconds": 823,
"durationText": "13:43",
"thumbnailUrl": "https://i.ytimg.com/vi/xvFZjo5PgG0/maxresdefault.jpg",
"viewCount": 23456789,
"likeCount": 1200000,
"commentCount": 18342,
"engagementRate": 0.0519,
"isShort": false,
"sortBy": "latest",
"resultPosition": 1,
"page": 1,
"scrapedAt": "2026-07-18T12:00:00.000Z"
}

The default key-value store also contains:

  • OUTPUT: compact terminal outcome, row and charge counts, cost figures, memory allocation, and warnings.
  • RUN_SUMMARY: detailed input, providers, attempts, status codes, pagination, filters, validation, billing, and stop reason.

Use the dataset for records and OUTPUT for orchestration. Do not infer success from an HTTP or Actor run status alone.

Run outcomes for automations and AI agents

OutcomeTransport stateMeaningRecommended agent action
COMPLETEsucceededRequested bounded work completed without recorded data-quality warningsConsume rows.
PARTIALsucceededUsable rows exist, but a route, validation, write, or event-cap warning occurredConsume with warnings; decide whether to retry the missing scope.
VALID_EMPTYsucceededThe request was valid but no matching public rows were available, or the event cap prevented provider workCheck dates, channel availability, and stopReason; do not invent rows.
INVALID_INPUTsucceededInput type, value, date, or channel reference was invalidCorrect the named field; do not retry unchanged.
CONFIG_ERRORfailedOwner-managed provider credentials or internal configuration prevented workEscalate; changing channel input will not fix it.
UPSTREAM_FAILEDfailedEvery configured provider route failed before a usable row was savedRetry with backoff or use a diagnostic provider mode.

Continuation tokens are provider-specific and remain internal. There is no public resume-token input. To bound or deepen a run, change maxPagesPerContentType, maxVideosPerChannel, and maxTotalVideos; never copy a continuation token between providers.

Pricing with worked examples

This Actor uses Pay per event + Apify platform usage.

EventPriceWhen it is charged
apify-actor-start$0.00005One event per allocated GB or part thereof, with a one-event minimum.
video-scraped$0.005Once for each validated video or Short successfully persisted to the dataset.

At the default 512 MB allocation, the start event count is one:

A bounded run of 10 records costs $0.05005 in named event charges at that memory allocation.

  • 1 saved video: 1 × $0.00005 + 1 × $0.005 = $0.00505
  • 10 saved records: 1 × $0.00005 + 10 × $0.005 = $0.05005
  • 50 saved videos: 1 × $0.00005 + 50 × $0.005 = $0.25005

At 4 GB, 10 saved videos cost 4 × $0.00005 + 10 × $0.005 = $0.05020 in event charges. Apify compute, storage, network, and any proxy usage are additional. The Actor reports both the maximum bounded event estimate before provider work and actual named-event counts afterward.

Set maxTotalVideos before increasing page depth. A date filter can reduce saved rows and event charges, but provider pages still use compute and provider capacity while the Actor looks for matching dates.

Use through the API

cURL

Keep the token in an environment variable and send it in the authorization header, not in a URL.

curl -X POST \
'https://api.apify.com/v2/acts/khadinakbar~youtube-channel-videos-scraper/runs?waitForFinish=60' \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"channelUrls": ["https://www.youtube.com/@TED"],
"contentType": "videos",
"maxVideosPerChannel": 10,
"maxPagesPerContentType": 1,
"maxTotalVideos": 10,
"sortBy": "latest"
}'

Read data.defaultDatasetId for rows and data.defaultKeyValueStoreId for OUTPUT and RUN_SUMMARY. If the run is still active after the wait window, poll the run endpoint before reading evidence.

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('khadinakbar/youtube-channel-videos-scraper').call({
channelUrls: ['https://www.youtube.com/@TED'],
contentType: 'all',
maxVideosPerChannel: 20,
maxPagesPerContentType: 2,
maxTotalVideos: 20,
sortBy: 'latest'
});
const [{ items }, output] = await Promise.all([
client.dataset(run.defaultDatasetId).listItems(),
client.keyValueStore(run.defaultKeyValueStoreId).getRecord('OUTPUT')
]);
console.log(output?.value?.outcome, items.length);

Python

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("khadinakbar/youtube-channel-videos-scraper").call(run_input={
"channelUrls": ["https://www.youtube.com/@TED"],
"contentType": "videos",
"maxVideosPerChannel": 10,
"maxPagesPerContentType": 1,
"maxTotalVideos": 10,
"sortBy": "latest",
})
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())
output = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("OUTPUT")
print(output["value"]["outcome"], len(rows))

Agent and MCP prompt card

When this Actor is exposed through Apify's Actors MCP server, route a request here only if the user provides known channels or channel identifiers.

Agent prompt: Collect 10 recent videos from the supplied channel, inspect OUTPUT, return warnings for PARTIAL, and report VALID_EMPTY without inventing data.

Use khadinakbar--youtube-channel-videos-scraper to collect up to 10 recent
long-form videos from https://www.youtube.com/@TED. Set one provider page and
a whole-run cap of 10. Return videoId, videoUrl, title, publishedAt,
durationSeconds, viewCount, likeCount, and commentCount. Then inspect OUTPUT.
If outcome is PARTIAL, explain the warnings. If VALID_EMPTY, say that no matching
public rows were returned. Never substitute made-up metrics or retry invalid input.

Agent routing contract:

  • Required entity: at least one known public channel URL, @handle, or channel ID.
  • Output entity: one public video or Short per dataset row.
  • Freshness: scrapedAt is collection time; public metrics are a snapshot, not a time series.
  • Side effects: starts a paid Actor run and may persist billable dataset rows.
  • Cost controls: set row and page caps explicitly.
  • Failure inspection: read OUTPUT, then RUN_SUMMARY when the outcome is not COMPLETE.
  • Pagination: controlled by bounded inputs; no cross-provider continuation token is exposed.

Limits, recovery, and honest expectations

SymptomLikely reasonRecovery
Fewer rows than expectedDate filter, duplicate IDs, missing dates, public availability, or result capsInspect RUN_SUMMARY, then widen one boundary deliberately.
No rows with VALID_EMPTYValid channel but no matching public items, or event cap blocked workCheck stopReason, dates, content type, and charge cap.
PARTIAL with dataA provider route failed or a row could not be validated/persistedKeep usable rows, inspect warnings, and retry only the missing scope.
Provider-specific failureCredential rejection, throttling, timeout, or upstream shape changeRestore default fallback order; use an *-only mode only for diagnosis.
Different order between runsPublic feeds and provider ordering changedTreat resultPosition as run-scoped, not permanent rank.
Missing public countsYouTube/provider did not expose them for that itemPreserve nullability; do not convert missing values to zero.

The Actor retries transient request failures and can fall back between two owner-managed public-data providers. Provider continuation tokens are opaque and are never forwarded across providers. It deduplicates video IDs across inputs and selected feed types, validates a complete record before persistence, and couples each successful dataset write to the video-scraped event.

No scraper can guarantee an exhaustive historical archive of YouTube. Deleted, private, restricted, unavailable, or provider-omitted videos may not appear. Public counts can change immediately after collection.

Verification snapshot

On 2026-07-18, the Actor was fresh-pulled from live build 1.3.1 and rebuilt through v1.4. Local validation finished with 32 passing tests, 95.65% helper-module line coverage, 85.15% branch coverage, valid Apify schemas, clean syntax checks, and an npm audit with zero known vulnerabilities. The review caught and fixed cross-provider continuation-token reuse, permissive API coercion, invalid calendar-date rollover, memory-insensitive start estimates, incomplete engagement-rate semantics, ambiguous bare video IDs, an SDK charge-limit state that could disagree with the persisted dataset, and a 4 GB MCP run whose platform-expanded start count was larger than the SDK's explicit-call count.

Build 1.4.3 completed a reviewed 26/26 REST acceptance matrix with zero unexpected failures at 512 MB. A separate real Actors MCP call against build 1.4.4 at 4 GB then found a semantic reporting defect that the REST matrix could not expose: Apify correctly expanded one explicit apify-actor-start call to four billable start events, while the old OUTPUT reported one. Build 1.4.5 is the corrected release target and must independently pass the full 26-case REST matrix, a real 4 GB MCP call, the live-release verifier, and a fresh source readback before handoff. The pinned run IDs live in the release evidence rather than being hidden behind an aggregate success claim.

This is engineering evidence, not a claim that YouTube or either upstream provider will always return every field. Final cloud acceptance evidence is tied to the deployed build and its pinned run IDs rather than inferred from a SUCCEEDED transport status.

Responsible use

Use this Actor for public YouTube metadata you are permitted to process. You are responsible for applicable law, YouTube terms, privacy obligations, contractual restrictions, and content rights. Do not use it to access private data, evade controls, identify sensitive individuals, or redistribute copyrighted media without permission. Apply appropriate retention, access, and deletion controls to exported datasets.

Frequently asked questions

Does it download YouTube videos or audio?

No. It returns structured public metadata and metric snapshots, not media files, audio, captions, or transcripts.

Does it need my YouTube API key or cookies?

No. Provider credentials are managed by the Actor owner. Users provide channel references and limits, not personal YouTube credentials.

Can it find channels for a topic?

This Actor expects known channels. Use youtube-search-scraper for keyword discovery, then map its channelUrl or channelId output into channelUrls here.

How do I collect comments from the returned videos?

Pass each videoUrl to startUrls, or each videoId to videoIds, in youtube-comments-scraper. This is a schema-confirmed downstream handoff, not a generic cross-link.

Why can engagement rate be absent?

The rate requires views, likes, and comments. If any public count is unavailable, omitting the derived rate is more accurate than treating the missing count as zero.