logo

YouTube API

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

YouTube API

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: sp tokens 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: hl controls UI language (published-date, duration, view-count strings); gl influences ranking and shelf eligibility.
  • Device Emulation: Desktop or mobile layout via device.
  • Pagination: Single sp parameter 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/youtube

Request Parameters

Required

ParameterTypeDescription
tokenstringYour Scrape.do API authentication token
search_querystringSearch terms (e.g., best laptop 2025, macbook pro m3). Alias: q

Localization

ParameterTypeDefaultDescription
hlstringenInterface language (en, de, fr, ja, tr, es, …). Controls published_date, length, and views text.
glstringusCountry 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

ParameterTypeDefaultDescription
devicestringdesktopdesktop or mobile. Mobile returns the mobile layout.

Filters, Sort & Pagination

ParameterTypeDefaultDescription
spstringYouTube'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

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 }
FieldTypeDescription
total_resultsintegerYouTube's estimated total. May be 0 on some continuation pages.
video_results_statestringStatus 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
}
FieldTypeAlwaysDescription
position_on_pageintegeryes1-based position
titlestringyesVideo title
linkstringyesCanonical watch URL
video_idstringyesYouTube video id
channel.namestringChannel display name
channel.linkstringChannel URL
channel.verifiedbooltrue when the channel has a verified badge
channel.thumbnailstringChannel avatar URL
published_datestringHuman-readable age, localized to hl ("4 months ago", "vor 4 Monaten")
viewsintegerView count parsed to integer (47,42747427, 1.2M1200000)
lengthstringDuration ("12:38", "1:05:22")
descriptionstringSnippet text shown under the result
extensionsstring[]Badges ("4K", "LIVE", "New", "CC")
thumbnail.staticstringStatic thumbnail URL
thumbnail.richstringAnimated preview URL when YouTube provides one
livebooltrue 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/..."
}
FieldTypeDescription
position_on_pageinteger1-based position
titlestringChannel display name
linkstringChannel URL
verifiedboolVerified badge
handlestring@handle slug
subscribersintegerSubscriber count parsed to integer
descriptionstringChannel description snippet
thumbnailstringChannel 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"
}
FieldTypeDescription
position_on_pageinteger1-based position
titlestringPlaylist title
linkstringPlaylist URL
channel.namestringUploader display name
channel.linkstringUploader channel URL
videosobject[]Preview videos. Each entry carries title, length, link when available
video_countintegerTotal video count on the playlist badge
thumbnailstringPlaylist 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.

FieldRenders 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

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..."
}
FieldTypeDescription
currentstringThe URL the plugin fetched for this page
nextstringReady-to-inspect URL for the next page
next_page_tokenstringRaw 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

spEffect
(omit)Relevance (default)
CAE%3DSort by rating
CAI%3DSort by upload date (newest first)
CAM%3DSort by view count

Result Type

spEffect
EgIQAQ%3D%3DVideos only
EgIQAg%3D%3DChannels only → populates channel_results
EgIQAw%3D%3DPlaylists only → populates playlist_results

Duration

spEffect
EgIYAQ%3D%3DUnder 4 minutes
EgIYAw%3D%3D4–20 minutes
EgIYAg%3D%3DOver 20 minutes

Features

spEffect
EgJwAQ%3D%3D4K
EgIgAQ%3D%3DHD
EgJAAQ%3D%3DLive now
EgQQARgBSubtitles / closed captions

Upload Date

spEffect
EgIIAQ%3D%3DLast hour
EgIIAg%3D%3DToday
EgIIAw%3D%3DThis week
EgIIBA%3D%3DThis month
EgIIBQ%3D%3DThis 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_results entries 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. hl controls metadata strings (published_date, length, view-count suffixes, shelf titles). gl influences 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_results as YouTube exhausts the feed.

Error Handling

{ "error": "error_code" }
StatusErrorCause
400token is requiredtoken query parameter missing
400search_query is requiredNeither search_query nor q provided
400device must be one of: desktop, mobileInvalid device value
400failed to construct YouTube URLInternal URL construction failed (rare — malformed inputs)
401The API Token is inactive or incorrect.Invalid API token
500decompression failedResponse body decompression failed
500internal server errorUnhandled exception. Report if persistent
502upstream returned truncated pageYouTube returned a partial response. Retry
502failed to parse search resultsYouTube returned an unexpected payload shape. Retry; report if persistent
502unexpected responseUpstream returned non-200. Retry
502request failedNetwork-level failure. Retry

On this page