YouTube API endpoint
Returns normalized YouTube search results using YouTube's InnerTube search API. Pass `continuation_token` from a previous response to retrieve the next page. Use `q` as the primary query parameter; `search_query` is accepted as an alias. `hl` and `gl` localize ranking and result context; they default to `en` and `US`. Named filters cover the public web search filters. Account-only chips such as Watched and Unwatched are not exposed.
/youtube/searchReturns search items in the same order they appear on YouTube.
Query parameters:
q: primary search querysearch_query: alias for qcontinuation_token: fetch the next page from a previous responsetype: video, shorts, channel, playlist, moviesort_by: relevance, upload_date, view_count, popularity, rating (popularity and rating currently use the same upstream ordering)upload_date: last_hour, today, this_week, this_month, this_yearduration: under_3_minutes, three_to_20_minutes, over_20_minutes; under_3, three_to_20, and over_20 are aliases for those current ranges. The legacy labels short, medium, and long are also accepted and preserve their previous upstream encodings.features: comma-separated values from live, 4k, hd, subtitles, cc, creative_commons, 360, vr180, 3d, hdr, location, purchasedhl: interface language, default en; accepts language tags such as en, zh-Hans, or jagl: two-letter region code, default US, such as US, GB, JPparams: raw protobuf-encoded filter string; ignored when named filters are presentThe filter encodings are taken from the current YouTube web search UI. last_hour remains supported as a direct upstream filter even though it is not currently shown in the UI. If continuation_token is provided, do not send type, sort_by, upload_date, duration, features, or params; locale fields may still be supplied.
Account-dependent chips such as Watched and Unwatched are intentionally not exposed because they require viewer history/session state. Recently uploaded is also a stateful result chip rather than a stable public filter parameter.
| Field | Filled in, of 20 checked | Values in the sample |
|---|---|---|
| type | 20 | |
| position | 20 | 1 to 20, median 10 |
| title | 20 | |
| url | 20 | youtube.com |
| thumbnail | 20 | yt3.ggpht.com and 1 other host |
| channel_id | 18 | |
| description_snippet | 20 | median 126 characters |
| is_verified | 17 | true in 17 of 17 |
| handle | 1 | |
| subscriber_count | 1 | |
| video_id | 19 | |
| channel_title | 19 | |
| duration | 19 | |
| duration_seconds | 19 | 71 to 4,496, median 924 |
| published_text | 19 | |
| view_count | 19 | |
| short_view_count | 19 | |
| channel_thumbnail | 19 | yt3.ggpht.com |
| badges | 14 | median 1 entry |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| q | string | No | Search query | gpt | |
| search_query | string | No | Alias for q | gpt | |
| continuation_token | string | No | Pagination token returned by a previous request | ||
| type | string | No | Filter by type Allowed values: video, shorts, channel, playlist, movie. | ||
| sort_by | string | No | Sort results Allowed values: relevance, upload_date, view_count, popularity, rating. | ||
| upload_date | string | No | Filter by upload date Allowed values: last_hour, today, this_week, this_month, this_year. | ||
| duration | string | No | Filter by duration; short, medium, and long preserve their previous upstream encodings Allowed values: under_3_minutes, three_to_20_minutes, over_20_minutes, under_3, three_to_20, over_20, short, medium, long. | ||
| features | string | No | Comma-separated feature filters. Allowed values: live, 4k, hd, subtitles, cc, creative_commons, 360, vr180, 3d, hdr, location, purchased | hd,subtitles | |
| hl | string | No | YouTube interface language | en | |
| gl | string | No | Two-letter YouTube region code | US | |
| params | string | No | Raw protobuf-encoded search filter (base64) | ||
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/youtube/search?q=coffee&type=video&sort_by=relevance&upload_date=last_hour&duration=under_3_minutes" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"query": "gpt",
"estimated_results": 9895225,
"items": [
{
"type": "video",
"position": 1,
"title": "ChatGPT Explained",
"url": "https://www.youtube.com/watch?v=abc123xyz89",
"thumbnail": "https://i.ytimg.com/vi/abc123xyz89/hq720.jpg",
"video_id": "abc123xyz89",
"channel_title": "OpenAI",
"channel_id": "UCXZCJLdBC09xxGZ6gcdrc6A",
"duration": "12:34",
"duration_seconds": 754,
"published_text": "2 days ago",
"view_count": "123,456 views",
"short_view_count": "123K views",
"description_snippet": "A concise walkthrough of GPT features.",
"channel_thumbnail": "https://yt3.ggpht.com/channel-thumb",
"is_verified": true,
"badges": [
"HD",
"CC"
]
},
{
"type": "channel",
"position": 2,
"title": "OpenAI",
"url": "https://www.youtube.com/@OpenAI",
"thumbnail": "https://yt3.ggpht.com/channel-avatar",
"channel_id": "UCXZCJLdBC09xxGZ6gcdrc6A",
"handle": "@OpenAI",
"subscriber_count": "1.93M subscribers",
"description_snippet": "OpenAI's mission is to ensure AGI benefits all of humanity.",
"is_verified": true
},
{
"type": "playlist",
"position": 3,
"title": "Python Language Full Course (2026)",
"url": "https://www.youtube.com/playlist?list=PL1234567890abcdef",
"thumbnail": "https://i.ytimg.com/vi/pl123/hqdefault.jpg",
"playlist_id": "PL1234567890abcdef",
"channel_title": "Shradha Khapra",
"channel_id": "UC1XBh-m27kkgwLAwu_SRJBg",
"video_count": "9 lessons"
}
],
"continuation_token": "NEXT_TOKEN"
}
}Request schema
No body schema
Response schema
#/definitions/youtube.searchResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | 200 | |||
| data | youtube.SearchResponse | No | ||||
| data.continuation_token | string | No | NEXT_TOKEN | Token to pass in the next request to get the following page. Omitted on the last page. | ||
| data.estimated_results | integer | No | 9895225 | Approximate number of results YouTube reports for the search. | ||
| data.items | array | No | Videos, channels and playlists on this page of results. | |||
| data.items[].badges | array | No | HD,CC | Badge labels shown on the video, such as `HD` or `CC`. | ||
| data.items[].channel_id | string | No | UCXZCJLdBC09xxGZ6gcdrc6A | YouTube channel ID, starting with `UC`. | ||
| data.items[].channel_thumbnail | string | No | https://yt3.ggpht.com/example=s68-c-k-c0x00ffffff-no-rj | URL of the publishing channel's avatar image. | ||
| data.items[].channel_title | string | No | OpenAI | Name of the channel that published the video or playlist. | ||
| data.items[].description_snippet | string | No | A concise walkthrough of GPT features. | Short excerpt of the video or channel description shown in the results. | ||
| data.items[].duration | string | No | 12:34 | Video length as YouTube displays it, such as `12:34`. | ||
| data.items[].duration_seconds | integer | No | 754 | Video length in seconds. | ||
| data.items[].handle | string | No | @OpenAI | Channel handle, starting with `@`. Set for channel results. | ||
| data.items[].is_live | boolean | No | Whether the video is a live stream. | |||
| data.items[].is_short | boolean | No | Whether the video is a YouTube Short. | |||
| data.items[].is_verified | boolean | No | Whether the channel carries a verified badge. | |||
| data.items[].playlist_id | string | No | PL1234567890abcdef | YouTube playlist ID. Set for playlist results. | ||
| data.items[].position | integer | No | 1 | Position of the item on this page of results, starting at 1. | ||
| data.items[].published_text | string | No | 2 days ago | Upload time as YouTube displays it, such as `2 days ago`. | ||
| data.items[].short_view_count | string | No | 123K views | Abbreviated view count as YouTube displays it, such as `123K views`. | ||
| data.items[].subscriber_count | string | No | 1.93M subscribers | Subscriber count as YouTube displays it, such as `1.93M subscribers`. | ||
| data.items[].thumbnail | string | No | https://i.ytimg.com/vi/abc123/hq720.jpg | URL of the item's thumbnail image. | ||
| data.items[].title | string | No | ChatGPT Explained | Video or playlist title, or channel name. | ||
| data.items[].type | string | No | video | Kind of result: `video`, `channel` or `playlist`. | ||
| data.items[].url | string | No | https://www.youtube.com/watch?v=abc123 | Link to the video, channel or playlist on YouTube. | ||
| data.items[].video_count | string | No | 9 lessons | Number of videos as YouTube displays it, such as `12 videos`. Set for channel and playlist results. | ||
| data.items[].video_id | string | No | abc123xyz89 | YouTube video ID. Set for video results. | ||
| data.items[].view_count | string | No | 123,456 views | View count as YouTube displays it, such as `123,456 views`. | ||
| data.query | string | No | gpt | Search text that was run. | ||
| msg | string | No | OK |
| Status | Description | Schema |
|---|---|---|
| 400 | Missing or invalid parameters | #/definitions/app.Response |
| 429 | Rate limit exceeded | #/definitions/app.Response |
| 500 | Internal server error | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/youtube/search?q=coffee&type=video&sort_by=relevance&upload_date=last_hour&duration=under_3_minutes" \
-H "x-api-key: $CRAWLORA_API_KEY"