YouTube Search Scraper With Keyword Rank Tracking avatar

YouTube Search Scraper With Keyword Rank Tracking

Pricing

Pay per usage

Go to Apify Store
YouTube Search Scraper With Keyword Rank Tracking

YouTube Search Scraper With Keyword Rank Tracking

Automate YouTube search scraping with this actor. Collect video results for any keyword including titles, URLs, channels, views, thumbnails, and publish dates for marketing research, SEO analysis, and content intelligence.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

API Empire

API Empire

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 days ago

Last modified

Share

YouTube Search Scraper — Keyword Rank, Slot Owners & Results

YouTube Search Scraper With Keyword Rank Tracking runs a real YouTube search for every keyword you give it and returns four things in one dataset: the ranked search results, a per-keyword rank verdict for each channel you track, the channels occupying the slots above you, and each channel's share of results across your whole keyword set. Every row is typed, normalized JSON — no HTML, no selectors, no enumerate() guesswork standing in for a real search position. After one run you know exactly where you rank, who outranks you, and how big they are.

What is YouTube Search Scraper With Keyword Rank Tracking?

It is an Apify Actor that searches YouTube the same way a visitor typing into the search bar would, then layers rank analysis on top of the raw results. Give it keywords and, optionally, the channels you care about — yours or a competitor's — and it tells you where each one sits in the results, who sits above it, and how much of the total result set any given channel controls.

No YouTube account, login or cookie is required. Every field returned is visible to a signed-out visitor on youtube.com/results or a channel's public About page.

  • Scrape ranked YouTube search results (video, channel, playlist or movie rows)
  • Track a channel's rank per keyword, including the keywords it does not rank for
  • List the channels holding the slots above a tracked channel, with subscriber counts
  • Compute each channel's share of results and keyword coverage across the whole run
  • Export as JSON, CSV, Excel, XML or HTML table — no proxy management, no parsing

What data does YouTube Search Scraper With Keyword Rank Tracking collect?

Four row types share one dataset, distinguished by a type field, so a single run can answer "what's in the results," "do I rank," "who outranks me," and "who owns this niche" without four separate tools.

Data TypeKey FieldsJSON Field Names
Search results (video / channel / playlist / movie)search position, title, channel, views, duration, verified badge, snippetsearchRank, title, channelName, viewCount, duration, channelIsVerified, searchSnippet
Keyword rank verdictsbest rank, every rank the channel holds, ranked / not-ranked statusbestRank, allRanks, rankStatus, resultsForChannel
Slot ownerswho occupies the ranks above your tracked channel, subscriber gapownerRank, channelName, numberOfSubscribers, subscriberGapVsTracked
Channel share of resultsone channel's footprint across your entire keyword setshareOfResultsPct, keywordsCovered, averageRank

Need more YouTube data?

If you need what happens after the search results — API Empire also publishes YouTube Playlist Scraper for full playlist contents, YouTube Video Details Scraper: Most Replayed for replay-heatmap peaks and chapters on a specific video, and YouTube Community Posts & Comments Scraper for a channel's Community tab. Pair any of them with this Actor's channelId output to go from "who ranks" to "what they post."

How does YouTube Search Scraper With Keyword Rank Tracking differ from the official YouTube Data API?

YouTube's Data API v3 returns search results too, but it is built for app development, not SEO rank tracking, and it charges by quota unit rather than by row.

FeatureYouTube Data API v3This Actor
Access requirementGoogle Cloud project, API key or OAuth consent screen, API enabledNone — run it directly on Apify
Daily quotaDefault project quota is 10,000 units/day; search.list costs 100 units per call, so roughly 100 searches/day before you request more quotaNo daily quota — cost scales with rows actually charged, not a fixed daily allowance
Per-keyword rank verdictNot provided — the caller must track position changes itselfBuilt-in keyword_rank row per tracked channel: bestRank, allRanks, ranked / not_ranked
Slot ownership / competitor detectionNot providedslot_owner rows list who occupies the ranks above your channel
Share of results across a keyword setNot providedchannel_share row aggregates every channel's footprint across the whole run
Subscriber counts on resultsRequires a separate channels.list call and its own quotaOptional, fetched once per channel and cached (lookupSubscriberCounts)
Setup timeCloud project, API enablement, credentials managementProvide keywords, click Start

The official API is the right call when you're building a YouTube-integrated app and need Google's supported, quota-governed access path. This Actor is the right call when you need a rank-tracking dataset — who ranks, who outranks them, and by how much — without managing a Cloud project or a daily unit budget.

Why do developers and teams scrape YouTube search rankings?

For AI engineers and agent builders

A rank-tracking dataset is a clean tool-call target: an agent tasked with "audit our YouTube SEO for these 20 keywords" can call this Actor, get back typed keyword_rank rows with bestRank and rankStatus already computed, and reason over the result without writing a parser or a ranking heuristic of its own. The allRanks array is enough for an agent to flag "you hold two slots on this keyword" without extra logic.

For marketers and YouTube SEO teams

Rank tracking is the core workflow: run your channel's target keyword list on a schedule, watch bestRank move, and use the slot_owner rows to see exactly which channels you need to outrank. Because a miss is emitted as rankStatus: "not_ranked" rather than silently omitted, a keyword you've never ranked for shows up in the same dataset as one you dominate.

For researchers and analysts

channel_share rows turn a keyword list into a market-share snapshot — which channels control a niche, how concentrated the results are, and whether one channel's dominance holds across the whole keyword set or just a lucky top spot on one term. This is public search-result data only; no login-gated or private content is touched.

For developers building data products

resultsForChannel, shareOfResultsPct and keywordCoveragePct are pre-computed, so a rank-tracking dashboard or a scheduled competitor-alert product can consume the dataset directly instead of re-deriving aggregates from raw search rows on every load.

How to scrape YouTube search rankings (step by step)

  1. Open YouTube Search Scraper With Keyword Rank Tracking on its Apify Store listing and click Try for free.
  2. Enter one or more keywords in searchKeywords — this is the only field the Actor actually needs to run.
  3. Add the channels you want ranked in trackedChannels (handle, UC… ID, or full URL), and set slotOwnersPerKeyword if you want to see who outranks you.
  4. Leave dataDepth at the default rank tier unless you need per-video likes, comments and exact publish dates — that tier requires a residential proxy and costs roughly 300× more traffic per row.
  5. Click Start, then download the dataset as JSON, CSV, Excel, XML or an HTML table once the run finishes.

What to do when YouTube changes its search page

The Actor reads YouTube's search results through a maintained extraction path rather than a hand-rolled HTML parser, and the output schema — field names and types — stays stable on your end even when the underlying page markup shifts. No action is required on a schema change; your integration keeps reading the same keys.

⬇️ Input

All fields are optional — required is empty in the input schema — but searchKeywords ships with a real schema default, not just a UI prefill, so an empty {} input still runs a live, chargeable search. See the pitfall note below the table.

ParameterRequiredTypeDescriptionExample Value
searchKeywordsNoarray of stringOne keyword per line; each is searched and ranked independently. default and prefill are both ["python tutorial"]. The base actor's queries field is also accepted and takes priority if present.["python tutorial", "learn python fast"]
trackedChannelsNoarray of stringChannels to rank-track — @handle, a UC… channel ID, or a full channel URL. Each is resolved to its channel ID once so matching survives a rename. Empty = ranked results + share-of-results only, no rank verdicts. prefill is ["@ProgrammingwithMosh"]; there is no schema default.["@ProgrammingwithMosh", "UC29ju8bIPH5as8OGnQzwJyA"]
resultsPerKeywordNointegerHow deep into the results to look per keyword. default 20, minimum 1, maximum 2000. Base field maxResults accepted and wins if present.20
rankingOrderNostring (enum)How YouTube orders results before ranking is read: relevance (default, YouTube's own default — applies no ordering parameter), date, viewCount, rating. Base field sortBy accepted."relevance"
publishedWithinNostring (enum)Restrict to a coarse upload window: "" (default, any time), lastHour, today, thisWeek, thisMonth, thisYear. Base field uploadDate accepted.""
videoLengthNostring (enum)Restrict by length: "" (default, any length), short (under 4 min), medium (4–20 min), long (over 20 min). Base field duration accepted.""
resultKindNostring (enum)Entity type occupying the slots you track: video (default), channel, playlist, movie. Base field type accepted."video"
emitRankRowsNobooleanEmit one keyword_rank row per keyword × tracked channel. default true. Turn off for raw results only.true
slotOwnersPerKeywordNointegerDistinct channels ranking above each tracked channel to report per keyword. default 10, minimum 0, maximum 50. 0 disables slot-owner reporting.10
lookupSubscriberCountsNobooleanFetch each relevant channel's About page once for subscriber count and country. default true. A failed lookup leaves the count null, never 0.true
maxChannelLookupsNointegerRun-wide cap on About-page fetches, shared between tracked channels and slot owners. default 30, minimum 0, maximum 500. Channels beyond the cap keep a null subscriber count.30
dataDepthNostring (enum)rank (default) — search position, title, channel, views, duration, verified status, snippet, ~2 KB/row on the container's own IP. full — additionally fetches likes, comments, exact publish date, tags and subscriber count per video, ~587 KB/row, residential proxy only."rank"
maxFullExtractionRowsNointegerSpend cap that only applies at dataDepth: "full". Caps how many rows in the entire run get the expensive per-video fetch; the rest keep rank columns and leave metadata null. default 25, minimum 0, maximum 2000.25
proxyConfigurationNoobjectApify Proxy configuration. prefill is {"useApifyProxy": false} — no schema default, so an omitted field runs with no proxy, on the container's own IP. Honoured as given; not silently overridden except the full-depth exception below.{"useApifyProxy": false}
verboseLogsNobooleanLog per-channel About lookups, response sizes and per-keyword byte counts. default false. Base field debug also accepted.false

⚠️ Common pitfall — the schema default is a live query, not a placeholder. searchKeywords carries a real default of ["python tutorial"], not just a UI prefill. If you call the Actor via the API and omit searchKeywords entirely (or send {}), Apify fills in that default before the run starts — you get a genuine search for "python tutorial" and every row it produces is a charged row_result event, even though you never asked for that keyword. Sending searchKeywords: [] explicitly is safe: the Actor detects the empty list, pushes a single uncharged type: "error" row, and exits — always populate the field explicitly, or rely on the empty-array no-op, but never rely on omitting it.

Example input, all parameters shown:

{
"searchKeywords": ["python tutorial", "learn python fast"],
"trackedChannels": ["@ProgrammingwithMosh"],
"resultsPerKeyword": 20,
"rankingOrder": "relevance",
"publishedWithin": "",
"videoLength": "",
"resultKind": "video",
"emitRankRows": true,
"slotOwnersPerKeyword": 10,
"lookupSubscriberCounts": true,
"maxChannelLookups": 30,
"dataDepth": "rank",
"maxFullExtractionRows": 25,
"proxyConfiguration": { "useApifyProxy": false },
"verboseLogs": false
}

⬆️ Output

Every run pushes typed JSON rows to one Apify dataset. Four structurally different row types share it, told apart by type; export any of it as JSON, CSV, Excel, XML or an HTML table. The dataset's default view surfaces 35 of these fields as columns — some fields below exist on the row but are not in that view, most notably id, input, order, thumbnailUrl, text, keywords, hashtags, isRanked, resultsScanned, ownerRank and keywordCoveragePct.

Search result row (type: "video" / "channel" / "playlist")

{
"type": "video",
"keyword": "python tutorial",
"searchRank": 3,
"isTrackedChannel": true,
"trackedChannelInput": "@ProgrammingwithMosh",
"id": "kqtD5dpn9C8",
"title": "Python for Beginners - Full Course",
"url": "https://www.youtube.com/watch?v=kqtD5dpn9C8",
"input": "python tutorial",
"order": 3,
"channelName": "Programming with Mosh",
"channelId": "UC29ju8bIPH5as8OGnQzwJyA",
"channelUrl": "https://www.youtube.com/@ProgrammingwithMosh",
"channelUsername": "@ProgrammingwithMosh",
"thumbnailUrl": "https://i.ytimg.com/vi/kqtD5dpn9C8/hqdefault.jpg",
"viewCount": 45213087,
"duration": "6:14:07",
"durationSeconds": 22447,
"channelIsVerified": true,
"searchSnippet": "Learn Python programming with this beginner-friendly, project-based full course...",
"date": null,
"text": null,
"likes": null,
"commentsCount": null,
"numberOfSubscribers": null,
"keywords": null,
"hashtags": null,
"dataDepth": "rank",
"scrapedAt": "2026-07-25T09:14:02Z"
}

date, text, likes, commentsCount, numberOfSubscribers and keywords stay null at the default rank depth — the flat search tier does not carry them. They fill in only when dataDepth: "full" successfully extracts that specific video.

Keyword rank row (type: "keyword_rank")

{
"type": "keyword_rank",
"keyword": "python tutorial",
"input": "python tutorial",
"trackedChannelInput": "@ProgrammingwithMosh",
"channelId": "UC29ju8bIPH5as8OGnQzwJyA",
"channelUsername": "@programmingwithmosh",
"channelName": null,
"rankStatus": "ranked",
"isRanked": true,
"searchRank": 3,
"bestRank": 3,
"allRanks": [3, 17],
"resultsForChannel": 2,
"resultsScanned": 20,
"numberOfSubscribers": 4110000,
"subscribersText": "4.11M subscribers",
"title": "Python for Beginners - Full Course",
"url": "https://www.youtube.com/watch?v=kqtD5dpn9C8",
"scrapedAt": "2026-07-25T09:14:03Z"
}

One row per keyword × tracked channel, always emitted — a channel that never appears for a keyword still gets a row with rankStatus: "not_ranked", bestRank: null, allRanks: null. channelName on this row type is null by design: the channel-resolution step reads a channel ID and subscriber count off the About page but does not parse a display name from it.

Slot owner row (type: "slot_owner")

{
"type": "slot_owner",
"keyword": "python tutorial",
"input": "python tutorial",
"trackedChannelInput": "@ProgrammingwithMosh",
"rankStatus": "ranked",
"trackedBestRank": 3,
"searchRank": 1,
"ownerRank": 1,
"channelId": "UCCezIgC97PvUuR4_gbFUs5g",
"channelName": "Corey Schafer",
"channelUrl": "https://www.youtube.com/@coreyms",
"channelUsername": "@coreyms",
"channelIsVerified": true,
"title": "Python Tutorial for Beginners - Full Course",
"url": "https://www.youtube.com/watch?v=YYXdXT2l-Gg",
"viewCount": 7820441,
"scrapedAt": "2026-07-25T09:14:03Z",
"numberOfSubscribers": 1290000,
"subscribersText": "1.29M subscribers",
"channelCountry": "United States",
"subscriberGapVsTracked": -2820000
}

One row per distinct channel occupying a slot above the tracked channel's bestRank (deduplicated — one row per channel, at its best position). If the tracked channel does not rank at all, every channel in the top block is reported instead, up to slotOwnersPerKeyword.

Channel share row (type: "channel_share")

{
"type": "channel_share",
"channelId": "UC29ju8bIPH5as8OGnQzwJyA",
"channelName": "Programming with Mosh",
"channelUrl": "https://www.youtube.com/@ProgrammingwithMosh",
"channelUsername": "@programmingwithmosh",
"isTrackedChannel": true,
"resultCount": 3,
"resultsScanned": 40,
"shareOfResultsPct": 7.5,
"keywordsCovered": 2,
"keywordsSearched": 2,
"keywordCoveragePct": 100.0,
"bestRank": 3,
"averageRank": 8.33,
"numberOfSubscribers": 4110000,
"subscribersText": "4.11M subscribers",
"scrapedAt": "2026-07-25T09:14:05Z"
}

One row per channel seen anywhere in the run, aggregated across every keyword — resultCount and shareOfResultsPct are computed against the total rows scraped in the whole run, not per keyword, and averageRank blends that channel's rank positions across every keyword it appeared in.

Error row (type: "error", always uncharged)

A keyword that returns zero rows (a genuine empty result set, or YouTube serving a bot-check page) produces {"type": "error", "keyword": "...", "input": "...", "error": "...", "scrapedAt": "..."}. An input with no usable keywords at all produces a single {"type": "error", "error": "No search keywords provided.", "scrapedAt": "..."}. Both are pushed with Actor.push_data() and no charged_event_name — filter type != "error" if you need a row count that matches what you were billed for; error rows are never part of it.

⚠️ Honest limitations

  • No rank history. YouTube publishes no historical ranking data, so a single run cannot show "you moved from #7 to #4." The Actor reports one point-in-time rank verdict per run rather than shipping fabricated trend columns. Schedule the Actor and diff the datasets across runs if you want a rank-history trend.
  • date, likes, commentsCount, keywords, text and per-video numberOfSubscribers are null at the default rank depth. The flat search tier this Actor runs on does not carry them. Set dataDepth: "full" to fill them in, at roughly 300× the proxy traffic per row.
  • dataDepth: "full" only extracts video rows. The per-video fetch that fills in the metadata columns only triggers when resultKind is video. If resultKind is channel, playlist or movie, every row stays at rank depth even with dataDepth: "full" selected — the extra fields simply never populate for those result kinds.
  • channelName on keyword_rank rows is always null. Tracked-channel resolution reads a channel ID and subscriber count off the channel's About page but does not parse a display name from it, so this one field never fills in on that row type even for a fully resolved channel. channelUsername and channelId are populated normally.
  • No automatic retry on a failed search. If a yt-dlp call for a keyword fails — a transient network error or a bot-check page — the Actor logs it and pushes one uncharged error row for that keyword rather than retrying it automatically. Re-run the Actor, or re-supply just the failed keywords, if you need that row.
  • Subscriber counts carry YouTube's own rounding. YouTube only publishes an abbreviated public count, so numberOfSubscribers: 4110000 is derived from the displayed string 4.11M subscribers. The raw string is kept in subscribersText so the real precision — or lack of it — stays visible.
  • maxChannelLookups is spent on tracked channels first. The shared About-page lookup budget resolves every tracked channel before any slot owner gets a lookup. With a low cap and several tracked channels, slot-owner rows can end up with numberOfSubscribers: null even though the run had budget nominally available.
  • searchSnippet is the search-result snippet, not the full description. It comes from the flat search tier's own truncated text. The full description is only available at dataDepth: "full", in the (undocumented-in-view) text field.
  • Upload-date filtering is bucketed. YouTube's search surface only offers hour / day / week / month / year windows on publishedWithin — there is no exact date-range parameter to encode.
  • Result depth is YouTube's call, not just the schema's. resultsPerKeyword accepts up to 2,000, but YouTube's flat search feed typically stops returning fresh rows well before that ceiling. The Actor returns what YouTube actually serves and logs the real row count per keyword.

How does YouTube Search Scraper With Keyword Rank Tracking compare to other YouTube scrapers?

FeatureThis ActorGeneric YouTube search scraper
Search result dataVideo/channel/playlist/movie rows with the true YouTube search position (playlist_index)Video/Short rows, typically numbered by loop position rather than a verified search index
Per-keyword rank verdictBuilt-in keyword_rank row per tracked channel, ranked / not_ranked always emittedNot offered — checked on lurkapi's and scrapestorm's own Apify Store listings, 2026-07-25
Slot ownership / who outranks youslot_owner rows list every channel above your tracked channel, with subscriber gapNot offered — checked on the Apify Store, 2026-07-25
Share of results across a keyword setchannel_share aggregation row per channel, across the whole runNot offered — checked on the Apify Store, 2026-07-25
Pricing modelPay per row_result event; error and empty-result rows are never chargedlurkapi advertises $1.50 per 1,000 videos plus paid add-ons for stats, language and channel analytics; scrapestorm advertises a flat $19.90/month subscription — both per their own listings, checked on the Apify Store 2026-07-25, not measured here

If you're building an AI agent or RAG pipeline, the rank-verdict row is the decision-maker — an agent that has to infer "did we rank" from a raw, unlabeled result list is doing analysis a data source should have already done for it.

How many results can you scrape with YouTube Search Scraper With Keyword Rank Tracking?

resultsPerKeyword accepts 1 to 2,000 (schema minimum 1, maximum 2000), applied independently per keyword — five keywords at 20 results each is 100 result rows before rank rows, slot owners or share rows are added. There is no additional hard cap in the Actor beyond that schema ceiling, but YouTube's own flat search feed typically stops returning fresh results well before 2,000; the Actor logs the real row count it received for each keyword so you can see where that happens. Keywords run with up to 4 processed concurrently, so total run time scales with keywords ÷ 4, not keywords × resultsPerKeyword sequentially. Rank tracking rarely needs more than the first page or two — the default of 20 already covers what a visitor sees without scrolling.

Integrate YouTube Search Scraper With Keyword Rank Tracking and automate your workflow

YouTube Search Scraper With Keyword Rank Tracking works with any language or tool that can send an HTTP request to the Apify API.

REST API integration

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run_input = {
"searchKeywords": ["python tutorial", "learn python fast"],
"trackedChannels": ["@ProgrammingwithMosh"],
"slotOwnersPerKeyword": 10,
}
run = client.actor("<YOUR_USERNAME>/youtube-search-scraper-keyword-rank-tracking").call(run_input=run_input)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item["type"] == "keyword_rank":
print(item["keyword"], item["rankStatus"], item["bestRank"])

Works in Python, Node.js, Go, Ruby or plain cURL against the same run-sync-get-dataset-items or runs endpoints.

Automation platforms (n8n, Make, LangChain)

In n8n, use the official Apify node, set it to Run Actor, point it at youtube-search-scraper-keyword-rank-tracking, and pass your keyword and channel list from an upstream node. In Make, the Apify module's "Run an Actor and get dataset items" action does the same, with the dataset items feeding straight into a Google Sheets or Slack module for a rank-change alert. In LangChain, ApifyWrapper.from_actor_call or the ApifyDatasetLoader can pull the resulting dataset directly into a document loader for downstream RAG or agent use.

Yes — this Actor collects only publicly available data: YouTube search result pages and public channel About pages, exactly as a signed-out visitor sees them. No login, no cookies, and no content behind a sign-in wall is accessed.

The data returned here is business and content-ranking data — search positions, video metadata, channel subscriber counts — not private personal data about individuals. It does not attach to identifiable private persons the way a personal social profile or a reviewer's comment history would, so GDPR's personal-data framework does not meaningfully apply to it. What does apply is YouTube's Terms of Service, which govern automated access to the platform, and ordinary database and content-ownership rights over what you do with the collected results. Consult legal counsel for commercial use cases, especially ones involving bulk redistribution of the collected data.

❓ Frequently asked questions

Does YouTube Search Scraper With Keyword Rank Tracking work without a YouTube account?

Yes. No login, API key, or cookie is required anywhere in the Actor — searches run against the public youtube.com/results page and channel About pages exactly as a signed-out visitor would see them.

How often is the scraped data updated?

Every run performs a live search at the moment it runs — there is no cache and no stored snapshot reused between runs. Rank positions can move between runs the same way they move on YouTube itself; if you want a rank-history trend, schedule the Actor and diff the datasets across runs, since YouTube itself publishes no historical ranking data.

What happens if a keyword returns zero results, or my tracked channel doesn't rank at all?

Two different things happen, and they are deliberately not the same. A keyword that genuinely returns no rows — because nothing matched, or because YouTube served a bot-check page — produces an uncharged type: "error" row with the failure reason. A keyword that returns rows just fine, where your tracked channel simply isn't among them, still produces a full keyword_rank row with rankStatus: "not_ranked" and bestRank: null — a miss is a finding the Actor reports, not a row it silently skips.

Can I scrape private or unlisted YouTube content?

No. Only what's publicly reachable from a search results page or a channel's public About page is returned — unlisted videos, private videos, and anything behind a sign-in wall are not accessible to this Actor, the same as they aren't accessible to a signed-out browser.

Do I need a separate signup or trial to use this Actor?

No separate signup exists beyond a standard Apify account. You run it from the Apify Console or the Apify API like any other Actor, and it charges per row_result event actually produced — error and empty-result rows are never charged.

Does YouTube Search Scraper With Keyword Rank Tracking work for AI agent workflows and LLM pipelines?

Yes. It's callable as a standard HTTP endpoint through the Apify API by any agent framework that can make a request — every row is typed JSON with stable field names, so there's no HTML or selector parsing step before handing the output to an LLM.

How does YouTube Search Scraper With Keyword Rank Tracking handle YouTube's anti-bot system?

The default rank tier runs on the container's own IP because YouTube's flat search feed doesn't trigger the bot check that its full video-page extraction does. If YouTube still returns a bot-check page ("Sign in to confirm you're not a bot" and similar phrasing), the Actor detects it explicitly and raises a clear, labeled error instead of returning an empty result silently. Selecting dataDepth: "full" forces those specific per-video requests through a residential proxy, because full extraction returns zero rows on any datacenter IP — that override is logged when it happens. Your own proxyConfiguration is honoured for everything else, not silently replaced. The Actor does not automatically retry a failed yt-dlp call — a transient failure is logged and reported as an uncharged error row for that keyword rather than retried in place.

How does YouTube Search Scraper With Keyword Rank Tracking compare to other YouTube scrapers?

The top-ranked competing Actors on the Apify Store (lurkapi's keyword search scraper and scrapestorm's search scraper, checked 2026-07-25) return search result rows with view counts, thumbnails and optional add-ons for stats or channel analytics, but neither publishes a rank-verdict, slot-ownership or share-of-results feature in its listing. This Actor's differentiator is exactly that layer — a bestRank and not_ranked verdict per tracked channel, who outranks it, and how much of a keyword set any one channel controls.

Does YouTube Search Scraper With Keyword Rank Tracking return data in a format LLMs can use directly?

Yes. Every row is typed, normalized JSON with stable field names — pass it directly into an LLM's context window, index it into a vector store, or route it through an agent tool without a parsing step.

Can I use this Actor without managing proxies?

Yes. The default rank tier runs on the container's own IP with no proxy required — that's the intended, cheaper path. Set proxyConfiguration only if you specifically want searches routed through Apify Proxy; dataDepth: "full" will still force its own per-video requests through a residential proxy regardless of what you set there, because that tier is bot-walled on datacenter IPs.

What happens when YouTube changes its structure or blocks the scraper?

The Actor is maintained, and its output schema — field names and types — stays stable on your end even when YouTube's underlying page markup changes. No numeric turnaround time is promised for a fix; the point of the stable schema is that your integration keeps working without changes on your side once one ships.

💬 Your feedback

Found a bug, or a field that's missing something you need? We want to know — the fastest way to reach us is through the Actor's page on the Apify Store, or by opening an issue against this Actor. Bug reports and field requests are how this dataset gets better for the next run.