# Search YouTube



<MethodPage method="GET" path="/v1/search" credits={1}>
  <MethodSignature name="search" args={[{ name: "query" }, { name: "options", optional: true }]} returns="SearchResponse" />

  Search videos, channels, playlists, movies, or Shorts. Does not consume YouTube Data API quota.

  <Security permission="transcripts:read" />

  <SchemaGroup title="Query Parameters">
    <SchemaField name="q" type="string" location="query" required>
      Search keyword or phrase.
    </SchemaField>

    <SchemaField name="limit" type="number" optional location="query">
      Max results to return, from 1 to 50. Default `20`.
    </SchemaField>

    <SchemaField name="type" type="string" optional location="query">
      `video`, `channel`, `playlist`, `movie`, or `shorts`. Default `video`.
    </SchemaField>

    <SchemaField name="upload_date" type="string" optional location="query">
      `hour`, `today`, `week`, `month`, or `year`.
    </SchemaField>

    <SchemaField name="duration" type="string" optional location="query">
      `short` (under 4m), `medium` (4\~20m), or `long` (over 20m).
    </SchemaField>

    <SchemaField name="sort_by" type="string" optional location="query">
      `relevance` (default), `rating`, `upload_date`, or `view_count`.
    </SchemaField>

    <SchemaField name="cursor" type="string" optional location="query">
      Opaque pagination token for retrieving the next page.
    </SchemaField>
  </SchemaGroup>

  <div id="returns" className="mt-8">
    Response (HTTP 200) [#response-http-200]

    ```jsonc
    {
      "query": string,               // Echoed search string
      "type": string,                // Search target filter applied
      "has_more": boolean,           // Whether additional search results are available
      "next_cursor": string | null,  // Cursor token to fetch the next page of results
      "items": [                     // Array of search result hits
        {
          // Fields that do not apply to a result's type are left out.
          "id": string,              // Video ID, channel ID, or playlist ID
          "type": string,            // "video", "channel", "playlist", or "shorts"
          "title": string,           // Result title
          "description": string,     // Snippet / description
          "author": string,          // Channel name
          "channel_id": string,      // Channel ID
          "length_seconds": number,  // Duration in seconds (for videos)
          "length_text": string,     // Formatted duration string (e.g. "20:40")
          "view_count_text": string, // Formatted view count (e.g. "89K views")
          "published_text": string,  // Relative upload date (e.g. "2 weeks ago")
          "thumbnails": [            // Artwork at one or more sizes
            { "url": string, "width": number, "height": number }
          ],
          "handle": string,          // Channel results: handle (e.g. "@TED")
          "subscriber_count_text": string, // Channel results: e.g. "27.8M subscribers"
          "video_count_text": string,      // Playlist results: e.g. "11 videos" or "9 episodes"
          "badges": string[]         // e.g. ["Verified"]
        }
      ]
    }
    ```
  </div>

  <MethodSamples>
    <LanguageSample language="TypeScript">
      ```ts
      const params = new URLSearchParams({
        q: "AI Agents",
        type: "video",
        upload_date: "month",
        limit: "10",
      });

      const response = await fetch(`https://api.ytapi.dev/v1/search?${params}`, {
        headers: {
          Authorization: `Bearer ${process.env.YT_API_KEY}`,
        },
      });

      const data = await response.json();
      console.log(data.has_more, data.next_cursor);
      console.log(data.items.map((item: { title: string }) => item.title));
      ```
    </LanguageSample>

    <LanguageSample language="Python">
      ```python
      import os
      import requests

      response = requests.get(
          "https://api.ytapi.dev/v1/search",
          headers={"Authorization": f"Bearer {os.environ['YT_API_KEY']}"},
          params={
              "q": "AI Agents",
              "type": "video",
              "upload_date": "month",
              "limit": 10,
          },
      )

      data = response.json()
      print("Has more:", data.get("has_more"))
      for item in data.get("items", []):
          print(item["title"])
      ```
    </LanguageSample>

    <LanguageSample language="cURL">
      ```bash
      curl -X GET "https://api.ytapi.dev/v1/search?q=AI+Agents&type=video&upload_date=month&limit=10" \
        -H "Authorization: Bearer $YT_API_KEY"
      ```
    </LanguageSample>

    <LanguageSample language="Go">
      ```go
      package main

      import (
      	"fmt"
      	"net/http"
      	"os"
      )

      func main() {
      	url := "https://api.ytapi.dev/v1/search?q=AI+Agents&type=video&upload_date=month&limit=10"
      	req, _ := http.NewRequest("GET", url, nil)
      	req.Header.Set("Authorization", "Bearer "+os.Getenv("YT_API_KEY"))

      	resp, err := http.DefaultClient.Do(req)
      	if err != nil {
      		panic(err)
      	}
      	defer resp.Body.Close()
      	fmt.Println(resp.Status)
      }
      ```
    </LanguageSample>
  </MethodSamples>
</MethodPage>
