Skip to content

Все для WordPress, веб-розробки — і не тільки

📺 Як отримати відео з плейлиста YouTube через API: робочий код за 15 хвилин

📺 Як отримати відео з плейлиста YouTube через API: робочий код за 15 хвилин

Вставили посилання на YouTube-відео в редактор, працює. Але коли на сайті потрібен цілий плейлист, який сам підхоплює нові відео, копіювати посилання вручну щоразу перетворюється на рутину.

Скрипт на PHP з YouTube Data API v3 вирішує завдання повністю: забирає всі відео з будь-якого публічного плейлиста, віддає JSON, а ви виводите їх як завгодно, сіткою карток, списком, галереєю. Налаштування займає 15 хвилин, потрібен лише API-ключ і базовий PHP.

Нижче, робочий код під WordPress з обробкою помилок, пагінацією і кешуванням. Підхід універсальний: працює в будь-якому PHP-проєкті, не лише під WP.

💡 Швидкий огляд:

  • Створюємо API-ключ у Google Cloud Console і прив'язуємо до YouTube Data API v3
  • Надсилаємо запит до playlistItems і отримуємо JSON з усіма відео плейлиста
  • Парсимо відповідь, збираємо прев'ю та посилання, виводимо сіткою на сторінці
  • Додаємо пагінацію для плейлистів довших за 50 відео і кешування через set_transient()

Крок 1: Створюємо ключ YouTube Data API v3

API-ключ ідентифікує ваш застосунок перед YouTube і враховує квоти. Створюється безплатно, добовий ліміт, 10 000 одиниць. Одного ключа вистачає з запасом для більшості сайтів.

Зайдіть у Google Cloud Console під своїм Google-акаунтом. Створіть новий проєкт, кнопка вибору проєкту у верхній панелі, потім New Project. Назвіть осмислено, наприклад my-youtube-feed.

Після створення проєкту перейдіть до APIs & Services → Library. У рядку пошуку наберіть YouTube Data API v3 і натисніть Enable. Без цього кроку ключ не прив'яжеться до потрібного API, і запити повернуть 403.

Тепер, сам ключ. У бічному меню відкрийте Credentials, натисніть Create Credentials → API key. Система згенерує ключ і покаже його в модальному вікні. Одразу скопіюйте: після закриття вікна ключ видно в списку, але його значення частково приховане.

Обов'язково натисніть Restrict key. У розділі API restrictions виберіть YouTube Data API v3, тоді ключ не спрацює для інших API, навіть якщо потрапить у відкритий репозиторій. Для локальної розробки HTTP-referrer можна залишити порожнім.

Ключ має вигляд AIzaSyD-.... Збережіть його в wp-config.php через define('YOUTUBE_API_KEY', '...') і додайте wp-config.php до .gitignore. Не хардкодьте ключ у коді теми.

Крок 2: Отримуємо відео з плейлиста

Для запиту потрібні дві речі: API-ключ та ID плейлиста. ID видобувається з URL: відкрийте плейлист на YouTube, скопіюйте адресний рядок. Параметр list= в URL і є playlist ID: наприклад, PLp0YhAQYkolGq1e6r1m5....

Базовий PHP-запит до endpoint playlistItems:

1$api_key = 'AIzaSy...'; // ваш ключ из шага 1
2$playlist_id = 'PLp0YhAQYkolG...'; // ID плейлиста из URL
3
4$api_url = 'https://www.googleapis.com/youtube/v3/playlistItems' .
5 '?part=snippet' .
6 '&maxResults=50' .
7 '&playlistId=' . urlencode($playlist_id) .
8 '&key=' . $api_key;
9
10$response = file_get_contents($api_url);
11$data = json_decode($response, true);
12
13if (json_last_error() !== JSON_ERROR_NONE) {
14 die('Ошибка парсинга JSON: ' . json_last_error_msg());
15}

Що тут відбувається. part=snippet, запитуємо базові дані: заголовок, опис, прев'ю, позицію в плейлисті. Для повного набору можна вказати snippet,contentDetails,status. maxResults=50, максимум за один запит, API за замовчуванням віддає 5 записів, тому параметр краще вказувати явно. playlistId кодуємо через urlencode() на випадок спецсимволів.

Для продакшену file_get_contents() замініть на wp_remote_get() (у WordPress) або cURL з таймаутом. Прямий виклик впаде, якщо Google тимчасово недоступний або мережа гальмує. Ось варіант з обробкою HTTP-помилок:

1$response = wp_remote_get($api_url, [
2 'timeout' => 15,
3 'headers' => ['Accept' => 'application/json'],
4]);
5
6if (is_wp_error($response)) {
7 error_log('YouTube API error: ' . $response->get_error_message());
8 return [];
9}
10
11$http_code = wp_remote_retrieve_response_code($response);
12if ($http_code !== 200) {
13 error_log('YouTube API HTTP ' . $http_code);
14 return [];
15}
16
17$body = wp_remote_retrieve_body($response);
18$data = json_decode($body, true);

Два рівні перевірки: спочатку is_wp_error() ловить мережеві збої, потім звіряємо HTTP-код. Якщо щось пішло не так, повертаємо порожній масив, сайт не падає.

Крок 3: Виводимо список відео на сторінці

API повертає масив items. Кожен елемент, одне відео плейлиста. Структура відповіді:

1{
2 "items": [
3 {
4 "snippet": {
5 "title": "Название видео",
6 "description": "Описание...",
7 "thumbnails": {
8 "default": { "url": "https://i.ytimg.com/.../default.jpg" },
9 "medium": { "url": "https://i.ytimg.com/.../mqdefault.jpg" },
10 "high": { "url": "https://i.ytimg.com/.../hqdefault.jpg" }
11 },
12 "resourceId": {
13 "videoId": "dQw4w9WgXcQ"
14 }
15 }
16 }
17 ]
18}

Відео ідентифікується за resourceId.videoId. З нього збирається посилання https://www.youtube.com/watch?v=<videoId>. Прев'ю лежить у thumbnails у трьох роздільностях: для сітки карток беріть medium, для компактного списку, default.

Код виведення для WordPress, шорткод або шаблон сторінки:

1if (! empty($data['items'])) {
2 echo '<div class="yt-playlist-grid">';
3
4 foreach ($data['items'] as $item) {
5 $title = esc_html($item['snippet']['title']);
6 $video_id = esc_attr($item['snippet']['resourceId']['videoId']);
7 $thumbnail = esc_url($item['snippet']['thumbnails']['medium']['url']);
8 $link = 'https://www.youtube.com/watch?v=' . $video_id;
9
10 printf(
11 '<a href="%s" class="yt-card" target="_blank" rel="noopener">'
12 . '<img src="%s" alt="%s" loading="lazy">'
13 . '<span>%s</span></a>',
14 $link, $thumbnail, $title, $title
15 );
16 }
17
18 echo '</div>';
19}

Три моменти, які економлять час на налагодженні:

  • loading="lazy". При 50 відео на сторінці без лінивого завантаження просяде PageSpeed. Атрибут каже браузеру: завантажуй картинку лише коли до неї докрутили.
  • esc_html()** і esc_url().** Обов'язкова санітація для WordPress. Назви відео іноді містять лапки та HTML-сутності, без екранування зламають верстку.
  • target="_blank"** з rel="noopener".** Відкриваємо YouTube у новій вкладці, але не віддаємо їй доступ до window.opener, захист від tab-napping.

CSS для сітки, мінімальний, під стандартну тему:

1.yt-playlist-grid {
2 display: grid;
3 grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
4 gap: 20px;
5}
6.yt-card {
7 text-decoration: none;
8 color: inherit;
9 border-radius: 8px;
10 overflow: hidden;
11 transition: transform 0.2s;
12}
13.yt-card:hover {
14 transform: translateY(-2px);
15}
16.yt-card img {
17 width: 100%;
18 aspect-ratio: 16 / 9;
19 object-fit: cover;
20}
21.yt-card span {
22 display: block;
23 padding: 10px;
24 font-weight: 600;
25 font-size: 14px;
26}

Сітка автоматично підлаштовується під ширину екрана: auto-fill + minmax(280px, 1fr) дають від однієї до кількох колонок без медіазапитів.

Крок 4: Пагінація, квоти і типові помилки

Пагінація. Один запит віддає максимум 50 відео. Якщо в плейлисті більше, у відповіді з'являється поле nextPageToken. Передайте його в наступному запиті, API поверне наступну сторінку. Цикл:

1$all_items = [];
2$page_token = null;
3
4do {
5 $url = $api_url . '&pageToken=' . urlencode($page_token ?? '');
6 // ... запрос к API ...
7 $all_items = array_merge($all_items, $data['items'] ?? []);
8 $page_token = $data['nextPageToken'] ?? null;
9} while ($page_token && count($all_items) < 500);

Цикл переривається на 500 відео, розумна стеля для сторінки сайту. Без обмеження ризикуєте вибрати всю квоту за пару завантажень.

Квоти. Кожен виклик playlistItems.list витрачає 1 одиницю квоти — це підтверджено офіційною таблицею квот Google. Добовий ліміт, 10 000 одиниць. Тобто 10 000 запитів на добу, з запасом для переважної більшості сайтів. Але якщо плейлист оновлюється часто, ставте кешування:

1$cache_key = 'yt_playlist_' . md5($playlist_id);
2$cached_data = get_transient($cache_key);
3
4if ($cached_data !== false) {
5 return $cached_data;
6}
7
8// ... запрос к API ...
9
10set_transient($cache_key, $data, HOUR_IN_SECONDS * 6);

Шість годин, розумний баланс між свіжістю та економією квоти. Для некритичних плейлистів ставте 12-24 години. get_transient() і set_transient(), нативні функції WordPress, працюють з об'єктним кешем (Redis/Memcached), якщо його налаштовано, інакше пишуть у wp_options.

Типові помилки і що з ними робити:

  • 403 Forbidden. API не увімкнено для проєкту в Google Cloud Console. Поверніться до кроку 1: кнопка Enable для YouTube Data API v3 має бути натиснута. Перевірте також, чи не накладено обмеження за IP у налаштуваннях ключа.
  • 400 Bad Request, «API key not valid». Ключ щойно створено і ще не активувався. Зачекайте 2-5 хвилин: обмеження API поширюються не миттєво.
  • 404 Not Found. Невірний playlist ID, або плейлист приватний. API-ключ повертає лише публічні та приховані за посиланням (unlisted) плейлисти. Приватні, ні, для них потрібна OAuth-авторизація.
  • Порожній масив items при валідному ID. Швидше за все, плейлист порожній. Відкрийте URL плейлиста в браузері і переконайтеся, що відео є.

💻 Відео: YouTube Data API v3 у дії

Коротке відео за темою, наочно показує весь процес від створення ключа до виведення списку відео:

⁉️🤔 Часті запитання

Чи працює API з приватними плейлистами?

Ні. playlistItems.list з API-ключем повертає лише публічні та приховані за посиланням (unlisted) плейлисти. Для приватних потрібна OAuth-авторизація: користувач має явно дозволити вашому застосунку доступ до свого акаунта. Для публічного сайту-агрегатора API-ключа достатньо.

Чи можна отримати відео з чужого плейлиста?

Так, якщо плейлист публічний. API-ключ не прив'язаний до власника плейлиста, він ідентифікує ваш застосунок, а не користувача YouTube. Будь-який публічний плейлист доступний за ID, незалежно від того, хто його створив.

Як отримати більше 50 відео за раз?

Ніяк — це апаратний ліміт maxResults для playlistItems, зафіксований у документації Google. Використовуйте пагінацію через nextPageToken (крок 4). Для плейлиста з 300 відео знадобиться 6 послідовних запитів, разом вони витратять 6 одиниць квоти з 10 000 добових.

Чому не показуються прев'ю відео?

Перевірте URL у thumbnails: поле називається url, не link і не src. Друга причина, блокувальники реклами іноді ріжуть домен i.ytimg.com. Третя: деякі старі відео (до 2010 року) не мають прев'ю високої роздільності, беріть default, він є завжди.

Що робити, якщо ключ скомпрометовано?

Негайно зайдіть у Google Cloud Console → Credentials, знайдіть ключ і натисніть Delete. Створіть новий. Старий ключ деактивується протягом 5 хвилин. Зберігайте ключ через define('YOUTUBE_API_KEY', '...') у wp-config.php і виключіть цей файл з репозиторію через .gitignore.

Чи варто морочитися з API, якщо можна вставити посилання на плейлист?

Якщо на сайті достатньо одного статичного плейлиста через iframe, API не потрібен, YouTube дає готовий код вбудовування. Але щойно з'являється завдання автоматично підхоплювати нові відео, фільтрувати за датою, кастомізувати верстку або виводити прев'ю в нестандартному дизайні, API стає єдиним робочим варіантом.

Для WordPress-сайту зв'язка wp_remote_get() + set_transient() повністю знімає питання квот і швидкості: раз на кілька годин скрипт забирає JSON, кешує, а фронт працює з кешем миттєво. Плейлист оновлюється сам, редактору нічого натискати не потрібно.

Якщо тема підтримує довільний PHP у шаблонах, беріть код з кроку 3, міняйте CSS під свій дизайн. Якщо використовується конструктор, обгорніть PHP-логіку в шорткод і вставляйте куди завгодно через [youtube_playlist id="PLp0..."].

Спробуйте з одного плейлиста: 15 хвилин на ключ і перший запит, і ви побачите, чи працює підхід під ваше завдання. А якщо вже використовували API для інших цілей, напишіть у коментарях, який endpoint виявився найкориснішим.