YouTube Search Scraper By Upload Date, Duration & Type
Pricing
from $5.99 / 1,000 results
YouTube Search Scraper By Upload Date, Duration & Type
Extract YouTube search result data in seconds. Gather video titles, links, channels, view counts, thumbnails, and upload dates from keyword searches to power research, trend analysis, or content monitoring workflows.
Pricing
from $5.99 / 1,000 results
Rating
0.0
(0)
Developer
Scrapier
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
YouTube Search Scraper — Verified Upload Date & Duration Filters
YouTube Search Scraper runs a real YouTube search for every term you supply and returns typed video, channel or playlist rows — title, view count, duration, channel identity, live status and more — as structured JSON. Every filter (upload-date window, video length, subtitles, Creative Commons, live-now, sort order) is encoded into YouTube's own sp= search parameter and was measured against a live result set, not just wired to a form field. Each row is ready to pass to an LLM, load into a spreadsheet, or feed into a monitoring pipeline. Point it at a keyword — not a URL — and it hands back what a browser would show.
What is YouTube Search Scraper By Upload Date, Duration & Type?
YouTube Search Scraper By Upload Date, Duration & Type queries youtube.com/results for each search term you give it and returns one typed row per result — video, channel or playlist — as normalized JSON. Its defining trait is that every filter it exposes was checked against a real, unfiltered search rather than assumed to work: "This week" returned a completely different set of videos than an unfiltered search (0 of 8 IDs in common), the subtitles filter changed the result set (only 4 of 8 IDs matched), and Creative Commons narrowed it to 0 of 8 shared IDs. No YouTube account, login, cookie or API key is required — the Actor reads the same public search results page any visitor sees.
Key capabilities:
- 🎬 Video, channel and playlist result rows, each with its own field set, selected with
resultKind - 🎛️ Five real search filters — sort order, upload-date window, video length, subtitles, Creative Commons — plus a live-now flag, all encoded in YouTube's actual
sp=protobuf parameter - ↕️ Re-sorting by view count or upload date after the fact, because YouTube's own
sort=date/sort=viewCountblends results back toward relevance rather than applying a strict order - 💸 Two extraction depths:
fullopens each result's own page for likes, comments, tags and exact timestamps through a residential proxy, orfastreads the search page only, with no proxy required - 📂 Optional one-request playlist enrichment for video count and owning channel, plus duplicate-ID dropping across YouTube's repeated result pages
What data can you get with YouTube Search Scraper?
resultKind decides which of four result types comes back: videos, channels, playlists, or — rarely populated by YouTube's own search — movies, which reuse the video row shape.
| Result Type | Extracted Fields | Primary Use Case |
|---|---|---|
| Video | title, viewCount, likes, commentsCount, duration, durationSeconds, publishedAt, liveStatus, availability, categories, language, keywords, hashtags, text, channelName, channelIsVerified, numberOfSubscribers, thumbnailUrl | Content research, video SEO tracking, trend and ranking monitoring |
| Channel | title, channelName, channelUsername, channelUrl, channelHandleUrl, numberOfSubscribers, channelIsVerified, thumbnailUrl, text | Creator and competitor discovery, influencer shortlisting |
| Playlist | title, playlistVideoCount, playlistOwnerName, playlistOwnerUrl, thumbnailUrl, text | Curated-content and niche-channel mapping |
| Movie | Same schema as video rows | Rarely returned by YouTube search; kept for input compatibility |
Verified search filters, not just declared ones
Every filter row in the schema carries an audit trail instead of a promise. Each pushed row records spParam — the exact base64 value sent to YouTube — appliedFilters, an object echoing every filter you set, and sortMode, a plain-English statement of what ordering was actually applied and why. That last field matters: requesting orderResultsBy = date at detailLevel = fast returns YouTube's blended order, because fast results carry no exact publish timestamp to re-sort by, and sortMode says so explicitly rather than silently returning the wrong order. orderResultsBy = rating is passed through to YouTube but is never re-sorted, because YouTube exposes no rating figure anywhere in the response payload.
{"resultKind": "video","searchRank": 3,"spParam": "EgQIAxAB","appliedFilters": {"sortBy": "relevance","uploadDate": "thisWeek","duration": null,"resultKind": "video","onlyWithSubtitles": false,"onlyCreativeCommons": false,"onlyLiveNow": false},"sortMode": "relevance (YouTube's native ordering, unchanged)","searchUrl": "https://www.youtube.com/results?search_query=cold+brew+review&sp=EgQIAxAB"}
Channel rows
Search with resultKind = channel and each row carries the channel's subscriber count, verification badge, handle (channelUsername) and both its canonical URL (channelUrl) and the raw uploader URL as YouTube returns it (channelHandleUrl). Useful for building a creator shortlist from a topic search without opening a single channel page by hand.
How does YouTube Search Scraper differ from the official YouTube Data API?
YouTube publishes an official search endpoint, search.list in the YouTube Data API v3, and it returns fewer fields per call than this Actor does at detailLevel = full.
| Feature | YouTube Data API v3 (search.list) | YouTube Search Scraper |
|---|---|---|
| Setup | Google Cloud project and API key required | Only an Apify account; no Google credentials |
| Results per call | maxResults 0–50, default 5; more pages need a nextPageToken and draw further quota | resultsPerTerm 1–2000 in a single run |
| Result types per call | video, channel and playlist together by default, or one via type | One resultKind per run, each with its own full row schema |
| Channel/playlist detail | Snippet only — subscriber count and playlist size need a separate channels/playlists call | numberOfSubscribers and playlistVideoCount/playlistOwnerName returned in the same run |
| Per-video detail | No likes, comment count or exact duration in the search snippet — needs a further videos.list call | likes, commentsCount and durationSeconds returned directly at detailLevel = full |
| Video length filter | videoDuration: any/short/medium/long, enum only | Same three bands, with measured real ranges: Short 66–144 s, Medium 247–1129 s, Long 3606–57468 s |
| Upload window | publishedAfter/publishedBefore accept exact RFC 3339 timestamps | Preset windows only — lastHour/today/thisWeek/thisMonth/thisYear |
(YouTube Data API v3 parameters as published at developers.google.com/youtube/v3/docs/search/list, checked 26 July 2026.)
The official API is the right choice when you need exact-timestamp date filtering or already manage a Google Cloud project and its quota. YouTube Search Scraper is the faster path when you want one Apify token, up to 2000 results per term, and channel or playlist detail without stitching together three separate API resources.
🧭 How to scrape YouTube with YouTube Search Scraper
- Open YouTube Search Scraper on the Apify Console and click Try for free
- Enter one or more terms into
searchTerms— the field that drives the run; nothing else is required - Set the real query controls that apply:
orderResultsBy,publishedWithin,videoLength,resultKind, and theonlyWithSubtitles/onlyCreativeCommons/onlyLiveNowtoggles - Click Start
- Download the dataset as JSON, CSV, Excel or open it through the Apify API
How to run multiple search terms in one job
searchTerms is an array — one term per line runs as one independent search, each recording which term produced every row in its input field. Terms are fetched with bounded internal concurrency (up to three in flight at once); this is not a configurable input, just how the run is scheduled internally.
⬇️ Input
Every parameter below is optional — required is empty in the schema — and every filter is encoded into the real sp= parameter described above.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
searchTerms | No | array | One search term per line, exactly as typed into YouTube's search box. Default ["python programming"]. Legacy key queries still accepted. | ["cold brew review"] |
resultsPerTerm | No | integer | Results to collect per term. Minimum 1, maximum 2000, default 10. At detailLevel = full each row costs roughly 587 KB of RESIDENTIAL proxy traffic. Legacy key maxResults still accepted. | 20 |
orderResultsBy | No | string | Ordering to request: relevance (default), date, viewCount, rating. viewCount is re-sorted by us into strict descending order; date is re-sorted only at detailLevel = full; rating cannot be verified. Legacy key sortBy still accepted. | viewCount |
publishedWithin | No | string | Upload window: "" (default, any time), lastHour, today, thisWeek, thisMonth, thisYear. Legacy key uploadDate still accepted. | thisWeek |
videoLength | No | string | Video length band: "" (default, any), short (under 4 min), medium (4–20 min), long (over 20 min). Video results only. Legacy key duration still accepted. | medium |
resultKind | No | string | Result type: video (default), channel, playlist, movie. Legacy key type still accepted. | video |
onlyWithSubtitles | No | boolean | Restrict to videos carrying closed captions. Default false. Video results only. | true |
onlyCreativeCommons | No | boolean | Restrict to Creative Commons–licensed videos. Default false. Video results only. | false |
onlyLiveNow | No | boolean | Restrict to streams currently broadcasting. Default false. Video results only. | false |
detailLevel | No | string | full (default) opens each result's own page for likes, comments, tags, timestamp, category and language, and requires a RESIDENTIAL proxy. fast reads the search page only, works without a proxy, at roughly 1/277th the traffic. | fast |
enrichPlaylistRows | No | boolean | Adds one extra ~2 KB request per playlist result to fill in playlistVideoCount and the owning channel. Default true. Ignored when not searching for playlists. | true |
dropDuplicateIds | No | boolean | Drops repeated IDs — YouTube repeats results across deep result pages (5 duplicates measured in 426 rows). Default true. | true |
proxyConfiguration | No | object | Apify Proxy configuration. Empty by default (useApifyProxy: false). detailLevel = full is bot-walled on datacenter IPs and automatically escalates to RESIDENTIAL if blocked. | {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]} |
verboseLogs | No | boolean | Logs every underlying search call, the exact sp= filter used, and each proxy step. Default false. Legacy key debug still accepted. | false |
Example input
{"searchTerms": ["cold brew review", "espresso machine comparison"],"resultsPerTerm": 25,"orderResultsBy": "viewCount","publishedWithin": "thisMonth","videoLength": "medium","resultKind": "video","onlyWithSubtitles": true,"detailLevel": "fast","dropDuplicateIds": true}
Common pitfall: an empty input still runs a search
searchTerms carries a schema default of ["python programming"], not just a form prefill. If you start a run through the Apify API with an empty input object ({}) rather than the Console form, the platform fills in that default before the run starts — the Actor genuinely searches "python programming" and you are billed row_result events for a query you never typed. If your integration always intends to supply its own terms, pass searchTerms explicitly on every call rather than relying on an empty body to fail safely; sending "searchTerms": [] does fail safely — the run pushes a single uncharged error row and exits. Separately, videoLength, onlyWithSubtitles, onlyCreativeCommons and onlyLiveNow only affect video results — set with resultKind = channel or playlist, they are silently ignored and the reason is written to the run log.
⬆️ Output
Every result is one dataset row of typed, normalized JSON with a consistent key set for its resultKind. Export as JSON, CSV, Excel or an RSS/XML feed, or read the dataset directly through the Apify API. Real search results are charged as row_result events; rows pushed with "type": "error" (no terms supplied, or a search that returned nothing) are not charged.
Scraped results
[{"type": "video","resultKind": "video","title": "Cold Brew Coffee: Full Review & Taste Test","id": "dQw4w9WgXcQ","url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ","input": "cold brew review","date": "2026-06-30T14:00:00Z","publishedAt": "2026-06-30T14:00:00Z","publishedAtEpoch": 1782914400,"text": "A full taste test of five cold brew concentrates, ranked by bitterness and cost per cup.","thumbnailUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg","hashtags": ["#coldbrew", "#coffee"],"keywords": ["cold brew", "coffee review", "taste test"],"channelName": "Brew Lab","channelId": "UCabc1234567890defghijk","channelUrl": "https://www.youtube.com/channel/UCabc1234567890defghijk","channelUsername": "@brewlab","channelIsVerified": false,"numberOfSubscribers": 84200,"viewCount": 152340,"likes": 6210,"commentsCount": 340,"commentsTurnedOff": false,"duration": "12:47","durationSeconds": 767,"liveStatus": "not_live","availability": "public","isMembersOnly": false,"categories": ["Howto & Style"],"language": "en","ageLimit": 0,"searchRank": 3,"order": 0,"spParam": "EgQIAxAB","appliedFilters": {"sortBy": "viewCount","uploadDate": "thisMonth","duration": "medium","resultKind": "video","onlyWithSubtitles": true,"onlyCreativeCommons": false,"onlyLiveNow": false},"sortMode": "viewCount (post-sorted by us, 25/25 rows had a view count)","detailLevel": "fast","searchUrl": "https://www.youtube.com/results?search_query=cold+brew+review&sp=EgQIAxAB","scrapedAt": "2026-07-26T09:12:04Z","runId": "aBcD1234EfGh5678"},{"type": "channel","resultKind": "channel","title": "Brew Lab","id": "UCabc1234567890defghijk","url": "https://www.youtube.com/channel/UCabc1234567890defghijk","input": "cold brew review","date": null,"text": "Coffee gear reviews and brewing science, weekly.","thumbnailUrl": "https://yt3.ggpht.com/abc123=s176-c-k-c0x00ffffff-no-rj","hashtags": [],"keywords": [],"channelName": "Brew Lab","channelId": "UCabc1234567890defghijk","channelUrl": "https://www.youtube.com/channel/UCabc1234567890defghijk","channelUsername": "@brewlab","channelHandleUrl": "https://www.youtube.com/@brewlab","channelIsVerified": false,"numberOfSubscribers": 84200,"viewCount": null,"likes": null,"commentsCount": null,"commentsTurnedOff": null,"duration": null,"isMembersOnly": null,"durationSeconds": null,"publishedAt": null,"publishedAtEpoch": null,"liveStatus": null,"availability": null,"categories": null,"language": null,"ageLimit": null,"searchRank": 1,"order": 1,"spParam": "EgQIAxAB","appliedFilters": {"sortBy": "viewCount","uploadDate": "thisMonth","duration": "medium","resultKind": "video","onlyWithSubtitles": true,"onlyCreativeCommons": false,"onlyLiveNow": false},"sortMode": "relevance (YouTube's native ordering, unchanged)","detailLevel": "fast","searchUrl": "https://www.youtube.com/results?search_query=cold+brew+review&sp=EgQIAxAB","scrapedAt": "2026-07-26T09:12:04Z","runId": "aBcD1234EfGh5678"},{"type": "playlist","resultKind": "playlist","title": "Cold Brew Reviews Playlist","id": "PLxyz9876543210abcdef","url": "https://www.youtube.com/playlist?list=PLxyz9876543210abcdef","input": "cold brew review","date": null,"text": "Every cold brew review from the channel, newest first.","thumbnailUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg","hashtags": [],"keywords": [],"channelName": "Brew Lab","channelId": "UCabc1234567890defghijk","channelUrl": "https://www.youtube.com/channel/UCabc1234567890defghijk","channelUsername": null,"numberOfSubscribers": null,"viewCount": null,"likes": null,"commentsCount": null,"commentsTurnedOff": null,"duration": null,"isMembersOnly": null,"durationSeconds": null,"publishedAt": null,"publishedAtEpoch": null,"channelIsVerified": null,"liveStatus": null,"availability": null,"categories": null,"language": null,"ageLimit": null,"playlistVideoCount": 14,"playlistOwnerName": "Brew Lab","playlistOwnerChannelId": "UCabc1234567890defghijk","playlistOwnerUrl": "https://www.youtube.com/channel/UCabc1234567890defghijk","searchRank": 2,"order": 2,"spParam": "EgQIAxAB","appliedFilters": {"sortBy": "viewCount","uploadDate": "thisMonth","duration": "medium","resultKind": "video","onlyWithSubtitles": true,"onlyCreativeCommons": false,"onlyLiveNow": false},"sortMode": "relevance (YouTube's native ordering, unchanged)","detailLevel": "fast","searchUrl": "https://www.youtube.com/results?search_query=cold+brew+review&sp=EgQIAxAB","scrapedAt": "2026-07-26T09:12:04Z","runId": "aBcD1234EfGh5678"}]
Every output field
| Field | Present on | Description |
|---|---|---|
type, resultKind | all | Row kind: video, channel or playlist. type mirrors resultKind for compatibility with earlier runs. |
title | all | Result title |
id | all | Video, channel or playlist ID |
url | all | Canonical URL for the result |
input | all | The search term that produced this row |
date, publishedAt | videos | Exact publish timestamp, ISO 8601 |
publishedAtEpoch | videos | Publish timestamp as Unix seconds |
text | all | Description (video/channel/playlist) |
thumbnailUrl | all | Highest-resolution thumbnail offered |
hashtags | videos | Hashtags parsed out of the description |
keywords | videos | Cleaned tag list (internal yt:-prefixed tags removed) |
channelName, channelId, channelUrl, channelUsername | all (channel identity on the row's own channel; on playlists, filled by enrichment) | Owning or represented channel |
channelHandleUrl | channels | Raw uploader URL as returned by the underlying extractor |
channelIsVerified | videos, channels | Verification badge |
numberOfSubscribers | channels always; videos when the data is present | Subscriber count |
viewCount | videos | View count |
likes | videos, at detailLevel = full | Like count |
commentsCount | videos, at detailLevel = full | Comment count |
commentsTurnedOff | videos, at detailLevel = full | true/false; null at fast depth, meaning "not fetched", not "disabled" |
duration | videos | Formatted length, h:mm:ss or m:ss |
durationSeconds | videos | Length in raw seconds |
isMembersOnly | videos | Derived from availability |
liveStatus | videos | e.g. is_live, not_live, was_live |
availability | videos | e.g. public, subscriber_only, premium_only |
categories | videos | YouTube category list |
language | videos | Detected/declared language |
ageLimit | videos | Age restriction, 0 if none |
playlistVideoCount | playlists, with enrichPlaylistRows on | Number of videos in the playlist |
playlistOwnerName, playlistOwnerChannelId, playlistOwnerUrl | playlists, with enrichPlaylistRows on | Owning channel of the playlist |
searchRank | all | YouTube's own position in the result page |
order | all | Row position after dedup and re-sorting |
spParam | all | The exact sp= value sent to YouTube for this search, or null |
appliedFilters | all | Object echoing sortBy, uploadDate, duration, resultKind, onlyWithSubtitles, onlyCreativeCommons, onlyLiveNow as applied |
sortMode | all | Plain-language statement of the ordering actually applied |
detailLevel | all | Extraction depth actually used for this row — channel and playlist results are always extracted flat regardless of the detailLevel you set, since fully resolving a channel or playlist would mean walking every video inside it |
searchUrl | all | Full YouTube search URL fetched, including the sp= filter |
scrapedAt | all | UTC timestamp the row was scraped |
runId | all, when available | Apify run ID |
error | error rows only | Failure reason; present only on uncharged rows |
How can I use the data extracted with YouTube Search Scraper?
- 📊 Video SEO and content teams pull
searchRank,viewCountandpublishedAtacross a keyword set to see which videos currently rank and how fast newer uploads are gaining views, informing which topics and formats to target next. - 🎥 Rights and production teams set
onlyCreativeCommons = trueto source reusable footage, then usechannelName,channelUrlandtextfor licensing attribution and outreach. - 🤖 AI engineers and LLM developers issue a query, receive typed video/channel/playlist JSON, and pass it straight into an agent's context — no HTML parsing step between the search and the model.
- 🔬 Market and competitive researchers run a channel search per topic and compare
numberOfSubscribersandchannelIsVerifiedacross results to map who currently owns a niche.
How do you monitor YouTube search rankings over time?
Rank monitoring is running the same search repeatedly and watching which video IDs move, appear, or disappear from the results — trustworthy here specifically because spParam and sortMode prove the same filter was applied on every run rather than YouTube silently changing what it served you. Diff two runs of the same searchTerms on id, searchRank and order to see who gained or lost position; diff on viewCount and numberOfSubscribers to see how fast a leading result is growing; watch for id values with no prior match to catch new uploads entering the result set.
A concrete loop: schedule a run across your keyword list, keep the previous run's dataset, and after each new run match rows by id within the same input term. Alert when a video's searchRank moves into your tracked range for the first time, when viewCount crosses a threshold between runs, or when a competitor's id appears where it wasn't before. Set orderResultsBy = viewCount for growth tracking specifically — it is the one ordering the Actor verifiably re-sorts into strict descending order, so the diff reflects real movement rather than YouTube's blended relevance.
Schedule the recurring runs with Apify's own Schedule feature from the Actor's page, and use a webhook on run completion to push each dataset into your own pipeline the moment it finishes.
Integrate YouTube Search Scraper and automate your workflow
YouTube Search Scraper works with any language or tool that can send an HTTP request through the Apify API.
REST API with Python
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("<YOUR_USERNAME>/youtube-search-scraper-by-upload-date-duration-type").call(run_input={"searchTerms": ["cold brew review"],"resultsPerTerm": 25,"orderResultsBy": "viewCount","detailLevel": "fast",})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["title"], row["viewCount"], row["channelName"])
Scheduled monitoring and delivery
Set up a recurring run with Apify's Schedule feature on the Actor's page, choosing how often it re-runs your searchTerms list. Attach a webhook to the run to notify your own endpoint, or push the dataset onward, the moment each scheduled run finishes — no polling loop required on your end.
Is it legal to scrape YouTube search results?
Yes — YouTube Search Scraper collects only what any anonymous visitor sees on YouTube's public search results page, without logging in or accessing any private data. Courts have repeatedly held that scraping publicly accessible web data does not violate the U.S. Computer Fraud and Abuse Act (hiQ Labs, Inc. v. LinkedIn Corp., 9th Cir., 2019). Video titles, view counts and channel handles are business and public-content data rather than personal data in the GDPR/CCPA sense, though a channel or video description may incidentally contain a person's name — treat any such fields with care in downstream use. You remain bound by YouTube's Terms of Service regardless of whether the CFAA applies. Consult your legal team before using extracted data for bulk redistribution or commercial resale.
❓ Frequently asked questions
Does YouTube Search Scraper support region or language filtering?
No. Unlike the official YouTube Data API's regionCode and relevanceLanguage parameters, this Actor has no region or language input — results reflect whatever YouTube serves the request's proxy exit location. If you need consistent regional targeting, route the run through a specific Apify Proxy country in proxyConfiguration.
How does YouTube Search Scraper decide whether to return videos, channels or playlists?
The resultKind parameter — video (default), channel, playlist or movie — selects one result type per run. It is encoded into the sp= filter as YouTube's own type field, so the underlying search itself, not just post-filtering, is restricted to that kind.
How does YouTube Search Scraper handle YouTube's anti-bot measures?
detailLevel = full is bot-walled on datacenter IPs — measured directly as zero rows returned with a "Sign in to confirm you're not a bot" page — so a Full run with no proxy selected starts on a RESIDENTIAL proxy automatically, and a Full run on your own proxy escalates to RESIDENTIAL if YouTube blocks it. Every escalation is written to the run log. detailLevel = fast works on the Actor's own container IP without any proxy.
Does YouTube Search Scraper really verify that its filters work?
Yes. Each filter's real effect on the result set was measured by ID overlap against an unfiltered search: "This week" shared 0 of 8 IDs, subtitles shared 4 of 8, Creative Commons shared 0 of 8, and live-now returned 8 of 8 rows with liveStatus = is_live. That audit trail is also returned per row in spParam, appliedFilters and sortMode, so you can confirm on your own data that a filter was actually applied.
How many results does YouTube Search Scraper return per search term?
Up to resultsPerTerm, from 1 to 2000, defaulting to 10. At detailLevel = full each row costs roughly 587 KB of RESIDENTIAL proxy traffic, so 2000 results is close to 1.2 GB for a single term; the same 2000 rows at detailLevel = fast cost roughly 2 KB each. dropDuplicateIds (default true) removes repeats YouTube serves across deep result pages before this count is reached.
How do I monitor YouTube search rankings for a keyword over time?
Schedule recurring runs of the same searchTerms with Apify's Schedule feature, then diff each new dataset against the previous one by id within the same input term — watch searchRank, order and viewCount for movement, and treat any unmatched id as a new entrant to the result set.
Does YouTube Search Scraper work with Claude, ChatGPT and other AI agent frameworks?
Yes. It is callable as a standard HTTP endpoint through the Apify API, so any agent framework that can issue a request — LangChain, CrewAI, a custom tool definition — can call it and receive typed JSON rows directly, letting an agent ground its answer in a live YouTube search rather than training data.
How does YouTube Search Scraper compare to other YouTube scrapers on Apify?
Checked on the Apify Store on 26 July 2026: api-ninja/youtube-search-scraper documents a broader features toggle object (HD, 3D, 4K, 360, HDR, VR180) and a "scrape all results" mode, but does not document that its filters were verified against real result sets. grow_media/youtube-search-api wraps the official YouTube Data API directly and documents "up to 1000 video results," but is scoped to video results only and states no channel or playlist search. tcz/youtube-search-term-channel-crawler is a minimal tool focused on pulling channel contact emails from search results and does not document result filtering at all. YouTube Search Scraper's difference is the combination of typed video/channel/playlist rows, real upload-date and duration filters with measured proof they work, and a per-row audit trail (spParam, sortMode) that lets you confirm it on your own runs.
Can I use YouTube Search Scraper without managing proxies or a YouTube/Google API key?
Yes for the API key — no Google Cloud project or YouTube API key is ever required. For proxies: detailLevel = fast needs none at all. detailLevel = full requires a RESIDENTIAL proxy, and if you leave proxyConfiguration empty the Actor selects Apify's RESIDENTIAL proxy for you automatically; you never have to source or rotate one yourself.
What happens if I call YouTube Search Scraper with an empty input?
It still runs. searchTerms carries a schema default of ["python programming"], so a run started through the Apify API with {} as input is not rejected — the platform fills in that default before execution, the Actor searches "python programming," and you are charged row_result events for it. To guarantee a run only ever searches terms you explicitly chose, always include searchTerms in the input you send.
💬 Your feedback
Found a bug, or a field YouTube exposes that isn't in the output yet? Open an issue on the Actor's Issues tab on Apify — reports that include the search term and the filters you used are the fastest to reproduce and fix.