YouTube Search Results Scraper (videos, channels, no API key) avatar

YouTube Search Results Scraper (videos, channels, no API key)

Pricing

from $0.30 / 1,000 results

Go to Apify Store
YouTube Search Results Scraper (videos, channels, no API key)

YouTube Search Results Scraper (videos, channels, no API key)

YouTube Search Results Scraper returns videos, channels or playlists for any keyword, with title, views, duration, channel and publish time — no API key, no quota.

Pricing

from $0.30 / 1,000 results

Rating

0.0

(0)

Developer

Murat Uzun

Murat Uzun

Maintained by Community

Actor stats

0

Bookmarked

5

Total users

1

Monthly active users

2 days ago

Last modified

Features

Limited permissions

Share

What is YouTube Search Results Scraper?

YouTube Search Results Scraper runs any search term against YouTube and returns videos, channels or playlists — title, channel, view count, duration, upload time, thumbnail and more — as one clean row per result. It calls YouTube's own /youtubei/v1/search endpoint directly, the same one youtube.com's search page uses, so no YouTube Data API key and no daily quota are needed. Paste in your search queries, pick a result type, and run it on Apify with scheduling, API access and export built in.

Who it is for: YouTube SEO and content teams tracking where videos rank for a keyword, marketers researching competitors and creators, and developers who need search results without the Data API quota. Price: $0.50 per 1,000 results (Free plan, pay per saved result row; failed, empty or skipped searches incur no result-row charge; the $0.00005 Actor start event still applies). Turn on Track rank changes between runs and every result also shows its previous position, how many places it moved, and whether it is new; results that dropped out are listed in the run summary, at no extra cost.

What data does YouTube Search Results Scraper extract?

One row per matching video, channel or playlist:

FieldTypeDescription
query, positionstring, numberThe search term and this result's 1-based rank
type, id, urlstringvideo/channel/playlist and its ID and canonical URL
titlestringVideo title, channel name or playlist title
channelName, channelId, channelUrlstringThe owning/uploading channel
viewCountText, viewCountstring, numberRaw and parsed view (or "watching") count
publishedTimeText, publishedAtApproxstringRaw relative time ("6 months ago") and a best-effort resolved ISO date
durationText, durationSecondsstring, numberVideo length, null for live streams
thumbnailUrlstringLargest available thumbnail
descriptionSnippetstringExcerpt from the video description or channel bio
subscriberCountTextstringChannel results only, e.g. "25.2K subscribers"
videoCountnumberPlaylist results only, parsed from the "N videos" badge
isLive, badgesboolean, arrayLive-stream flag and labels like New, LIVE, 4K, CC
publishDate, uploadDate, likeCount, description, tags, category, isFamilySafe, detailsStatusstring, string, number, string, array, string, boolean, stringOnly with Add video details: exact times, likes, full description, tags and category from YouTube's player data, plus whether the lookup worked
previousPosition, positionChange, isNewInResults, comparedWithRunAtnumber, number, boolean, stringRank tracking only: position in the previous run of the same query and filters, places moved (positive = up), new entry flag, and when that previous run happened
errorCode, error, scrapedAtstringAlways null on saved rows (failed searches go to ERRORS, see below); ISO timestamp

How to use YouTube Search Results Scraper

  1. Open the Input tab and list your Search queries, e.g. web scraping tutorial, apify.
  2. Pick a Result type — video, channel, playlist or all three mixed.
  3. Optionally set Upload date, Duration and Sort by to narrow the results.
  4. Set Max results per query (the Actor pages through YouTube's continuations to reach it) and click Start.
  5. Download the dataset as JSON, CSV, Excel or HTML from the Output tab, or pull it via the API.

Feature filters and video details

Features (features) works like YouTube's Filters -> Features menu, and results must have every feature you list: live, 4k, hd, subtitles, creativeCommons, 360, vr180, 3d, hdr. They are sent to YouTube's own search filter. Live tests on 13 Nov 2026 (20 results each) showed the matching badge on every result for live, 4k, subtitles, 360 and vr180. For hd, creativeCommons, 3d and hdr YouTube clearly changed the results, but the search cards carry no badge to confirm each one. YouTube's "Location" feature returned no results in testing, so it is not offered. An unknown value stops the run before any request.

Add video details (fetchVideoDetails: true) adds each video's exact publishDate and uploadDate (instead of only "3 weeks ago"), likeCount, the full description, tags, category and isFamilySafe. It costs one small extra request per video (about 10 KB) and the price per result does not change. Channel and playlist rows get empty detail columns with detailsStatus: "NOT_A_VIDEO". If YouTube answers with its sign-in check, the row keeps all search fields and says detailsStatus: "BLOCKED"; OUTPUT.videoDetails counts fetched, blocked and failed lookups. Details are only looked up for rows that will actually be saved within your charge limit.

Track YouTube rank changes between runs

Set Track rank changes between runs (trackRankChanges: true) and schedule the same queries daily or weekly. The Actor stores each query's last complete result list in your account's named key-value store youtube-search-rank-history, keyed by the query (case-insensitive) plus the type, upload-date, duration, sort, region and language filters, so different filter sets never mix.

On the next run every row gets:

On the first run, history fields are naturally null; useful video results still have query, position, type, ID, URL, title and channel name. Compare matching video IDs after a complete prior snapshot to validate rank changes. Optional video details can be unavailable (for example, detailsStatus: "BLOCKED") without invalidating the search result.

  • previousPosition: where it ranked last time (null on the first run or if it was not in the previous list).
  • positionChange: previous minus current position; +3 means it moved up three places, 0 means unchanged, and null means there is no previous position to compare.
  • isNewInResults: true when it was not in the previous list even though that run looked at least this deep; null when that cannot be known (first run, or the previous run fetched fewer results).

OUTPUT.rankTracking adds totals (comparedQueries, firstRunQueries, newEntries, movedUp, movedDown, unchanged) and a droppedOut list of results from the previous run that are no longer in the same top positions, with their old position. Only complete result lists become the next baseline, so a run cut short by a failed page or the time limit never creates fake "new" entries later. The Rank changes dataset view shows the columns side by side.

{
"queries": ["web scraping tutorial", "python requests tutorial"],
"type": "video",
"maxResultsPerQuery": 50,
"trackRankChanges": true
}

Example input

{
"queries": ["web scraping tutorial", "apify"],
"type": "video",
"uploadDate": "any",
"sortBy": "relevance",
"duration": "any",
"maxResultsPerQuery": 50
}

Example output

{
"query": "web scraping tutorial",
"position": 1,
"type": "video",
"id": "hHQlcnubuFI",
"url": "https://www.youtube.com/watch?v=hHQlcnubuFI",
"title": "Learn Web Scraping in 5 Minutes (NO PRIOR KNOWLEDGE)",
"channelName": "CodeHead",
"channelUrl": "https://www.youtube.com/channel/UCFVteOob_YXJHPaGTqlDV2Q",
"viewCountText": "158,721 views",
"viewCount": 158721,
"publishedTimeText": "6 months ago",
"durationText": "4:53",
"durationSeconds": 293,
"descriptionSnippet": "Get Rid of IP Blocking for just $1 with DataImpulse: ...",
"isLive": false,
"scrapedAt": "2026-09-13T12:00:00.000Z"
}

Input parameters

ParameterTypeDefaultDescription
queriesarray["web scraping tutorial"]Search terms, one dataset slice per query
typestringvideoall, video, channel or playlist
uploadDatestringanyhour, today, week, month or year
sortBystringrelevancerelevance, date, views or rating
durationstringanyshort (<4 min), medium (4-20 min), long (>20 min)
maxResultsPerQueryinteger50Results per query, 1-1000
language, regionstringen, USSent to YouTube as hl/gl
maxConcurrencyinteger3Queries run in parallel

Which filters are verified vs. best-effort

Every filter value below was captured live against youtubei/v1/search and checked against the actual returned results, not copied from documentation:

  • Type (video/channel/playlist) — verified: each filter returns exclusively that renderer type.
  • Upload date (hour/today/week/month/year) — verified: tested against a high-volume query and every returned video's relative-time text fell inside the requested window.
  • Duration (short/medium/long) — verified: every returned video's length matched the bucket.
  • Sort by views — verified: results come back in a monotonically decreasing view-count order.
  • Sort by date and rating — not reliably honoured server-side as of this testing; YouTube's WEB client silently no-ops both values on this endpoint. For sortBy=date the Actor instead re-sorts the page(s) it already fetched by a parsed approximate publish date (client-side, best-effort — not a true site-wide "newest first"). sortBy=rating has no reliable substitute (YouTube no longer exposes like/dislike counts publicly) and is left in fetch order.

Playlists render as YouTube's newer lockupViewModel card rather than the legacy playlistRenderer; the Actor reads that shape (with a fallback for the old one). Channel results also carry a long-standing field-name swap in YouTube's own JSON: videoCountText actually holds the subscriber-count text and subscriberCountText holds the @handle — the Actor corrects for this internally so subscriberCountText in the dataset means what it says.

Pricing

YouTube Search Results Scraper uses pay-per-event pricing: $0.0005 per result row, i.e. $0.50 per 1,000 results, on the Free plan, plus $0.00005 per Actor start event. A 50-result run across 10 queries costs about $0.25. Set Maximum cost per run and the Actor trims work to fit your budget instead of overspending.

YouTube Search Results Scraper vs. the YouTube Data API

The official YouTube Data API's search.list endpoint burns 100 quota units per call against a 10,000-unit daily default — about 100 searches a day, no more. This Actor talks to the same endpoint the youtube.com search page itself uses, with no API key, no OAuth and no quota ceiling, and returns a flat one-row-per-result dataset ready for a spreadsheet or a pipeline.

Run it from code

JavaScript (npm install apify-client):

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('webdatatools/youtube-search-scraper').call({
queries: ['web scraping tutorial'],
maxResultsPerQuery: 20,
trackRankChanges: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const v of items) console.log(v.position, v.positionChange, v.title);

Python (pip install apify-client):

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('webdatatools/youtube-search-scraper').call(
run_input={'queries': ['web scraping tutorial'], 'maxResultsPerQuery': 20},
)
for item in client.dataset(run['defaultDatasetId']).iterate_items():
print(item['position'], item['title'], item['viewCount'])

CLI (npm install -g apify-cli, then apify login):

$echo '{"queries":["web scraping tutorial"],"maxResultsPerQuery":10}' | apify call webdatatools/youtube-search-scraper --output-dataset

Using YouTube Search Results Scraper with AI agents and MCP

This Actor is pay-per-event with limited permissions — the two requirements for an Actor to be callable through the Apify MCP server at mcp.apify.com. An agent passes queries and gets back structured video/channel/playlist rows for competitive research, content discovery or lead sourcing, and the same run works from n8n, Make, Zapier and LangChain through Apify's integrations.

To add only this Actor as a tool in an MCP client (Claude Desktop, Cursor, VS Code), use the hosted server with your Apify token:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/?tools=webdatatools/youtube-search-scraper",
"headers": { "Authorization": "Bearer <APIFY_TOKEN>" }
}
}
}

Then ask, for example: "Search YouTube for 'python requests tutorial', return the top 20 videos and tell me which ones moved up since last week."

Errors, empty results and run outcomes

Failed, empty or skipped searches are not saved as dataset rows and incur no result-row charge; the $0.00005 Actor start event still applies. They go to the ERRORS record in the run's key-value store, one entry per query with a code and a plain-English message:

errorCodeMeaningWhat to do
NO_RESULTSYouTube returned no results for this query and filtersLoosen the filters (upload date, duration, type) or check the spelling
SEARCH_REQUEST_FAILEDYouTube rejected or did not answer the first request after retriesRun again later; if it repeats, open an Issue with the run link
SEARCH_PAGE_FAILEDA later results page failed; the results before it were keptRun again if you need the full depth
STOPPED_FOR_TIMEThe run time limit (or an abort) came first; any results already found were keptRaise the run timeout or split the queries
CHARGE_LIMITThe run's maximum total charge was used up before this queryRaise Maximum cost per run

OUTPUT summarises every run: requestedQueries, completedQueries, resultRows, zeroResultQueries, failedQueries, skippedQueries, incompleteQueries, budgetLimited, stoppedForTime, partial, the timeoutSource (the platform's ACTOR_TIMEOUT_AT, or the run's own timeout option when that variable is missing) and, with rank tracking, rankTracking.

  • At least one result saved: the run succeeds and its status message says how many and whether anything was incomplete.
  • No results because YouTube had none, the charge limit was 0 or time ran out: the run still succeeds, with zeroResultReason (NO_RESULTS, CHARGE_LIMIT or RUN_TIME_LIMIT) and zeroResultMessage in OUTPUT. No result-row charge; the $0.00005 Actor start event still applies.
  • No results because YouTube requests failed, or the input has no usable query: the run fails with a message, so schedules and webhooks can alert you. No result-row charge; the $0.00005 Actor start event still applies.

FAQ

How much does a typical run cost? You pay $0.0005 per saved result row ($0.50 per 1,000) plus $0.00005 per Actor start event, on the Free plan; paid Apify plans get lower per-result prices (see the Pricing tab). 10 queries x 50 results = 500 rows = about $0.25. Rank tracking, feature filters and video details add no charge: they are on the same rows. Failed, empty or skipped searches incur no result-row charge; the Actor start event still applies. Set Maximum cost per run and the Actor reserves budget before each query, so parallel queries never overspend.

Why is videoCount null for channel results? YouTube's search results page does not expose a channel's total video count anywhere in the response — only subscriberCountText. It's populated for playlists, parsed from the "N videos" thumbnail badge.

Why does publishedAtApprox look approximate? YouTube search only ever returns relative text like "6 months ago", never an exact timestamp, so the Actor resolves it against the scrape time as a best-effort midpoint — treat it as approximate, not authoritative.

Does sorting by date actually work? Not server-side, as documented above — see "Which filters are verified vs. best-effort".

Is this legal to run? Yes. It reads YouTube's own public search results page data, the same data any visitor's browser receives, and collects no personal data beyond what a channel or video owner already published.

What are the limitations? YouTube can change its internal JSON shape or filter encoding at any time without notice; if a run starts returning fewer fields than expected, please open an Issue.

Part of the webdatatools web-intelligence suite — every Actor is pay-per-event, reads public data without a login, and returns one clean row per entity:

Browse the whole suite at webdatatools, or call ten of these Actors straight from Claude, Cursor or Cline with the webdatatools MCP server.

Website & domain intelligence

Content for AI, LLMs and RAG

Search, video and social

Leads, jobs and company data

Developer, app and research data

Support and feedback

Found a query that returns unexpected results, or a field that's missing? Open an issue on the Issues tab.

If this Actor is useful to you, you can leave a review on its Apify Store page. Nothing is offered in return.