# Get playlist



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

  Returns the playlist's details and its first page of videos (up to 100). For the next page, call the same endpoint with `cursor` set to the `next_cursor` you got; repeat until `has_more` is `false`. Each page costs 1 credit. Pages after the first carry the videos only, not the playlist details.

  <Security permission="videos:read" />

  <SchemaGroup title="Path Parameters">
    <SchemaField name="id" type="string" location="path" required>
      Playlist ID (`PL...`) or a full YouTube playlist URL.
    </SchemaField>
  </SchemaGroup>

  <SchemaGroup title="Query Parameters">
    <SchemaField name="cursor" type="string" optional location="query">
      `next_cursor` from the previous page. Leave it out for the first page.
    </SchemaField>
  </SchemaGroup>

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

    ```jsonc
    {
      "playlist_id": string,          // Canonical playlist ID (PL...)
      "title": string,                // Playlist title
      "video_count": number,          // Total videos in the playlist
      "view_count_text": string,      // Formatted view count (e.g. "25,616 views")
      "author": string,               // Owner channel name
      "thumbnails": [                 // Artwork at one or more sizes
        {
          "url": string,
          "width": number,
          "height": number
        }
      ],
      "videos": [                     // This page of videos
        {
          "video_id": string,         // 11-character video ID
          "title": string,            // Video title
          "index": number,            // Position within the playlist (1-based)
          "length_seconds": number,   // Duration in seconds
          "length_text": string,      // Duration text (e.g. "3:00:00")
          "author": string            // Video creator name
        }
      ],
      "has_more": boolean,            // Whether another page is available
      "next_cursor": string | null    // Opaque cursor for the next page, or null
    }
    ```
  </div>

  <MethodSamples>
    <LanguageSample language="TypeScript">
      ```ts
      const id = "PL-_QwjtlyjHZRRt4AQnQtYFxbiVP-oyuF";
      const response = await fetch(`https://api.ytapi.dev/v1/playlists/${id}`, {
        headers: {
          Authorization: `Bearer ${process.env.YT_API_KEY}`,
        },
      });

      const playlist = await response.json();
      console.log(playlist.title, playlist.next_cursor);
      ```
    </LanguageSample>

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

      playlist_id = "PL-_QwjtlyjHZRRt4AQnQtYFxbiVP-oyuF"
      response = requests.get(
          f"https://api.ytapi.dev/v1/playlists/{playlist_id}",
          headers={"Authorization": f"Bearer {os.environ['YT_API_KEY']}"},
      )

      print(response.json())
      ```
    </LanguageSample>

    <LanguageSample language="cURL">
      ```bash
      curl -X GET "https://api.ytapi.dev/v1/playlists/PL-_QwjtlyjHZRRt4AQnQtYFxbiVP-oyuF" \
        -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/playlists/PL-_QwjtlyjHZRRt4AQnQtYFxbiVP-oyuF"
      	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>
