What it does
Seeing what ranks on YouTube for a keyword usually means searching by hand and copying titles, with no view counts or durations in view. This actor runs YouTube search by keyword through the official YouTube Data API v3 using your own free key, and returns one row per result in YouTube's search order, with searchRank recorded for each.
Search results on their own only carry basic snippet data, so every result is enriched with a videos.list lookup: title, description, channel, published date, duration in seconds, views, likes, comment count, tags, category, default language, thumbnails, live status, made-for-kids flag and a Shorts flag. You can apply YouTube's own filters: order (relevance, date, view count, rating or title), publishedAfter and publishedBefore, regionCode, relevanceLanguage and videoDuration. Setting searchType to channel returns channel rows instead.
It is aimed at YouTube keyword research, trend and competitor tracking, influencer discovery and content gap analysis. Results cost $0.30 per 1,000 plus $0.002 per page of 50, roughly $0.34 per 1,000 all in.
How it works
- Each query in
searchQueriesis sent tosearch.listwith your filters, 50 results per page, up tomaxResultsPerQuery. - The video IDs on each page are looked up with
videos.listso every row carries full stats, duration and tags. - Rows keep the query and the result's rank, and duplicates across queries are removed.
- The run log shows a quota estimate before any call; each page costs 100 search units plus 1 for the video details.
- Search pages that return no rows are not charged, and a
quotaExceedederror stops the run cleanly with the rows already delivered.
Input example
A typical run input (JSON). Every field is also available as a form in the Apify console.
{
"apiKey": "AIzaSy...your-own-key",
"mode": "search",
"searchQueries": [
"web scraping tutorial",
"python requests tutorial"
],
"maxResultsPerQuery": 100,
"order": "viewCount",
"publishedAfter": "2026-01-01",
"regionCode": "US",
"relevanceLanguage": "en",
"videoDuration": "medium"
}All input fields
| Field | Type | Required | Default | What it does |
|---|---|---|---|---|
apiKey | string | no | Required. Your own free YouTube Data API v3 key (starts with AIza). Get one in about a minute: console.cloud.google.com → create a project → APIs & Services → Library → enable "YouTube Data API v3" → Credentials →… | |
mode | string | no | "search" | videos: details and stats for video URLs/IDs (1 quota unit per 50 videos). search: YouTube search results, enriched with full video details (100 units per page of 50). channel: channel stats plus every upload (about 2… |
searchQueries | array | no | [] | One or more search terms. Each page of up to 50 results costs 100 of your 10,000 daily quota units (about 5,000 results per free key per day). YouTube returns at most about 500 results per query. |
maxResultsPerQuery | integer | no | 50 | Search results per query. YouTube returns at most about 500 per query. Each 50 = one search page (100 quota units + 1 for video details). |
order | string | no | "relevance" | search.list order (search mode). |
searchType | string | no | "video" | video: video rows with full details. channel: channel rows with subscriber, video and view counts (search mode). |
publishedAfter | string | no | "" | Optional date (YYYY-MM-DD). In search mode, filters results; in channel mode, only uploads on or after it (and paging stops at older videos, saving quota). |
publishedBefore | string | no | "" | Optional date (YYYY-MM-DD) for search mode. |
regionCode | string | no | "" | Optional 2-letter country code (US, GB, DE …): search results available in that country (search mode). |
relevanceLanguage | string | no | "" | Optional ISO 639-1 language code (en, es, de …): results most relevant to that language (search mode). |
videoDuration | string | no | "any" | Filter search results by duration (search mode, videos only). short < 4 min, medium 4–20 min, long > 20 min. |
videoUrls | array | no | Videos for the videos and comments modes: watch URLs, youtu.be links, Shorts, embed or live URLs, or bare 11-character IDs. Duplicates are removed. videos.list takes 50 IDs per call. | |
channels | array | no | [] | Channel URLs (youtube.com/@handle, /channel/UC…, /user/name), @handles or channel IDs (UC…), for channel mode. Each gives one channel row plus its uploads. |
maxVideosPerChannel | integer | no | 100 | Newest uploads per channel (channel mode). 0 = channel row only. Every 50 videos cost about 2 quota units. |
includeShorts | boolean | no | true | Channel mode. The API does not flag Shorts, so this uses a heuristic (3 minutes or less, not live): turning it off also drops regular videos that short. |
maxCommentsPerVideo | integer | no | 100 | Top-level comments per video (comments mode). Replies are not counted here; they are capped separately by Max replies per comment. 100 top-level comments per quota unit. |
includeReplies | boolean | no | false | Also return replies (comments mode), up to Max replies per comment per thread. Each reply is its own comment-result row, linked by parentId. |
maxRepliesPerComment | integer | no | 20 | With Include replies on: at most this many replies per top-level comment (comments mode), so one huge thread cannot eat the run. 0 = no replies. Up to 5 replies come free with the thread call; more cost 1 quota unit… |
commentOrder | string | no | "time" | time: newest first. relevance: YouTube's top comments. |
searchTerms | string | no | "" | Optional keyword filter applied by YouTube to the comments (comments mode). |
Output example
Each result row records the query and its rank alongside the video's stats, as in these results for one keyword:
| searchQuery | searchRank | title | channelTitle | publishedAt | durationSec | viewCount | likeCount | commentCount | categoryId | isShort |
|---|---|---|---|---|---|---|---|---|---|---|
| web scraping tutorial | 1 | Beginners Guide To Web Scraping with Python - All You Need To Know | Tinkernut | 2021-11-27T13:00:24Z | 456 | 487354 | 13287 | 232 | 27 | false |
| web scraping tutorial | 2 | Learn Web Scraping in 5 Minutes (NO PRIOR KNOWLEDGE) | CodeHead | 2026-03-05T15:01:30Z | 293 | 178100 | 6749 | 96 | 27 | false |
| web scraping tutorial | 3 | Python Tutorial: Web Scraping with BeautifulSoup and Requests | Corey Schafer | 2017-11-08T17:30:00Z | 2748 | 1195647 | 25130 | 1140 | 27 | false |
Pricing
Pay per event: you are charged only for the results you receive, with no subscription. Set a maximum total charge on any run and it stops cleanly at the cap.
| Charged for | When | Price | Per 1,000 | Worked example |
|---|---|---|---|---|
| Video result | Charged per search result (video row with full details and stats) delivered | $0.0003 | $0.30 | 1,000 results = $0.30 (grow_media: $1.00; api-ninja: $5.00 + start fee) |
| Search page | Charged per search page of up to 50 results that returned rows (it costs 100 of your quota units) | $0.002 | $2 | 50 results = $0.002 + 50 × $0.0003 = $0.017 |
| Channel result | Charged per channel row delivered (searchType channel, or channel mode) | $0.0005 | $0.50 | 100 channels = $0.05 |
| Comment result | Charged per comment or reply row delivered (comments mode; author fields stripped) | $0.0005 | $0.50 | 10,000 comments = $5.00 |
| Actor Start (platform start fee) | Charged when the Actor starts running. Number of events charged depends on Actor memory (one event per GB, minimum one event). | $0.00005 | — | One run at 256 MB = $0.0000125 |
Prices are read from the live Apify Store listing when this page is built. The listing is always authoritative.
Try YouTube Search Scraper (Official API) on Apify. Pay only for the results you get.
Run on Apify →Use cases
YouTube keyword research
Run a list of candidate keywords and compare what ranks: view counts, durations and publish dates of the top results show how competitive each term is and what format wins.
Content gap analysis
Filter by publishedAfter and order set to date to see what has been published recently on a topic, or by view count to see what has performed best, and spot angles nobody covers well.
Influencer and channel discovery
Search a niche and look at which channels appear repeatedly in the results, or set searchType to channel to get channel rows with subscriber, video and view counts directly.
Regional and language checks
Use regionCode and relevanceLanguage to see results available in a given country or most relevant to a language, for example before launching content in a new market.
How it compares
| ActorForge YouTube Search | Typical no-key search scrapers | Searching by hand | |
|---|---|---|---|
| Views, likes, duration on every result | Yes (enriched via videos.list) | Often only what the results page shows | Views only, by hand |
| Rank per query recorded | Yes (searchRank) | Varies | Manual |
| Date, region, language, length filters | Yes | Varies | Partly, in the YouTube UI |
| Matches a logged-in user's results | Not exactly (no personalisation) | Varies | Yes |
| Max results per query | About 500 (YouTube's cap) | Varies | As far as you scroll |
| Daily volume on free quota | About 5,000 results per key | No quota | No quota |
| Price per 1,000 results | About $0.34 all in | Varies | Free, but slow |
Search is the most quota-hungry API call, so a free key tops out at about 5,000 results a day; if you need far more volume and do not mind page scraping, a no-key scraper has no quota ceiling. Results also differ slightly from what a logged-in user sees, because the API has no personalisation and no ads.
Limits and honest notes
- You need your own free YouTube Data API v3 key (see the 4-step guide above). Without one the run stops at once with instructions, and nothing is charged.
- Search is quota-hungry: each search.list page of up to 50 results costs 100 of your 10,000 free daily units (plus 1 unit for the video details), so one free key gives about 5,000 search results a day (about 100 pages). Quota resets at midnight Pacific Time. A
quotaExceedederror stops the run cleanly; rows already delivered are kept, and the failed call is free. - About 500 results per query at most. That is YouTube's own cap on search depth, so
maxResultsPerQuerygoes up to 500. For more coverage, split a topic into several narrower queries or date ranges. - Results and their order are YouTube's own search ranking for an API request (no personalisation, no ads). Results may differ slightly from what a logged-in user sees on youtube.com.
- Like counts that the creator hides come back as null. There are no dislike counts (removed by YouTube), no revenue and no watch time.
isShortis a heuristic (3 minutes or less and not live), because the API does not flag Shorts. Use the video length filtershortto get only videos under 4 minutes.- Free rows (type error) cover failed queries and invalid inputs. Search pages that return no rows are not charged.
- You must refresh or delete stored API data within 30 days (YouTube Developer Policies III.E.4). We keep nothing after the run.
- The run's spend limit is respected: each page of rows is charged before it is delivered, and the run stops cleanly at the cap.
FAQ
How many YouTube search results can I get per keyword?
YouTube caps search depth at about 500 results per query, so maxResultsPerQuery goes up to 500. For more coverage, split a topic into narrower queries or separate date ranges with publishedAfter and publishedBefore.
Why does YouTube search use so much API quota?
YouTube charges 100 quota units for each search.list page of up to 50 results, plus 1 unit here for the video details. With 10,000 free units a day, one key gives about 100 pages, or roughly 5,000 results.
Will the results match what I see on youtube.com?
They are YouTube's own search ranking for an API request, with no personalisation and no ads. They can differ slightly from what a logged-in user sees in the browser.
How do I search for YouTube Shorts only?
The API does not flag Shorts. Set videoDuration to short to get videos under 4 minutes, and use the isShort heuristic in each row (3 minutes or less and not live) to narrow further.
What does a search run cost?
Results cost $0.0003 each and each page of up to 50 results that returned rows costs $0.002. So 50 results cost $0.017, and 1,000 results cost about $0.34.
Use it from code
Run the actor through the Apify API with the input above.
cURL
curl -X POST "https://api.apify.com/v2/acts/actor-forge~youtube-search-api/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"apiKey": "AIzaSy...your-own-key", "mode": "search", "searchQueries": ["web scraping tutorial", "python requests tutorial"], "maxResultsPerQuery": 100, "order": "viewCount", "publishedAfter": "2026-01-01", "regionCode": "US", "relevanceLanguage": "en", "videoDuration": "medium"}'JavaScript (Node.js)
// Node.js 18+ (built-in fetch). Set APIFY_TOKEN in your environment.
const input = {
"apiKey": "AIzaSy...your-own-key",
"mode": "search",
"searchQueries": [
"web scraping tutorial",
"python requests tutorial"
],
"maxResultsPerQuery": 100,
"order": "viewCount",
"publishedAfter": "2026-01-01",
"regionCode": "US",
"relevanceLanguage": "en",
"videoDuration": "medium"
};
const res = await fetch(
"https://api.apify.com/v2/acts/actor-forge~youtube-search-api/run-sync-get-dataset-items",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.APIFY_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify(input),
}
);
const items = await res.json();
console.log(items.length, items[0]);Python
# pip install apify-client (set APIFY_TOKEN in your environment)
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run_input = {
"apiKey": "AIzaSy...your-own-key",
"mode": "search",
"searchQueries": [
"web scraping tutorial",
"python requests tutorial"
],
"maxResultsPerQuery": 100,
"order": "viewCount",
"publishedAfter": "2026-01-01",
"regionCode": "US",
"relevanceLanguage": "en",
"videoDuration": "medium"
}
run = client.actor("actor-forge/youtube-search-api").call(run_input=run_input)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)The run-sync-get-dataset-items endpoint waits for the run (up to 5 minutes) and returns the dataset rows directly. For longer runs, start the run asynchronously and read the dataset when it finishes, as the Python example does. Replace APIFY_TOKEN with your own token from the Apify console.
Step-by-step guides
How to Get YouTube Data With the Official API (Free Key, No Code)
Create a free YouTube Data API v3 key in Google Cloud (no billing account), paste it into an ActorForge YouTube actor, and get video, channel…
Related actors
YouTube Scraper (Official API) — Videos, Search & Stats
Bring your own free YouTube API key. Get video details and stats (views, likes, comments, duration, tags), YouTube search results, channel uploads…
$0.40 per 1,000 · video resultYouTube Channel Scraper (Official API) — All Videos & Stats
Bring your own free YouTube API key. Get any channel's stats (subscribers, total views, video count, country) and every upload with views, likes…
$0.40 per 1,000 · video resultKeyword Suggestions — Google, YouTube, Bing Autocomplete
Bulk keyword suggestions from Google, YouTube, Bing and Baidu autocomplete. Expand each seed with a-z, question words or prepositions for long-tail…
$0.30 per 1,000 · seed expandedGoogle Trends Scraper — Trending Now & Interest Over Time
Google Trends scraper and API: Trending Now searches for 125 countries from the official feed (traffic, start time, picture, news articles), plus…
$0.50 per 1,000 · trend resultTry YouTube Search Scraper (Official API) on Apify. Pay only for the results you get.
Run on Apify →