YouTube Search API
Search live YouTube for videos, channels, playlists, and shorts. Results come straight from YouTube at request time — nothing is read from the NexLev catalog.
Base URL: https://prod.dashboard.nexlev.io — see Authentication. This operation costs 🥞 1 quota per request — see Rate Limits & Quota.
Requests are served with automatic failover across upstream data providers. The source field in every response reports whether the primary or the fallback path answered; the payload shape is identical either way.
Not to be confused with the catalog search. GET /api/external/videos/video-search searches NexLev's own indexed video catalog
and supports catalog-only filters such as outlier score, subscriber count, and
RPM. Use that one for research over curated data; use this one when you
need what YouTube is returning right now.
Operations Quick Reference
Rate Limit
20 requests per minute per API key on this endpoint, on top of your plan
quota. Exceeding either returns 429 Too Many Requests — see Rate Limits &
Quota.
Search YouTube
GET /api/external/youtube/searchDescription: Run a YouTube search and return the videos, channels, playlists, and shorts YouTube currently ranks for that query, with optional type, duration, recency, feature, and region filters.
🥞 Quota Cost: 1 quota per request
Each call to this endpoint deducts 1 quota from your account balance. Paginated requests each count separately. Monitor your usage at Manage API Key to avoid interruptions.
When to use this operation:
- Checking what YouTube ranks for a keyword right now
- Keyword and title research against live search results
- Finding channels or playlists by name when you do not have a channel ID
- Sampling shorts for a topic without going channel by channel
Query Parameters
Parameter names are camelCase. Unknown parameters are rejected with a 400 rather than silently ignored — so a typo or a snake_case name (sort_by, upload_date) fails loudly instead of returning unfiltered results.
This endpoint's naming differs from the older channels/* routes, which use
id, sort_by, and forUsername. Do not copy parameter names between them.
Example URLs
https://prod.dashboard.nexlev.io/api/external/youtube/search?query=mkbhd
https://prod.dashboard.nexlev.io/api/external/youtube/search?query=mkbhd&type=video&sortBy=views
cURL Example:
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=mkbhd&type=video&sortBy=views" \
-H "Authorization: Bearer YOUR_API_KEY"Status Code: 200 OK
Response Body:
{
"query": "mkbhd",
"estimatedResults": "360582",
"continuation": "EpoDEgVta2JoZBqQA0VnSVFBVWdV...",
"resultCount": 20,
"source": "primary",
"results": [
{
"type": "video",
"videoId": "_xjxwl1zLMc",
"title": "Framework 13 Pro: The Modular Laptop is Real!",
"channelTitle": "Marques Brownlee",
"channelId": "UCBJycsmduvYEL83R_U4JriQ",
"channelHandle": "@mkbhd",
"description": "The modular Macbook Pro for Linux users. Color me impressed...",
"viewCount": "2643412",
"publishedTime": "3 days ago",
"duration": "12:49",
"isLive": false,
"badges": ["New", "4K"],
"thumbnail": [
{
"url": "https://i.ytimg.com/vi/_xjxwl1zLMc/hq720.jpg?...",
"width": 720,
"height": 404
},
{
"url": "https://i.ytimg.com/vi/_xjxwl1zLMc/hq720.jpg?...",
"width": 360,
"height": 202
}
]
}
],
"filters": {
"type": "video",
"sortBy": "views"
}
}Envelope Fields
query- The query that was executedestimatedResults- YouTube's own estimate of total matches, as a numeric string. May be absent on some responses — do not assume it is presentcontinuation- Token for the next page.nullmeans there are no further pagesresultCount- Number of items inresultsfor this pagesource-"primary"or"fallback"; which leg of the failover chain served the request. Informational onlyresults- The result items. The shape varies bytype— see belowfilters- Echo of the filters that were applied. Onlytype,sortBy,duration,uploadDate, andgeoare echoed —featuresandlangare not. Filters you did not pass are omitted, notnull, so this is{}for an unfiltered query
Result Item Shapes
Every item carries a type discriminator. Branch on it — the available fields differ significantly. Pick a type below for its fields and a sample payload.
Integration Notes
These are all consequences of what YouTube returns upstream — worth handling defensively:
viewCountis not consistently typed. It is a numeric string onvideoitems ("2643412") and a number onshortsitems (29000000). Coerce before doing arithmetic.publishedTimeis a relative human string, not a timestamp —"3 days ago","1 year ago". There is no absolute date in the search payload; call Video Details if you need one.durationis a display string ("12:49"), not seconds.- Shorts are flattened out of their shelf, and their thumbnail array is frequently empty — fall back to
https://i.ytimg.com/vi/{videoId}/hqdefault.jpg. - Channel thumbnails may be protocol-relative (
//yt3.ggpht.com/...). Prefix withhttps:before use. - Mixed results by default. Without
type, a single page can contain videos, channels, playlists, and shorts together, andresultCountcounts them all. - Result counts per page are not fixed and are not controllable — there is no
limitparameter. Observed pages range from ~20 to 80+ items, depending on what YouTube returns and how many shorts got unpacked from their shelf. Paginate withtoken; never assume a page size. type=movieandtype=showare accepted and do return results, but items are tagged with the standard types above —moviecomes back asvideoitems, andshowreturns a mix ofvideo,shorts, andplaylist. There is nomovieorshowitem type.
Pagination
When more results are available, the response returns a continuation token. Pass it back as token to fetch the next page.
How to use continuation tokens:
- Make an initial request without
tokento get the first page - Check the
continuationfield in the response:- If it contains a token, more results are available
- If it is
null, you have reached the last page
- To fetch the next page, repeat the request with
tokenset to that value — and resend the samequeryand all the same filters - Repeat until
continuationisnull
Tokens are opaque and tied to the original query. Changing query, type,
sortBy, or any other filter alongside a token invalidates it — start over
instead.
Example pagination workflow:
# page 1
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=cooking%20tutorials&type=video" \
-H "Authorization: Bearer YOUR_API_KEY"Response: {
"continuation": "EpoDEgVta2JoZBqQA0VnSVFBVWdV...",
"resultCount": 20,
"results": [
/* Array of result items */
]
}# page 2 — feed `continuation` back in as `token`
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=cooking%20tutorials&type=video&token=EpoDEgVta2JoZBqQA0VnSVFBVWdV..." \
-H "Authorization: Bearer YOUR_API_KEY"Response: {
"continuation": null, // null means no more results
"resultCount": 18,
"results": [
/* Array of remaining result items */
]
}Unlike the channels/* endpoints, which signal "no more pages" with an
empty string, this endpoint uses null. Check for both if you share
pagination code across endpoints.
Error Responses
More Examples
# Most-viewed videos for a term
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=mkbhd&type=video&sortBy=views" \
-H "Authorization: Bearer YOUR_API_KEY"
# Channels only
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=mkbhd&type=channel" \
-H "Authorization: Bearer YOUR_API_KEY"
# Shorts, US region
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=cooking&type=shorts&geo=US&lang=en" \
-H "Authorization: Bearer YOUR_API_KEY"
# Short, recent, HD videos with subtitles
curl "https://prod.dashboard.nexlev.io/api/external/youtube/search?query=news&type=video&duration=short&uploadDate=week&features=HD,subtitles" \
-H "Authorization: Bearer YOUR_API_KEY"