YouTube Channel Videos Scraper
Pricing
from $5.00 / 1,000 video scrapeds
YouTube Channel Videos Scraper
Export every uploaded video from any public YouTube channel into clean, structured dataset rows — video ID, title, view count, published time, duration, thumbnail. Devil Scrapes walks the channel's own paginated video grid so your pipeline doesn't break when YouTube reshuffles its layout.
Pricing
from $5.00 / 1,000 video scrapeds
Rating
0.0
(0)
Developer
DevilScrapes
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 hours ago
Last modified
Categories
Share
🎯 What this scrapes
A YouTube channel's /videos tab ships its first ~30 uploads inline in a ytInitialData blob, then hides the rest behind a continuation token buried in the page — the same token shape that moves every few WEB-client releases. We find that token wherever YouTube nests it this month with a generic recursive search, page through /youtubei/v1/browse for the rest, and turn every upload into one clean dataset row with title, views, duration, publish time, and the highest-resolution thumbnail.
🔥 What we handle for you
- 🛡️ Browser fingerprint rotation —
curl-cffiimpersonates real Chrome / Firefox / Safari TLS handshakes so the target sees a browser, not Python. - 🌐 Residential proxy rotation via Apify Proxy — fresh session and exit IP on every block.
- 🔁 Retries with exponential backoff on
408 / 429 / 5xx— up to 5 attempts per page,Retry-Afterhonoured. - 🧱 Rate-limit-aware pacing — when the target pushes back, we slow down instead of getting banned.
- 🧊 Clean, typed dataset rows — Pydantic-validated, ISO-8601 timestamps, stable IDs, JSON / CSV / Excel export straight from the Apify Console.
- 💰 Pay-Per-Event pricing — you only pay for results that hit your dataset. No data, no charge.
💡 Use cases
- Competitor/content research — pull a competitor channel's full upload history to study cadence, titling, and view performance over time.
- Creator analytics — build per-channel dashboards of view counts and publish cadence without babysitting the YouTube UI.
- Video-inventory pipelines — feed a downstream catalog, recommender, or archive with a channel's canonical video list, IDs, and thumbnails.
- Trend tracking — snapshot a set of channels on a schedule to watch view-count growth and publishing frequency shift over time.
⚙️ How to use it
- Click Try for free at the top of the page.
- Fill in the input form — most fields have sensible defaults.
- Click Start. Output streams into the run's dataset.
- Export from Storage → Dataset as JSON, CSV, or Excel — or fetch via the API.
📥 Input
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
channels | array | yes | ['@mkbhd'] | YouTube channel handles, bare handles, or full channel URLs (e.g. @mkbhd, mkbhd,… |
maxVideos | integer | no | 30 | Stop paging once this many videos have been emitted for a single channel (1–5000). Set above ~30 to force a second… |
hl | string | no | 'en' | YouTube UI language passthrough — affects relative-timestamp text like "3 days ago". Example: en. |
gl | string | no | 'US' | YouTube UI country/region passthrough. Example: US. |
proxyConfiguration | object | no | {'useApifyProxy': True} | Apify Proxy configuration. Recon confirmed byte-identical channel-page payloads across datacenter and residential exits… |
Example input
{"channels": ["@mkbhd","@veritasium"],"maxVideos": 45,"hl": "en","gl": "US","proxyConfiguration": {"useApifyProxy": true}}
📤 Output
Every row is one dataset item.
| Field | Type | Notes |
|---|---|---|
channel_handle | string | Normalised @handle of the channel this video belongs to. |
video_id | string | 11-character YouTube video ID. |
title | string | Video title at scrape time. |
view_count | integer | Parsed view count. 0 when absent or unparseable. |
published_time | string | YouTube's relative publish string (e.g. '3 days ago'), verbatim — no absolute-timestamp resolution. |
duration_text | string | Verbatim duration text (e.g. '12:34'). Null for live streams/premieres. |
duration_seconds | integer | Duration parsed to seconds. Null alongside duration_text for live/premiere videos. |
thumbnail_url | string | Highest-resolution thumbnail URL available. |
Example output
{"channel_handle": "@mkbhd","video_id": "dQw4w9WgXcQ","title": "This Changes Everything","view_count": 4213098,"published_time": "3 days ago","duration_text": "12:34","duration_seconds": 754,"thumbnail_url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg"}
💰 Pricing
Pay-Per-Event — you pay only when these events fire:
| Event | USD | What it is |
|---|---|---|
actor-start | $0.2 | One-off warm-up charge per run |
video-scraped | $0.005 | PPE event |
Example: 1 000 results at the rates above ≈ $5.20. No subscription, no minimum, no card to start — Apify gives every new account $5 of free credit.
🚧 Limitations
Public channels only — the /videos tab, not Shorts or Live. No channel-metadata row (subscribers, banner, description) — video rows only. No absolute-timestamp resolution for publish dates. YouTube's internal payload shape can shift between web-client releases; we walk it with a generic recursive search rather than a fixed path, but a structural change may still need a same-day patch.
❓ FAQ
Does this scrape Shorts or Live tabs?
No — v1 covers the standard /videos tab only (regular uploads). Shorts and Live listings are out of scope for this release.
Does it return channel-level metadata like subscriber count?
No — this Actor returns video rows only, not a channel-metadata row (subscribers, banner, description).
Why is published_time a string like '3 days ago' instead of a date?
That's what YouTube's own channel page returns — it does not expose an absolute timestamp here. We pass it through verbatim rather than guessing at a conversion.
What happens if a channel has zero videos?
The run still succeeds — a legitimately empty channel returns zero rows for that channel and the final status message reports it separately from a failed/degraded fetch.
What happens if a channel handle is invalid or the channel is private?
That single channel is skipped and counted as failed in the run summary; every other channel in the same run still completes.
💬 Your feedback
Spotted a bug, hit a weird edge case, or need a new field? Open an issue on the Actor's Issues tab on Apify Console — we ship fixes weekly and we read every report.