YouTube Search Scraper - Keyword Rankings
Pricing
from $2.00 / 1,000 results
YouTube Search Scraper - Keyword Rankings
Give it keywords, get YouTube's ranked results: position, title, channel, views and publish date for every result. Built for rank tracking and competitor research. No transcripts or comment text: the Video Scraper does those.
Pricing
from $2.00 / 1,000 results
Rating
0.0
(0)
Developer
Tubelens
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
YouTube search scraper - track keyword rankings and search results
Give it keywords, get YouTube's ranked results. Each row is one result with its position, so you always know what rank a video, channel or playlist holds for that search right now.
$0.005 per run start plus $0.002 per result, that's $2 per 1,000 results.
Takes a list of keywords, not just one, so you can track a whole set in a single run.
Why this scraper?
- 🔑 No quota wall. YouTube's own Data API charges 100 units per search against a 10,000-unit daily default, about 100 searches a day, and requests to raise that limit for competitive analytics are frequently turned down.
- 📋 Bulk keywords, not one at a time. Paste a list and every row carries the keyword that produced it. The dedicated search actor in this niche takes a single query string, so bulk sets are impossible there.
- 🥇 Real rank position. Every result carries its 1-based position, counting only what a person would actually scroll past. It works in all five result types: videos rank against videos, channels against channels, playlists against playlists, Shorts against Shorts. Shelves and other page furniture never take a number.
- 🕳️ Deep paging, not just the first screen. Around 300 to 500 unique results for a specific keyword, well past where cheaper scrapers stop. Very broad one-word terms exhaust much sooner.
- 🎯 Filters that are honest about what works. Sort is Relevance or Popularity because those are the only two that actually reorder anything on YouTube's own page; upload window, duration and content filters all measurably change what comes back.
- 🌍 Language genuinely changes the results. Set it to match your audience and get a different ranked list, not just relabeled text. View counts and publish dates come back as real numbers and real dates in 14 languages, Indian lakh grouping and Arabic word-counts included, not just in English.
- 🚫 No proxy setup, no browser to babysit. Datacenter routing by default, works out of the box.
- 🧾 Honest dates. A search result only ever carries relative text like "6 years ago", never an exact timestamp, so this actor gives you that text plus a derived date flagged as approximate instead of pretending to know the real one.
What data can you extract?
| Field | Type | Description |
|---|---|---|
position, keyword, rowType | number, string, string | Rank for this keyword, the keyword that produced the row, and the kind of row: video, channel, playlist or shelfItem |
title, url, videoId | string | Result title, canonical link, and video ID when the row is a video |
channel.name, channel.id, channel.url, channelHandle, channelIsVerified | string, string, string, string, boolean | The channel behind the result, its @handle, and its verified badge |
subscriberCount, subscriberCountText | number, string | Subscriber count, populated on channel rows |
viewCount, viewCountText, concurrentViewers | number, string, number | Lifetime view count and its text, plus a live stream's current watcher count kept in its own field, never folded into viewCount |
publishedText, publishedAt, publishedAtIsApproximate | string, date, boolean | The relative text YouTube shows, a date derived from it, and a flag marking that date as approximate. The text is kept word for word in whatever language you ran |
durationSeconds, durationText, isShort | number, string, boolean | Length in seconds, the text as shown, and whether the result is a Short |
isLive, isUpcoming | boolean | Whether the result is live now, or an upcoming premiere or scheduled stream |
descriptionSnippet | string | The description preview shown under the result |
badges | array | Labels YouTube attaches, such as Live now or New |
thumbnails | array | Thumbnail image URLs |
playlistId, playlistItemCount | string, number | Populated on playlist rows |
shelfTitle | string | Names the shelf a shelfItem row came from |
estimatedResults | number | YouTube's own total-match count for the keyword, a free signal for how competitive it is |
searchedAt, language | date, string | When the search ran and which language it ran in, so rows from different runs stay comparable in one table |
YouTube search scraper vs the official YouTube Data API
| Concern | Official YouTube Data API | This actor |
|---|---|---|
| Daily limit | 10,000 units a day by default; one keyword search costs 100 units, about 100 searches a day | No daily cap |
| Bulk keyword lists | One query per call, quota burns fast | Paste a full keyword list in one run |
| Getting more quota | Extension requests for scraping or competitive analytics are frequently rejected | Nothing to request |
| Rank position | Not returned | Every row carries its position (shelf rows, if you enable them, don't) |
| Setup | Google Cloud project, API key, OAuth on some endpoints | An Apify token, nothing else |
| Cost at volume | Free until quota, then blocked | $2 per 1,000 results |
If you need a handful of searches a day, the official API is free and fine. Past that, the quota is the wall this actor exists to remove.
How to scrape YouTube search results: step by step
- Create a free Apify account. Takes 30 seconds, no card needed.
- Open YouTube Search Scraper in the Apify Console.
- Paste your keywords, one per line, and set any filters you want: result type, sort, upload window, duration, features.
- Click Start.
- Export as JSON, CSV or Excel, or pull the dataset over the Apify API.
Or drive it from the command line:
curl -X POST "https://api.apify.com/v2/acts/tubelens~youtube-search-scraper/run-sync-get-dataset-items?token=APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"keywords": ["ai agents", "cooking recipes"]}'
How much does YouTube Search Scraper cost?
Two charges: $0.005 per run start, plus $0.002 per result, which works out to $2 per 1,000 results. Every row costs the same, whatever type it is. On the Apify free plan ($5 of monthly credit) that's about 2,500 results. On Starter ($29), about 14,500.
Input
{"keywords": ["ai agents", "cooking recipes", "react tutorial"],"maxResultsPerKeyword": 50,"resultType": "video","sortBy": "relevance","uploadedWithin": "any","duration": "any","features": [],"language": "en","includeShelves": false}
| Field | Type | Default | Notes |
|---|---|---|---|
keywords | string[] | required | One search term per line; every result row carries the keyword that produced it |
maxResultsPerKeyword | integer | 50 | Caps rows returned per keyword, not how much the actor scans, 1 to 1,000 |
resultType | enum | video | video, channel, playlist, movie, shorts |
sortBy | enum | relevance | relevance or popularity, the only two sorts that actually work on YouTube's page |
uploadedWithin | enum | any | any, today, week, month, year |
duration | enum | any | any, short (under 3 min), medium (3 to 20 min), long (over 20 min) |
features | string[] | [] | subtitles, 4k, 360, vr180, live |
language | string | en | Two-letter code; genuinely changes which results come back, not just labels. Publish dates are read in ar, de, en, es, fr, hi, id, it, ja, ko, nl, pt, ru and tr |
includeShelves | boolean | false | Off by default so you get only the organic, ranked results: anything YouTube mixes into the page without a rank, such as a shelf, a channel card or a catalogue film, is not returned and not billed. On, all of it comes back unranked and billed, and a video sitting in both the ranked list and a shelf comes back twice |
Output
One row per search result, in rank order. A video row:
{"rowType": "video","videoId": "UyoVmQLekBc","url": "https://www.youtube.com/watch?v=UyoVmQLekBc","title": "How I Built an AI Agent in 14 minutes as A Beginner (2026)","channel": {"name": "Mikey No Code","id": "UCde0vB0fTwC8AT3sJofFV0w","url": "https://www.youtube.com/@mikeynocode"},"viewCount": 19861,"viewCountText": "19,861 views","concurrentViewers": null,"publishedText": "1 day ago","publishedAt": "2026-07-27T00:00:00.000Z","publishedAtIsApproximate": true,"durationSeconds": 1082,"durationText": "18:02","thumbnails": [{ "url": "https://i.ytimg.com/vi/UyoVmQLekBc/hq720.jpg", "width": 720, "height": 404 }],"badges": ["New"],"isShort": false,"isLive": false,"isUpcoming": false,"descriptionSnippet": "Claim your FREE $499 Masterclass: Build & Sell Apps, AI Agents & Websites with AI ...","channelHandle": null,"subscriberCount": null,"subscriberCountText": null,"playlistId": null,"playlistItemCount": null,"shelfTitle": null,"channelIsVerified": true,"position": 1,"keyword": "ai agents","estimatedResults": 2411581,"searchedAt": "2026-07-28T20:27:15.782Z","language": "en"}
Fields that only apply to another row type come back null: playlistId and playlistItemCount populate on playlist rows, channelHandle, subscriberCount and subscriberCountText populate on channel rows, and shelfTitle names the shelf or Shorts grid a row sat in. concurrentViewers is deliberately separate from viewCount: a live stream's current watcher count is not a lifetime view count, so live rows populate one and not the other.
With includeShelves off, every row you get is a ranked result, so position is never null. Turn shelves on and you also get everything YouTube mixed into the page without a rank: rowType: "shelfItem" rows from a shelf, a channel card injected between two videos, and catalogue films from YouTube Movies. All of those come back with position: null, and all of them are billed. Two things to budget for: a video can sit in both the ranked list and a shelf, and you get it twice, once ranked and once as a shelfItem (measured on one 60-row run, 3 videos arrived twice), and the catalogue films carry no view count and no publish date. Dedupe on videoId if you only want one copy, and keep the row whose position is not null.
Movie searches return full films alongside ordinary long videos, all with rowType: "video". Films carry no view count and no publish date anywhere in YouTube's search response, so those two fields come back null on them rather than guessed.
Which tubelens scraper do I need?
| I want to... | Use |
|---|---|
| Search YouTube by keyword and get ranked results with position | This actor, youtube-search-scraper |
| Pull everything from one channel: videos, Shorts, live streams, playlists, community posts | youtube-channel-scraper |
| Get one video's full metadata, transcript, comments and channel data | youtube-video-scraper |
They chain: search finds it, the channel scraper catalogs it, the video scraper reads it.
Use cases
- 📊 Rank tracking: monitor where a video or channel sits for target keywords over time, on a schedule.
- 🔍 Competitive research: see which competitors' videos outrank yours for the same searches.
- 🧭 Content gap analysis: sweep a batch of keywords and compare
estimatedResultsacross them to spot under-served searches. - 📈 Title and thumbnail testing: check whether a change actually moves position.
- 🌍 Localized research: run the same keyword in different languages and see how the ranking shifts.
- 🥇 Agency reporting: pull rank data across many keywords for many clients into your own warehouse instead of a per-creator dashboard tool.
- 🎬 Shorts strategy: filter to Shorts only and see what's currently ranking in that format.
Limitations
- Depth depends mostly on the keyword, and it is not a fixed number. Runs capped at 1,000 results, measured on the live actor: "how to tie a tie" reached 505 unique results, "best laptop 2026" 459, "ai agents" 443, "yoga for beginners" 318, and the very broad "music" exhausted at 93. Specific, multi-word keywords go deep; single broad terms run out fast, because YouTube itself stops serving more. The same keyword also varies run to run: two walks of "salesforce" returned 316 and 273. Filtering to
resultType: videoreaches deeper than an unfiltered search. When a run stops early for any reason other than running out of results, the status message says so. - Publish dates are approximate. Search results carry no absolute timestamp, only text like "6 years ago".
publishedAtis derived from that text and flagged withpublishedAtIsApproximate: true. - Sort is Relevance or Popularity only. Sorting by upload date or rating doesn't actually reorder anything on YouTube's own search page, so those options aren't offered. Use the
uploadedWithinfilter for recency instead. - One result type per run. Set
resultTypeto video, channel, playlist, movie or Shorts. YouTube does slip other shapes into a filtered page, a channel card or a catalogue film in the middle of a video search, and those are dropped rather than mixed into your rows, so a run returns the one type you asked for. - Only ranked results are returned and billed.
positionruns 1, 2, 3 and so on down the results YouTube ranked for your search, whichever result type you asked for. Anything the page carries without a rank never takes a number away from a real result: by default it isn't returned at all, and it only arrives, unranked and billed, if you turnincludeShelveson. - A
duration: shortsearch can include rows with no length. Live streams have no fixed length, but YouTube's own filter still admits them into that bucket, so those rows reportdurationSeconds: nullrather than a guess. - Country routing isn't offered. Tested and dropped: result overlap between the datacenter default,
country: USandcountry: DEmeasured 48 to 70 percent, but a same-settings datacenter run repeated against itself overlapped only 64 percent, so the country effect was indistinguishable from ordinary run-to-run noise, even with residential proxy genuinely engaged.languageis what actually re-ranks results, so that's the lever this actor exposes. - A run that stops early says
Partial:and names the cause. Stopping early means something cut the run short: the time budget, a charge limit, a page ceiling, or YouTube handing back a page that couldn't be read. Asking for more results than a keyword actually has is not stopping early; that run simply returns everything that exists and reports the count plainly. - Publish dates need a language this actor can read.
publishedAtis derived from YouTube's relative wording, which is written in the language you run in. It is read inar,de,en,es,fr,hi,id,it,ja,ko,nl,pt,ruandtr. Run in any other language and every other field still arrives,publishedTextstill carries YouTube's own wording, and the run warns in its log thatpublishedAtwill be empty rather than leaving you to find out from the data. - This actor doesn't read the videos it finds. Transcripts, comments and full descriptions come from
youtube-video-scraper. A channel's full catalog comes fromyoutube-channel-scraper.
FAQ
How much does YouTube Search Scraper cost? YouTube Search Scraper uses pay-per-result pricing. You pay $2 for 1,000 results, plus a small $0.005 run-start fee. The Apify Free plan gives you $5 in usage credits a month, enough for around 2,500 results. If you run regularly, the $29/month Starter plan covers about 14,500 results.
No subscription lock-in. Pause whenever.
How deep does search go?
Deeper than the first page, but it isn't unlimited, and how deep depends mostly on the keyword. Measured on the live actor with the cap at 1,000: "how to tie a tie" reached 505 unique results, "best laptop 2026" 459, "ai agents" 443, "yoga for beginners" 318, and the very broad "music" ran out at 93. Specific multi-word keywords go deep, single broad terms exhaust fast. The same keyword varies between runs too: two walks of "salesforce" returned 316 and 273. Filtering to resultType: video reaches deeper than a broad, unfiltered search.
Is it legal to scrape YouTube? Scraping public data is generally allowed in the US and most of the EU, as long as you don't collect personal data covered by GDPR or CCPA without a lawful basis. This actor only touches YouTube's public search results, but how you use the output is on you.
Apify's full breakdown: Is web scraping legal?.
Can I integrate YouTube Search Scraper with other tools? Push results into Make, Zapier, Slack, Airbyte, GitHub, Google Sheets, Google Drive, and more. Apify treats every actor as a webhook source, so anything that consumes webhooks or pulls from an API works.
Full list: Apify integrations.
Can I use YouTube Search Scraper with the Apify API? Yes. Every run is available over the Apify REST API:
curl -X POST "https://api.apify.com/v2/acts/tubelens~youtube-search-scraper/runs?token=APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"keywords": ["ai agents"]}'
Docs: Apify API reference.
Can I use YouTube Search Scraper through an MCP Server? Yes. Apify ships an MCP server that exposes every actor as a tool, so Claude Desktop, Cursor, and any other MCP-capable client can call YouTube Search Scraper. Setup: Apify MCP docs.
Your feedback Found a bug or need a field that isn't here? Open an issue at console.apify.com/actors/ge5BpC9ZGa5R3Thh9/issues and it goes straight to a human.