◀ 3.

YouTube APIでチャンネル情報を取得|ID・ハンドル・統計の読み方

▶

YouTube Data API v3のchannels.listは、指定した条件に合うチャンネルの一覧を取得します。チャンネルID、ハンドル、ユーザー名を混同せず、必要なpartと認証/認可の条件を選びます。2017年当時の元コード表と応答例は後半に保持しています。

チャンネル取得と検索で異なるID構造、統計の欠落と次ページtokenの扱い

最初に指定する条件を決める

条件用途注意
id既知のチャンネルID動画IDやURL全体と混同しない
forHandle現在のハンドルから取得GoogleDevelopersと@GoogleDevelopersのような指定。実対象の存在は別確認
forUsername従来のユーザー名から取得表示名やハンドルの単純な置換ではない
mine=true認可したユーザーのチャンネル適切なOAuth認可が必要
managedByMeコンテンツパートナー向けCMS等の条件があり、一般利用の代替にしない

フィルタは仕様に従って1つ選びます。旧表にあるcategoryIdは非推奨で、新規実装の通常手段にはしません。パラメータ名は小文字のidです。part=snippet,statisticsで名前などと統計を要求できますが、part/fieldsを絞ることと割当単価の低下は同じではありません。

2026年10月26日に確認したlistのpartはauditDetails、brandingSettings、contentDetails、contentOwnerDetails、id、localizations、snippet、statistics、status、topicDetailsです。auditDetails等には追加の認可条件があります。旧文のinvideoPromotionを現在のchannels.listへそのまま指定しません。別メソッドの項目名と、listで選べるpartを分けます。

要求を組み立てるときの確認

送信先はhttps://www.googleapis.com/youtube/v3/channelsです。公開データ取得のAPIキーと、ユーザーとしての操作/非公開情報のOAuthを区別します。APIキーの発行だけでmineや監査用partを利用できるわけではありません。API有効化・実行元/API制限・対象の可視性・割当も別に確認します。

概念上のパラメータ例はpart=snippet,statisticsとforHandle=@GoogleDevelopersです。これは資格情報を含まない説明で、実キー通信による動作確認ではありません。URLにキーを直書きし、シェル履歴やアクセスログへ残す手順は避けます。旧URL例は対応する注意とともに残します。

統計は数値・欠落・公開条件を分ける

  • subscriberCountは3桁の有効数字へ切り捨てられた値です。正確な内部の登録者数を復元できるとは考えません。hiddenSubscriberCountや欠落も見て、取得できない値を0と表示しません。
  • videoCountは公開動画の件数で、所有者として取得しても全ての非公開動画を含む総数とは限りません。
  • commentCountは非推奨です。元の応答例に値があっても、今も必ず返る項目として実装しません。
  • viewCountの定義も時期で変わります。確認した公式資料は2026年8月24日以降、各形式の動画の再生開始時点を数える変更を案内しています。過去の取得値との比較では対象時点/定義を明記し、元例の2017年の数字を現在値に見せません。
  • JSONのカウントが文字列で返る場合、必要なくint/floatへ変換しません。JavaScript等の数値精度や実行環境の整数幅にも注意します。表示時はHTMLとしてエスケープします。

取得済みJSONを読むPHP例

次の共通教材のytReadChannelPage(200, 取得済み本文)は、HTTP状態とroot.kind/itemsを検査し、チャンネルIDと一部の統計だけを返します。欠落はnull、登録者数はhiddenSubscriberCountが明示的にfalseの場合だけを採用します。丸められた値をさらに正確な値へ補正するものではありません。snippetのタイトル等はこの例では取り出しません。

<?php
declare(strict_types=1);

// Offline teaching helpers: no network, credentials, logs or automatic paging.
function ytReadListRoot(int $httpStatus, string $body, string $kind): stdClass
{
    if ($httpStatus !== 200 || strlen($body) > 262144) {
        throw new InvalidArgumentException('Expected bounded HTTP 200 JSON');
    }
    try {
        $root = json_decode($body, false, 16, JSON_THROW_ON_ERROR);
    } catch (JsonException) {
        throw new InvalidArgumentException('Invalid JSON');
    }
    if (!$root instanceof stdClass || property_exists($root, 'error')
        || ($root->kind ?? null) !== $kind || !isset($root->items)
        || !is_array($root->items) || count($root->items) > 50) {
        throw new InvalidArgumentException('Unexpected list shape');
    }
    return $root;
}

function ytReadIdentifier(mixed $value): string
{
    // A local teaching constraint, not proof an ID exists or is authorized.
    if (!is_string($value) || !preg_match('/\A[A-Za-z0-9_-]{1,128}\z/D', $value)) {
        throw new InvalidArgumentException('Unexpected identifier');
    }
    return $value;
}

function ytReadNextPage(stdClass $root): ?string
{
    if (!property_exists($root, 'nextPageToken')) {
        return null;
    }
    $token = $root->nextPageToken;
    if (!is_string($token) || strlen($token) > 1024 || preg_match('/[\x00-\x20\x7f]/', $token)) {
        throw new InvalidArgumentException('Unexpected next page token');
    }
    return $token === '' ? null : $token;
}

function ytReadSearchPage(int $httpStatus, string $body): array
{
    $root = ytReadListRoot($httpStatus, $body, 'youtube#searchListResponse');
    $fields = ['youtube#video' => 'videoId', 'youtube#channel' => 'channelId', 'youtube#playlist' => 'playlistId'];
    $items = [];
    $skipped = 0;
    foreach ($root->items as $item) {
        if (!$item instanceof stdClass || ($item->kind ?? null) !== 'youtube#searchResult'
            || !isset($item->id) || !$item->id instanceof stdClass || !is_string($item->id->kind ?? null)) {
            throw new InvalidArgumentException('Unexpected search item');
        }
        $kind = $item->id->kind;
        if (!isset($fields[$kind])) {
            $skipped++;
            continue;
        }
        $field = $fields[$kind];
        $items[] = ['kind' => $kind, 'id' => ytReadIdentifier($item->id->$field ?? null)];
    }
    return ['items' => $items, 'skipped' => $skipped, 'next_page_token' => ytReadNextPage($root)];
}

function ytReadCount(stdClass $stats, string $field): ?string
{
    if (!property_exists($stats, $field)) {
        return null;
    }
    $value = $stats->$field;
    if (!is_string($value) || !preg_match('/\A[0-9]{1,40}\z/D', $value)) {
        throw new InvalidArgumentException('Unexpected count string');
    }
    return $value;
}

function ytReadChannelPage(int $httpStatus, string $body): array
{
    $root = ytReadListRoot($httpStatus, $body, 'youtube#channelListResponse');
    $items = [];
    foreach ($root->items as $item) {
        if (!$item instanceof stdClass || ($item->kind ?? null) !== 'youtube#channel') {
            throw new InvalidArgumentException('Unexpected channel item');
        }
        $id = ytReadIdentifier($item->id ?? null);
        $stats = $item->statistics ?? new stdClass();
        if (!$stats instanceof stdClass) {
            throw new InvalidArgumentException('Unexpected statistics');
        }
        $hidden = $stats->hiddenSubscriberCount ?? null;
        if (property_exists($stats, 'hiddenSubscriberCount') && !is_bool($stats->hiddenSubscriberCount)) {
            throw new InvalidArgumentException('Unexpected visibility flag');
        }
        $items[] = [
            'id' => $id,
            'view_count' => ytReadCount($stats, 'viewCount'),
            'video_count' => ytReadCount($stats, 'videoCount'),
            'hidden_subscriber_count' => $hidden,
            'subscriber_count' => $hidden === false ? ytReadCount($stats, 'subscriberCount') : null,
        ];
    }
    return ['items' => $items, 'next_page_token' => ytReadNextPage($root)];
}

共通コードは検索の読み取り関数も含みます。新例の入力上限は262,144byte、JSON深さ16、items最大50件、IDはASCIIの英数字/ハイフン/アンダースコア1〜128字、カウント文字列は数字1〜40字、次ページtokenは1024byteです。これは教材の受入制限で、Googleの全入力/ID/カウントの仕様を検証する規則ではありません。Content-Type・受信途中の容量/時間・重複JSONキー・全fieldの検査は別です。通信、キー読込、ログ、HTML生成、自動ページ取得は行いません。

空の結果と次ページ

itemsが空なら空の一覧として扱い、直ちに認証失敗やチャンネル削除と断定しません。必要な対象を取得できたかはID/ハンドル・可視性・操作条件を確認します。HTTP200と、業務上必要な結果があることを分けてください。

ページを持つ応答ではnextPageTokenを次の要求のpageTokenへ渡します。短いページだから必ず終了、としないでください。tokenを解読して番号を作ったり、検索のtokenをchannelsへ流用したりしません。対象条件・認証・取得回数/総量の上限を保ち、同時更新中の完全なsnapshotや重複のない一覧は保証しません。

元の構文・URL・応答例

以下の表は元記事の記録です。旧JSONは構文が有効であり、壊れたJSONとして書き換えていません。新規実装の条件や数値の意味は、各表の直前と上の説明を参照してください。

旧表の注意:旧要点表はforHandle等がなく、「APIキー必須」という表現も不十分です。公開取得とOAuth必須の条件を、新しい条件表/認可の説明で分けます。

この記事の要点
  • YouTube Data API v3 でチャンネル情報を取得する基本
  • エンドポイント: https://www.googleapis.com/youtube/v3/channels
  • 必須パラメータ: part(snippet / statistics 等)+ id または forUsername
  • API キー必須(OAuth でも可)。レート制限はクォータ単位

 

これはYouTube Data API (v3)を使用したチャンネル情報を取得する方法に関する記事です。

 

チャンネル情報を取得する基本構文は以下の通りです。

旧表の注意:これはエンドポイントの旧表です。URLだけで認証や認可が成立するわけではありません。

構文

https://www.googleapis.com/youtube/v3/channels

 

基本構文に対してパラメータを付与する必要があります。

旧表の注意:partは必要ですが、全partが無認可で使えるという意味ではありません。現在のlistで指定できる値を本文で確認します。

必須パラメータ

part

part名によってレスポンスの内容を変更することが出来ます。

partは以下を指定することが出来ます。

上の「最初に指定する条件を決める」に現行のpartを整理しています。元のinvideoPromotionを現在のlistのpart一覧として使わず、追加認可を要する項目にも注意します。

チャンネルの登録者数やビデオの総再生回数を取得したい場合は「statistics」を指定します。

 

旧表の注意:categoryIdは非推奨です。forHandleを含む現行条件を先に確認し、mine/managedByMeの認可も区別します。

以下の中からパラメータを1つ設定

categoryId、forUsername、id、managedByMe、mine

旧表のcategoryIdを新規実装へそのまま使わず、現行のフィルタと認可条件に従って選択します。

例えば小文字のidへ既知のチャンネルIDを指定します。ハンドル/ユーザー名/動画IDとは区別します。

 

旧表の注意:onBehalfOfContentOwnerは一般の省略可能な値として無条件に使うものではなく、コンテンツパートナーの認可等が関係します。maxResultsは必ずその件数が返る保証ではありません。

省略可能なパラメータ

maxResults、onBehalfOfContentOwner、pageToken

上記のパラメータは指定してもしなくても良いです。

例えば「maxResults」を指定した場合はレスポンス結果数の限界値を指定することが出来ます。

 

以下、APIキーを使用した例文です。

GoogleのチャンネルIDを指定します。

旧表の注意:旧URLへ実キーを置換して実行しないでください。URLは履歴/引数/ログへ残り得ます。このチャンネルIDの現在の存在や値は実通信で確認していません。

例文

https://www.googleapis.com/youtube/v3/channels
?part=statistics
&id=UCK8sQmJBp8GCxrOtXWBpyEA
&key={APIキー}

 

以下、例文のレスポンスです。

元例のviewCountはチャンネルの統計の過去値です。集計の定義/対象時点と現在の値を混同しません。

旧表の注意:過去の応答値を保持した表です。commentCountは非推奨、subscriberCountは丸められた値であり、現在値ではありません。欠落/非公開を0へ変換しません。

レスポンス

{
 "kind": "youtube#channelListResponse",
 "etag": "\"cbz3lIQ2N25AfwNr-BdxUVxJ_QY/gxdVXRcX3iWbOP0L3N9tSiqTkMo\"",
 "pageInfo": {
  "totalResults": 1,
  "resultsPerPage": 1
 },
 "items": [
  {
   "kind": "youtube#channel",
   "etag": "\"cbz3lIQ2N25AfwNr-BdxUVxJ_QY/lxon5EE4ehTeG1THvk-NEufHjr8\"",
   "id": "UCK8sQmJBp8GCxrOtXWBpyEA",
   "statistics": {
    "viewCount": "1478719085",
    "commentCount": "24",
    "subscriberCount": "5514700",
    "hiddenSubscriberCount": false,
    "videoCount": "1950"
   }
  }
 ]
}

 

指定できるパラメータのリストはこちらを参照。

確認範囲と関連情報

2026年10月26日確認。旧表/応答例/元リンクと全履歴を保持し、PHP例は合成データと取得済み旧JSONでオフライン検査しています。実キー/HTTP通信、Google側の認証/認可、現在のID/動画/統計値、実ブラウザや全field/schemaを検証したものではありません。キー/token/応答全文をログへ出さず、無条件の自動再送は行いません。

親ページから子ページを選択できます。チャンネル情報と検索を用途で選び、エラーの切り分け、キーの扱い、API有効化も参照してください。

公式資料:channels.list、チャンネルの統計/field、search.listとページ情報、操作別の割当。

子ページ

子ページはありません

同階層のページ
  1. APIキー取得方法
  2. APIの有効化
  3. チャンネル情報の取得
  4. 動画やチャンネルの検索
  5. エラー一覧

最近更新/作成されたページ