YouTube API
Scrape YouTube search results, channels, playlists, and Shorts shelves as structured JSON

The YouTube API is a specialized plugin that searches YouTube and returns structured JSON for the search result page: videos, channels, playlists, Shorts shelves, ads, and the "people also watched" / "related searches" rails. One HTTP call. No JavaScript rendering. No render fee.
Credit Usage: Each successful request costs 10 credits. Pagination uses the sp continuation token that comes back in pagination.next_page_token.
Key Features
- Structured JSON Output: Up to 20 video results per page plus channels, playlists, Shorts shelves, ads, and discovery rails (
people_also_watched,from_related_searches,channels_new_to_you,explore_more). - Result Type Filters:
sptokens for videos-only, channels-only, or playlists-only — switches the populated array. - Sort Modes: relevance (default), rating, upload date, view count.
- Duration Filters: under 4 minutes, 4–20 minutes, over 20 minutes.
- Feature Filters: 4K, HD, LIVE, closed captions.
- Upload Date Filters: last hour, today, this week, this month, this year.
- Localization:
hlcontrols UI language (published-date, duration, view-count strings);glinfluences ranking and shelf eligibility. - Device Emulation: Desktop or mobile layout via
device. - Pagination: Single
spparameter doubles as filter token and continuation cursor — the plugin routes them automatically. - No Blocks or CAPTCHAs: Anti-bot is handled by Scrape.do.
Endpoint
GET https://api.scrape.do/plugin/google/youtubeRequest Parameters
Required
| Parameter | Type | Description |
|---|---|---|
token | string | Your Scrape.do API authentication token |
search_query | string | Search terms (e.g., best laptop 2025, macbook pro m3). Alias: q |
Localization
| Parameter | Type | Default | Description |
|---|---|---|---|
hl | string | en | Interface language (en, de, fr, ja, tr, es, …). Controls published_date, length, and views text. |
gl | string | us | Country code (us, gb, de, fr, jp, …). Influences ranking and which shelves appear. |
For the cleanest locale experience, match hl to gl (e.g., hl=de&gl=de).
Device
| Parameter | Type | Default | Description |
|---|---|---|---|
device | string | desktop | desktop or mobile. Mobile returns the mobile layout. |
Filters, Sort & Pagination
| Parameter | Type | Default | Description |
|---|---|---|---|
sp | string | — | YouTube's opaque token. Short values control sort / result type / duration / features / upload date. Long values are continuation cursors emitted in pagination.next_page_token. The plugin routes both automatically. See Common sp Values. |
Example Usage
Basic search
curl --location --request GET 'https://api.scrape.do/plugin/google/youtube?token=<SDO-token>&search_query=best+laptop+2025'import requests
import json
token = "<SDO-token>"
url = f"https://api.scrape.do/plugin/google/youtube?token={token}&search_query=best+laptop+2025"
response = requests.request("GET", url)
print(json.dumps(response.json(), indent=2))const axios = require('axios');
const token = "<SDO-token>";
const url = `https://api.scrape.do/plugin/google/youtube?token=${token}&search_query=best+laptop+2025`;
axios.get(url)
.then(response => {
console.log(JSON.stringify(response.data, null, 2));
})
.catch(error => {
console.error(error);
});package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
token := "<SDO-token>"
url := fmt.Sprintf(
"https://api.scrape.do/plugin/google/youtube?token=%s&search_query=best+laptop+2025",
token,
)
resp, err := http.Get(url)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}require 'net/http'
require 'json'
token = "<SDO-token>"
url = URI("https://api.scrape.do/plugin/google/youtube?token=#{token}&search_query=best+laptop+2025")
response = Net::HTTP.get(url)
puts JSON.pretty_generate(JSON.parse(response))import java.net.HttpURLConnection;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class YouTubeSearch {
public static void main(String[] args) throws Exception {
String token = "<SDO-token>";
String url = String.format(
"https://api.scrape.do/plugin/google/youtube?token=%s&search_query=best+laptop+2025",
token
);
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
BufferedReader reader = new BufferedReader(
new InputStreamReader(conn.getInputStream())
);
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
System.out.println(response.toString());
}
}using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
string token = "<SDO-token>";
string url = $"https://api.scrape.do/plugin/google/youtube?token={token}&search_query=best+laptop+2025";
using HttpClient client = new HttpClient();
string response = await client.GetStringAsync(url);
Console.WriteLine(response);
}
}<?php
$token = "<SDO-token>";
$url = "https://api.scrape.do/plugin/google/youtube?token={$token}&search_query=best+laptop+2025";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
?>curl "https://api.scrape.do/plugin/google/youtube?search_query=best+laptop+2025&token=YOUR_TOKEN"German locale
curl "https://api.scrape.do/plugin/google/youtube?search_query=beste+laptop+2025&hl=de&gl=de&token=YOUR_TOKEN"published_date, length, and view-count strings render in German.
Sort by view count
curl "https://api.scrape.do/plugin/google/youtube?search_query=best+laptop+2025&sp=CAM%3D&token=YOUR_TOKEN"Channels only
curl "https://api.scrape.do/plugin/google/youtube?search_query=tech+reviewer&sp=EgIQAg%3D%3D&token=YOUR_TOKEN"Populates channel_results[] instead of videos.
Playlists only
curl "https://api.scrape.do/plugin/google/youtube?search_query=learn+golang&sp=EgIQAw%3D%3D&token=YOUR_TOKEN"Populates playlist_results[].
Long-form videos (over 20 minutes)
curl "https://api.scrape.do/plugin/google/youtube?search_query=podcast+interview&sp=EgIYAg%3D%3D&token=YOUR_TOKEN"4K videos only
curl "https://api.scrape.do/plugin/google/youtube?search_query=nature+documentary&sp=EgJwAQ%3D%3D&token=YOUR_TOKEN"Live now
curl "https://api.scrape.do/plugin/google/youtube?search_query=formula+1&sp=EgJAAQ%3D%3D&token=YOUR_TOKEN"Mobile layout
curl "https://api.scrape.do/plugin/google/youtube?search_query=workout+videos&device=mobile&token=YOUR_TOKEN"Pagination
# Page 1
curl "https://api.scrape.do/plugin/google/youtube?search_query=best+laptop+2025&token=YOUR_TOKEN"
# → response includes pagination.next_page_token = "EqwDEhBiZXN0..."
# Page 2: pass that token as sp
curl "https://api.scrape.do/plugin/google/youtube?search_query=best+laptop+2025&sp=EqwDEhBiZXN0...&token=YOUR_TOKEN"The same sp parameter handles both filters and continuation tokens. Short values filter; long values paginate.
Response
Top-Level Structure
{
"search_parameters": { ... },
"search_information": { ... },
"ads_results": [ ... ],
"video_results": [ ... ],
"channel_results": [ ... ],
"playlist_results": [ ... ],
"shorts_results": [ ... ],
"people_also_watched": [ ... ],
"people_also_search_for": [ ... ],
"channels_new_to_you": [ ... ],
"from_related_searches": [ ... ],
"explore_more": [ ... ],
"related_searches": [ ... ],
"pagination": { ... }
}Collections that have no items for a given query are omitted. The one exception is video_results, which is always present — returns [] when empty.
search_parameters
Echo of the request.
{
"engine": "google_youtube",
"search_query": "best laptop 2025",
"gl": "us",
"hl": "en"
}sp appears only when set.
search_information
{ "total_results": 16406969 }| Field | Type | Description |
|---|---|---|
total_results | integer | YouTube's estimated total. May be 0 on some continuation pages. |
video_results_state | string | Status label (e.g., when YouTube auto-corrects spelling). Present only when set. |
video_results[]
Always present. Returns [] when no videos are found.
{
"position_on_page": 2,
"title": "The Best Laptops of 2025",
"link": "https://www.youtube.com/watch?v=PKshhTHyoZU",
"video_id": "PKshhTHyoZU",
"channel": {
"name": "Just Josh",
"link": "https://www.youtube.com/@JustJoshTech",
"verified": true,
"thumbnail": "https://yt3.ggpht.com/..."
},
"published_date": "4 months ago",
"views": 313829,
"length": "12:38",
"description": "Save BIG on Your Laptop: ...",
"extensions": ["4K"],
"thumbnail": {
"static": "https://i.ytimg.com/vi/PKshhTHyoZU/hqdefault.jpg",
"rich": "https://i.ytimg.com/an/PKshhTHyoZU/..."
},
"live": false
}| Field | Type | Always | Description |
|---|---|---|---|
position_on_page | integer | yes | 1-based position |
title | string | yes | Video title |
link | string | yes | Canonical watch URL |
video_id | string | yes | YouTube video id |
channel.name | string | Channel display name | |
channel.link | string | Channel URL | |
channel.verified | bool | true when the channel has a verified badge | |
channel.thumbnail | string | Channel avatar URL | |
published_date | string | Human-readable age, localized to hl ("4 months ago", "vor 4 Monaten") | |
views | integer | View count parsed to integer (47,427 → 47427, 1.2M → 1200000) | |
length | string | Duration ("12:38", "1:05:22") | |
description | string | Snippet text shown under the result | |
extensions | string[] | Badges ("4K", "LIVE", "New", "CC") | |
thumbnail.static | string | Static thumbnail URL | |
thumbnail.rich | string | Animated preview URL when YouTube provides one | |
live | bool | true when the video is a live stream |
channel_results[]
Populated when the query surfaces channel cards — most often with sp=EgIQAg== (Channels filter).
{
"position_on_page": 2,
"title": "Just Josh",
"link": "https://www.youtube.com/@JustJoshTech",
"verified": true,
"handle": "@JustJoshTech",
"subscribers": 379000,
"description": "Finding You The Best Laptop!",
"thumbnail": "https://yt3.ggpht.com/..."
}| Field | Type | Description |
|---|---|---|
position_on_page | integer | 1-based position |
title | string | Channel display name |
link | string | Channel URL |
verified | bool | Verified badge |
handle | string | @handle slug |
subscribers | integer | Subscriber count parsed to integer |
description | string | Channel description snippet |
thumbnail | string | Channel avatar URL |
playlist_results[]
Populated when the query surfaces playlist cards — most often with sp=EgIQAw== (Playlists filter).
{
"position_on_page": 2,
"title": "Best Gaming Laptops 2025",
"link": "https://www.youtube.com/playlist?list=PLFBbwFM8jIbOfpMghQOpdS8E8tJMweb3h",
"channel": {
"name": "Jarrod'sTech",
"link": "https://www.youtube.com/@JarrodsTech"
},
"videos": [
{ "link": "https://www.youtube.com/watch?v=zqjHX_WSyz8&list=PLFBbwFM8jIbOfpMghQOpdS8E8tJMweb3h" }
],
"video_count": 23,
"thumbnail": "https://i.ytimg.com/vi/zqjHX_WSyz8/hq720.jpg"
}| Field | Type | Description |
|---|---|---|
position_on_page | integer | 1-based position |
title | string | Playlist title |
link | string | Playlist URL |
channel.name | string | Uploader display name |
channel.link | string | Uploader channel URL |
videos | object[] | Preview videos. Each entry carries title, length, link when available |
video_count | integer | Total video count on the playlist badge |
thumbnail | string | Playlist cover thumbnail |
shorts_results[]
Array of Shorts shelves. Each shelf is a block that renders inline among regular video results.
{
"position_on_page": 5,
"shorts": [
{
"title": "Top 3 Laptops",
"link": "https://www.youtube.com/shorts/abc123",
"thumbnail": "https://i.ytimg.com/vi/abc123/oardefault.jpg",
"views_original": "2.1M",
"views": 2100000,
"video_id": "abc123"
}
]
}ads_results[]
Promoted entries that appeared on the page.
{
"position_on_page": 1,
"title": "Microsoft® Surface",
"link": "https://www.googleadservices.com/pagead/aclk?...",
"website": "https://www.googleadservices.com/pagead/aclk?...",
"channel": {
"name": "Microsoft",
"thumbnail": "https://lh3.googleusercontent.com/..."
},
"description": "Discover the new Surface lineup.",
"thumbnail": {
"static": "https://lh3.googleusercontent.com/..."
}
}Discovery Rails
Each rail is an array of the same shape as video_results[]. Present only when YouTube renders the corresponding shelf.
| Field | Renders when |
|---|---|
people_also_watched | "People also watched" shelf |
people_also_search_for | "People also search for" shelf (video items) |
channels_new_to_you | "Channels new to you" shelf |
from_related_searches | "From related searches" shelf |
explore_more | "Explore more" / "Latest from" shelf |
related_searches
Keyword refinement chips rendered above results.
[
{ "query": "best laptop 2025 under 1000" },
{ "query": "best gaming laptop 2025" }
]pagination
Present on every response that YouTube advertises a continuation for.
{
"current": "https://www.youtube.com/results?gl=us&hl=en&search_query=best+laptop+2025",
"next": "https://www.youtube.com/results?gl=us&hl=en&search_query=best+laptop+2025&sp=EqwDEhBiZXN0...",
"next_page_token": "EqwDEhBiZXN0..."
}| Field | Type | Description |
|---|---|---|
current | string | The URL the plugin fetched for this page |
next | string | Ready-to-inspect URL for the next page |
next_page_token | string | Raw continuation token. Pass this back as sp on a new request |
Common sp Values
sp is YouTube's opaque filter / sort / pagination token. Short values control filters and sort; long values are continuation cursors emitted in pagination.next_page_token. The plugin accepts both.
Sort Order
sp | Effect |
|---|---|
| (omit) | Relevance (default) |
CAE%3D | Sort by rating |
CAI%3D | Sort by upload date (newest first) |
CAM%3D | Sort by view count |
Result Type
sp | Effect |
|---|---|
EgIQAQ%3D%3D | Videos only |
EgIQAg%3D%3D | Channels only → populates channel_results |
EgIQAw%3D%3D | Playlists only → populates playlist_results |
Duration
sp | Effect |
|---|---|
EgIYAQ%3D%3D | Under 4 minutes |
EgIYAw%3D%3D | 4–20 minutes |
EgIYAg%3D%3D | Over 20 minutes |
Features
sp | Effect |
|---|---|
EgJwAQ%3D%3D | 4K |
EgIgAQ%3D%3D | HD |
EgJAAQ%3D%3D | Live now |
EgQQARgB | Subtitles / closed captions |
Upload Date
sp | Effect |
|---|---|
EgIIAQ%3D%3D | Last hour |
EgIIAg%3D%3D | Today |
EgIIAw%3D%3D | This week |
EgIIBA%3D%3D | This month |
EgIIBQ%3D%3D | This year |
These tokens are defined by YouTube and can change without notice. When a token is no longer accepted, YouTube returns an unfiltered result set.
Notes
- Organic variance. YouTube reorders search results continuously. Consecutive calls with identical parameters can return 60–95% overlap depending on the query. This is inherent to the surface, not the plugin.
- Shorts availability. Shorts shelves appear unpredictably. Expect 0, 1, or multiple
shorts_resultsentries depending on the query and locale. Absence doesn't mean failure. - Ads are best-effort. YouTube runs many layouts in parallel; unknown layouts are skipped rather than returned as partial objects.
- Locale fidelity.
hlcontrols metadata strings (published_date,length, view-count suffixes, shelf titles).glinfluences ranking and which shelves render. - Pagination depth. Continuation pagination is stable for tens of pages. Very deep pagination (>50 pages) may start returning empty
video_resultsas YouTube exhausts the feed.
Error Handling
{ "error": "error_code" }| Status | Error | Cause |
|---|---|---|
400 | token is required | token query parameter missing |
400 | search_query is required | Neither search_query nor q provided |
400 | device must be one of: desktop, mobile | Invalid device value |
400 | failed to construct YouTube URL | Internal URL construction failed (rare — malformed inputs) |
401 | The API Token is inactive or incorrect. | Invalid API token |
500 | decompression failed | Response body decompression failed |
500 | internal server error | Unhandled exception. Report if persistent |
502 | upstream returned truncated page | YouTube returned a partial response. Retry |
502 | failed to parse search results | YouTube returned an unexpected payload shape. Retry; report if persistent |
502 | unexpected response | Upstream returned non-200. Retry |
502 | request failed | Network-level failure. Retry |

