YouTube Search Results & Rank Tracker Scraper
Pricing
from $0.18 / 1,000 results
YouTube Search Results & Rank Tracker Scraper
Give it keywords and get YouTube search results with rank, title, channel, views and duration. Rank tracker mode compares keyword rankings with the last run: rank change, new and dropped results, target videos or channels flagged, several countries per run. $0.24 per 1,000 results, failures free.
Pricing
from $0.18 / 1,000 results
Rating
0.0
(0)
Developer
Gautham Krishna
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
2 hours ago
Last modified
Categories
Share
Get YouTube search results as clean rows with rank, title, channel and views, for SEO teams tracking keyword rankings and marketers looking for creators.
Use cases, each with a ready-to-run example:
- Track where a channel ranks for a keyword
- Compare search results in the US, the UK and India
- Find the most viewed videos for a keyword
- Search YouTube Shorts for a keyword
- Find small creators in a niche by subscriber count
- Get views, likes and tags for a list of video URLs
Each result also has the duration, upload age, thumbnail and snippet. Add video URLs to get full details for specific videos too: description, tags, likes, category and upload date. Rank tracker mode compares each result with the last run, flags your own or competitors' videos and channels, and covers several countries in one run. Channel discovery finds YouTube channels on a topic within a subscriber range, such as small creators with 1,000 to 100,000 subscribers for outreach.
You pay $0.24 per 1,000 results ($0.00024 each), and less on Apify Store discount tiers (Bronze, Silver, Gold), down to $0.18 per 1,000 on Gold.
Failed queries, unavailable videos, invalid input, dropped rows and channels left out by a subscriber range are never charged.
In the final test run, 56 queries in 15 languages all returned results, and all 50 real videos in the lookup returned full details.
What you get per result
| Field | What it holds |
|---|---|
query, rank | The search it came from and its position, starting at 1 |
type | video, short, channel, playlist or movie |
id, url | Video, channel or playlist ID and its link |
title, thumbnail | As shown in the results |
channelName, channelId, channelUrl, channelVerified | The uploader. Joint uploads also list every channel in collaborators |
viewCount, viewCountText | Views as a number and as YouTube shows them |
duration, durationSeconds | Length, such as 1:00:06 and 3606 |
publishedTimeText | Upload age as shown, such as 6 years ago |
descriptionSnippet | The description excerpt shown under the result |
badges | Labels such as 4K, CC, New or LIVE |
isLive, watchingCount | Live streams show viewers watching now instead of views |
subscriberCountText, channelHandle | On channel results |
subscriberCount | On channel results, the subscriber count as a number, such as 90600 for 90.6K subscribers. It is as rounded as YouTube shows it, and null when the channel hides its count. It is always the last field of a channel row |
videoCountText | On playlist and channel results |
status | ok, no_results, unavailable, invalid_input, error, or dropped (rank tracker only) |
Rows from the video lookup add:
| Field | What it holds |
|---|---|
description | The full description |
keywords | The uploader's tags |
likeCount | Likes, when the uploader shows them |
category | Such as Education or Music |
publishDate, uploadDate | Exact dates with time zone |
isLive, isLiveContent, liveStartTime, liveEndTime | Live status and stream times |
isShort, isFamilySafe, isUnlisted | Flags from YouTube |
Rows from the rank tracker options add:
| Field | When | What it holds |
|---|---|---|
country | countries is set | The country this result was searched from |
isTarget | targets is set | true when the result is one of your target videos, or comes from one of your target channels |
previousRank | compareWithLastRun is on | Its rank in the last run, or null if it was not in it |
rankChange | compareWithLastRun is on | previousRank minus rank, so 3 means it moved up three places |
isNew | compareWithLastRun is on | true when it was not in the last run's results. All three fields are null on the first run |
Input
{"queries": ["python tutorial for beginners", "receta de paella valenciana"],"maxResultsPerQuery": 40,"type": "video","uploadDate": "month","duration": "long","sortBy": "viewCount","videos": ["https://www.youtube.com/watch?v=jNQXAC9IVRw", "dQw4w9WgXcQ"]}
| Option | Values |
|---|---|
type | all, video, shorts, channel, playlist, movie |
uploadDate | any, hour, today, week, month, year |
duration | any, short (under 4 min), medium (4 to 20 min), long (over 20 min) |
sortBy | relevance, viewCount |
features | live, 4k, hd, subtitles, creativeCommons, 360, vr180, hdr |
language, country | Interface language such as en and two-letter country such as US. Results are localised for that country |
includeShortsShelves | Also return the Shorts that YouTube shows in shelves between results |
countries | Several two-letter countries, such as ["US", "IN", "DE"]. Every query runs once per country |
compareWithLastRun | Rank tracker mode, see below |
targets | Videos (URL or ID) and channels (@handle, channel URL or UC... ID) to flag with isTarget |
minSubscribers, maxSubscribers | Keep only channels in this subscriber range, see below |
You can send only queries, only videos, or both.
The video lookup accepts watch, youtu.be, Shorts, embed and live links, plus bare 11-character IDs.
Output example
These are real rows from a test run. A search result:
{"query": "python tutorial for beginners","rank": 1,"type": "video","id": "kqtD5dpn9C8","url": "https://www.youtube.com/watch?v=kqtD5dpn9C8","title": "Python for Beginners - Learn Coding with Python in 1 Hour","channelName": "Programming with Mosh","channelId": "UCWv7vMbMWH4-V0ZXdmDpPBA","channelUrl": "https://www.youtube.com/@programmingwithmosh","viewCount": 25573529,"viewCountText": "25,573,529 views","duration": "1:00:06","durationSeconds": 3606,"publishedTimeText": "6 years ago","thumbnail": "https://i.ytimg.com/vi/kqtD5dpn9C8/hq720.jpg?sqp=-oaymwEXCNAFEJQDSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLAlOSbnBnoUI-N9v2_o-DYUecBN7A","descriptionSnippet": "Learn Python basics in just 1 hour! Perfect for beginners interested in AI and coding. ⚡ Plus, get 6 months of PyCharm FREE with ...","badges": [],"isLive": false,"channelVerified": true,"collaborators": [],"watchingCount": null,"status": "ok"}
A video lookup, with the search-only fields that are null on these rows (query, rank, viewCountText and so on) left out:
{"type": "video","id": "jNQXAC9IVRw","url": "https://www.youtube.com/watch?v=jNQXAC9IVRw","title": "Me at the zoo","channelName": "jawed","channelId": "UC4QobU6STFB0P71PMvOGN5A","channelUrl": "https://www.youtube.com/@jawed","viewCount": 441938487,"duration": "0:19","durationSeconds": 19,"thumbnail": "https://i.ytimg.com/vi/jNQXAC9IVRw/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG-AoAC8AGKAgwIABABGFUgWShlMA8=&rs=AOn4CLA9eLBatYv9WbkD4BbZ2Im-biSPTw","isLive": false,"input": "https://www.youtube.com/watch?v=jNQXAC9IVRw&t=10","status": "ok","description": "Microplastics are accumulating in human brains at an alarming rate\nhttps://www.youtube.com/watch?v=0PT5c1z3LL8\n\n“Nanoplastics and Human Health” with Matthew J Campen, PhD, MSPH\nhttps://www.youtube.com/watch?v=RRBN_4L09Mg\n\n00:00 Intro\n00:05 The cool thing\n00:17 End","keywords": ["me at the zoo", "jawed karim", "first youtube video"],"likeCount": 20034803,"category": "Film & Animation","publishDate": "2005-04-23T20:31:52-07:00","uploadDate": "2005-04-23T20:31:52-07:00","isLiveContent": false,"liveStartTime": null,"liveEndTime": null,"isShort": false,"isFamilySafe": true,"isUnlisted": false}
A video that does not exist comes back as "status": "unavailable", "message": "Video unavailable" and costs nothing.
Find channels by subscriber count
Set minSubscribers, maxSubscribers or both to get channels on a topic within a subscriber range.
{"queries": ["sourdough baking", "watercolor painting", "home espresso"],"type": "channel","maxResultsPerQuery": 50,"minSubscribers": 1000,"maxSubscribers": 100000}
A kept channel from the test run, with the empty fields left out:
{"query": "sourdough baking","rank": 4,"type": "channel","id": "UCym_8JHA4htlFLIHGpNZGrQ","url": "https://www.youtube.com/@FullProofBaking","title": "Full Proof Baking","channelName": "Full Proof Baking","channelId": "UCym_8JHA4htlFLIHGpNZGrQ","channelUrl": "https://www.youtube.com/@FullProofBaking","thumbnail": "https://yt3.googleusercontent.com/ytc/AIdro_ndWmzk7nuUIL6cUYxx64d_L0Vjq4foburvGQ33-j5GHw=s176-c-k-c0x00ffffff-no-rj-mo","descriptionSnippet": "Sourdough-obsessed home baker from Chicago.","channelVerified": false,"channelHandle": "@FullProofBaking","subscriberCountText": "90.6K subscribers","status": "ok","subscriberCount": 90600}
A range always searches channels.
With type set to all, the search switches to channels, since mixed results hold too few channels to fill a list.
With type set to video, shorts, playlist or movie, the run returns one free row that explains the mismatch.
rank stays the channel's position in YouTube's channel results, so ranks skip the channels left out.
In the search above, ranks 2 and 3 were outside the range.
maxResultsPerQuery counts the channels kept.
The scraper reads more pages to fill it while at least about a third of the channels read so far are in range, then stops, so a narrow range can return fewer.
Channels outside the range, and channels that hide their count, are left out and cost nothing.
The status message says how many were left out.
The count comes from the text YouTube shows in your language, such as 1.2M, 51,5 K, 124.000, 22.2 लाख or 12.4万.
A channel near a limit can fall either side of it as its rounded count changes.
The dataset's Channels view shows rank, channel, handle, subscribers and link side by side.
The output has public channel details only, with no emails or other contact data.
Rank tracker mode
Turn on compareWithLastRun and schedule the same input daily or weekly.
Each run compares every query in every country with the last complete run of it in your account.
{"queries": ["python tutorial for beginners", "receta de paella valenciana"],"maxResultsPerQuery": 20,"countries": ["US", "IN", "DE"],"compareWithLastRun": true,"targets": ["@programmingwithmosh", "UC8butISFwT-Wl7EV0hUK0BQ", "https://youtu.be/kqtD5dpn9C8"]}
A result from the second run of a test, with some search fields left out:
{"query": "python tutorial for beginners","rank": 2,"type": "video","id": "kqtD5dpn9C8","url": "https://www.youtube.com/watch?v=kqtD5dpn9C8","title": "Python for Beginners - Learn Coding with Python in 1 Hour","channelName": "Programming with Mosh","channelId": "UCWv7vMbMWH4-V0ZXdmDpPBA","viewCount": 25639490,"isTarget": true,"previousRank": 1,"rankChange": -1,"isNew": false,"country": "US","status": "ok"}
A result that was in the last run and is gone now comes back as a free dropped row, with its last rank and the details it had then.
This one is from the same run, with the empty fields left out:
{"query": "python tutorial for beginners","rank": null,"type": "video","id": "qwAFL1597eM","url": "https://www.youtube.com/watch?v=qwAFL1597eM","title": "Python Tutorial for Beginners (with mini-projects)","channelName": "freeCodeCamp.org","channelId": "UC8butISFwT-Wl7EV0hUK0BQ","previousRank": 18,"rankChange": null,"isNew": false,"status": "dropped","message": "Ranked 18 in the last run on 2026-10-16, missing from this run's 20 results","isTarget": true,"country": "US"}
Each query, country, language, filter set and max results value has its own history.
Change any of them and the next run starts a new history, because a deeper or differently filtered list is not comparable.
A query that failed, returned nothing or stopped at your maximum charge keeps the previous history, so the next run still compares with the last complete run.
The history lives in a key-value store named youtube-search-scraper-monitor in your own Apify account.
Delete it to start over.
The dataset's Rank tracker view shows country, rank, last run rank, change, new and target side by side.
With a subscriber range on, the range is part of the history too.
A channel from the last run counts as dropped only when this run read past its old rank and did not find it.
A channel this run found outside the range, or one past where this run stopped reading, is not a dropped row.
Targets given as @handle, /c/ or /user/ links are looked up once per run to find the channel ID, so they also match results whose channel link has no handle.
A target YouTube does not know comes back as a free invalid_input row.
Run it on a schedule
A daily or weekly run of the rank tracker shows how your videos and channels move for the searches you care about.
We tracked 60 channel searches on 17 Oct and ran them again on 20 Oct.
Of the 1,423 channels returned, 338 were new to their search, 973 had moved and 112 held their rank, and 280 free dropped rows named the channels that fell out.
- Set your input with
compareWithLastRun: trueand click Save as a new task. - On the task page, click Actions, then Schedule, and pick how often it runs. Apify's schedules guide covers cron times and time zones.
- On the task's Integrations tab, choose where each run's results go.
| Integration | What it does |
|---|---|
| Slack | Posts a message to your channel when a run finishes |
| Google Drive | Saves each run's results as a file in your Drive |
| Webhook | Sends the finished run, with its dataset ID, to your own URL |
| Make, Zapier, n8n | Adds each new row to a Google Sheet, a CRM or a database |
Each row has a stable id, the video or channel ID, so a sheet can chart one result's rank across runs.
How well it works
In the test run, 56 search queries in 15 languages (English, Spanish, Hindi, Tamil, Japanese, Korean, Arabic, Russian, Portuguese, German, French, Chinese, Turkish, Indonesian and Vietnamese) all returned results, 40 per query for most. All 50 real videos in the lookup returned full details. The Shorts, channel, playlist, movie, upload date, duration, sort and feature filters were each checked in separate runs.
In the rank tracker test, 56 queries in 3 countries (US, IN and DE) ran twice, 5 minutes apart.
All 168 query and country pairs returned results both times.
A script checked every previousRank, rankChange, isNew and dropped row of the second run against the first run's ranks, and found no mismatch.
Every result from the 4 target channels and the target video was flagged, and no other result was.
In the channel discovery test, 60 channel searches in English with a 1,000 to 100,000 subscriber range all returned channels in range, 2,096 in all, while 3,022 channels outside it were left out for free.
20 of the kept channels were checked against their channel pages, and all 20 counts matched.
Runs in Japanese, Hindi, Spanish and German returned channels in range for all 20 of their searches.
The count reader was also checked on the same searches in 83 interface languages, and all 2,067 counts it could compare matched the English count.
In a rank tracker test with the range on, the same 60 searches ran twice, and a script found no mismatch in the second run's previousRank, rankChange, isNew and 253 dropped rows.
Use it from AI agents
The scraper works as a tool through the Apify MCP server in Claude, Cursor, VS Code and other MCP clients. An agent can search YouTube for a topic and get back ranked rows it can filter, summarise or pass to a transcript tool.
You can also call it through the Apify API or the Python and JavaScript clients, and schedule it or connect it to Make, Zapier and n8n.
Pricing
Prices are per 1,000 results.
| Event | No discount | Bronze | Silver | Gold |
|---|---|---|---|---|
| Result returned (a search row or a looked-up video) | $0.24 | $0.22 | $0.20 | $0.18 |
Query with no results, unavailable video, invalid input, failed request, dropped row or channel outside the subscriber range | Free | Free | Free | Free |
Bronze, Silver and Gold are Apify Store discount tiers, and Apify's Pricing tab shows them as Starter, Scale and Business. Apify decides which tier an account is on. Set a maximum cost per run in the run options. The scraper stops once that limit is reached.
More from heyitsgautham
Other actors from the same account.
- YouTube Transcript & Subtitles Scraper for specific videos, or when you want every video on a channel or playlist with channel stats and up to 20,000 videos per source.
- YouTube Video & Shorts Comments Scraper with Replies for the comments and replies on a video or Short, for sentiment analysis and audience research.
- YouTube Channel & Playlist Transcripts for every video on a channel or playlist, with channel stats and up to 20,000 videos per source.
- YouTube & TikTok Transcripts MCP Server for AI Agents for giving an AI agent YouTube and TikTok transcripts, YouTube search and comments as MCP tools, with nothing to host.
- Google Trends Scraper: Related Queries & Trending Searches for Google Trends interest over time, related queries and Trending Now.
FAQ
Why did a query return fewer results than I asked for?
YouTube decides how deep a search goes.
With result type All, YouTube often runs out of regular results after 30 to 60 and fills the rest of the feed with Shorts shelves.
Set type to video for longer lists, or turn on includeShortsShelves to get those Shorts as rows.
A narrow filter such as uploadDate: today on a niche query can return only a handful of results, because that is all YouTube shows.
Why did a subscriber range return fewer channels than I asked for? YouTube's channel results for a topic mix sizes, and big channels tend to come first. The scraper keeps reading while at least about a third of the channels read are in your range, so a narrow range such as 1,000 to 10,000, or a high floor such as 1,000,000, can end with fewer channels. Try a wider range, or several related queries.
Can I sort by upload date?
YouTube removed that sort option from search in 2025.
Use the uploadDate filter instead.
Why do Shorts rows have no publishedTimeText?
YouTube shows Shorts in shelves without a channel or date.
The scraper fills channel, exact views, duration and publishDate with one extra small request per Short, so you get the exact date instead of text like "2 days ago".
Why do ranks move between two runs a few minutes apart? YouTube does not show every logged-out visitor the same order, and each run reaches YouTube from different residential IPs in the country. In the rank tracker test, the second run, 5 minutes after the first, had 1,673 top-10 results. 759 of them were at most one place from their last rank, 406 sat at the same rank, and 260 were new. Read single moves of one or two places as noise, and look at trends over several runs.
Does it use the official YouTube Data API? No. It reads the same public data the YouTube website shows to a logged-out visitor, so you need no API key and have no daily quota.
Are view counts exact?
Yes for videos.
Live streams have viewCount: null and the number of people watching in watchingCount.
Limitations
- Results depend on the
countryandlanguageyou pick, and on YouTube's own ranking, which changes over time. - Mixes (auto-generated playlists) have no single channel, so their channel fields are empty.
- Like counts are missing when the uploader hides them.
- Subscriber counts are the rounded figures YouTube shows, such as 90.6K. YouTube does not show exact counts to visitors.
- YouTube can change its site at any time. If something breaks, open an issue on the Issues tab.