C# から Google Photos Library API を使いたい

スマホで撮った画像、Google Photoにアップロードしてる人、多いですよね?

で、スマホの設定で自動アップロードで問題ないかとは思いますが、ちょっと考えるところがありまして?せっかくならAPIでいろいろやってみようかな、と思い、Google Photos Library APIを使ってみました。ただ、以前とは異なりAPIでできること結構限られてるようです。。。なので、あまりAPIを使う必要ないかなとも思いながらも、解決するまで時間がかかったので意地で記事にしましたw。

Google系サービスはUIやら仕組みやらが頻繁に異なるようなので完全にUIや仕組みが同じとは限らないことは注意。 ※2026年1月時点の情報です。

Sponsored Link

プロジェクトを作成しましょう。

① Google Cloud Console(https://console.cloud.google.com/)から新しいプロジェクトを作成します。

② 作成したプロジェクトを選択状態にしたら、[APIライブラリ]の検索窓から「Google Photos Library API」を検索。選択後の画面で「有効にする」をクリック。

③ 「有効なAPIとサービス」に画面が遷移され、Photos Library APIが表示された状態に。

Sponsored Link

OAuth 同意画面の設定を行いましょう。

④ 作成したプロジェクトで引き続き「OAuth 同意画面」の設定を行います。左メニューの「OAuth 同意画面」をクリック。表示された画面の「開始」ボタンをクリック。

⑤ 各種設定を行います。

【アプリ情報】

アプリ名好きなものを入れます。
ユーザーサポートメールご自身のメールアドレス

 入力できたら「次へ」ボタン

【対象】

「外部」を選択。※「内部」は組織アカウント専用なので、個人は「外部」になるとのこと。

で、次へ

【連絡先情報】

連絡先となるメールアドレスを入力。ここは複数指定可能な模様。

で、次へボタンをクリック。

【作成】ボタン押下 一通り入力が完了し利用規約にチェックを入れて進むと「作成」ボタンがクリックできるようになります。

作成完了となるとメッセージが表示され画面が切り替わります。

Sponsored Link

スコープの設定を行いましょう。

⑥ 左メニューの「データアクセス」を選択します。そこで表示された画面内の「スコープを追加または削除」ボタンをクリックします。

⑦ 画面右側にタブが表示されますので、そこの「フィルタ」に「photolibrary」と入力。すると今回追加したいスコープが抽出表示されます。

⑧ フィルタされたスコープのうち「…./photoslibrary.appendonly」または「…./photoslibrary.readonly.appcreateddata」を選択状態にします。すると2つのスコープにチェックが入った状態になります。※ここで一覧に表示されない場合には、前述のAPIの有効が正しく実行されていない可能性があります。

※注!)/photoslibrary.readonly ではなく /photoslibrary.readonly.appcreateddata です。

 → 2026年1月時点で「readonly」はセキュリティ上の問題?で個人アプリでは使用できない模様。以下のエラーメッセージが返され、情報が取得できないかと思われます。

The service photoslibrary has thrown an exception. HttpStatusCode is Forbidden. Request had insufficient authentication scopes.

画面一番下の「更新」ボタンをクリック。

この2つのスコープは、読んで字のごとく「参照」と「追加(アップロード)」の目的。

⑨ タブが閉じられ、元画面の「非機密のスコープ」「機密性の高いスコープ」にそれぞれ選択した2つのスコープが表示されています。

画面下の「Save」ボタンをクリック。スコープの設定が完了しました。

Sponsored Link

テストユーザの設定をしましょう。

⑩ 左メニュー「対象」画面内にある「テストユーザ」ボタンをクリック。

⑪ 右側にタブが表示されますので、ボックスの中にGoogle Photoで利用しているGmailアカウントを入力し、「保存」ボタンをクリック。

 呼び出し元画面に戻り、入力したGmailアカウントが登録さえているのが確認できます。

Sponsored Link

クライアントを作成しましょう。

⑫ 左メニュー「クライアント」を選択し、表示された画面内の「新しいクライアントを作成」をクリック。

⑬ 「OAuthクライアントIDの作成」画面で、アプリケーションの種類を「デスクトップアプリ」に、名前は「好きな名称」を入れ「作成」ボタンをクリック。

⑭ クライアントIDとクライアントシークレットが発行されます。コピーするか、JSONをダウンロードを実行し、情報を保持します。

ここまでが前準備。長いですね・・・

Sponsored Link

Visual Studioで準備をしましょう。

ここからは若干簡素に記載しますw

① Nugetで以下の2つをインストールします。

  ・Google.Apis.PhotosLibrary.v1

  ・Google.Apis.Auth

② 先ほど「OAuthクライアントIDの作成」画面でダウンロードしたJSONファイルをC#ソリューションと同じ場所に格納します。ファイル名は「client_secret.json」に変更。

※JSONファイル名やファイル格納場所については絶対ではありません。後述のサンプルソースに合わせたもの。

Sponsored Link

以下のサンプルソースで試しましょう。

using System.Net.Http.Headers;
using Google.Apis.Auth.OAuth2;
using Google.Apis.PhotosLibrary.v1;
using Google.Apis.PhotosLibrary.v1.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;

class Program
{
    static async Task Main(string[] args)
    {
        // --- 1. 認証設定 ---
        string[] Scopes = {
            "https://www.googleapis.com/auth/photoslibrary.appendonly",
            "https://www.googleapis.com/auth/photoslibrary.readonly.appcreateddata"
        };

        UserCredential credential;
        // 同じ階層に[client_secret.json]が無ければ適切な場所に書き換えて。
        using (var stream = new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
        {
            credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                GoogleClientSecrets.FromStream(stream).Secrets,
                Scopes,
                "user",
                CancellationToken.None,
                new FileDataStore("token.json", true));
        }

        // --- 2. サービスの作成 ---
        var service = new PhotosLibraryService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = "HogeHogePhotoTool",      // なんでもOK
        });

        // --- 3. アップロード処理 ---
        string filePath = @"Z:\works\hogehoge.jpg";     // 適切なファイルパスで。
        if (!File.Exists(filePath))
        {
            Console.WriteLine("ファイルが見つからない!パスを確認して。");
            return;
        }

        Console.WriteLine("アップロード開始...");
        string uploadToken = "";

        // UserCredentialから最新のアクセストークンを取得
        var accessToken = await credential.GetAccessTokenForRequestAsync();

        using (var httpClient = new HttpClient())
        {
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            using (var fileStream = File.OpenRead(filePath))
            {
                var content = new StreamContent(fileStream);
                content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                content.Headers.Add("X-Goog-Upload-Protocol", "raw");
                content.Headers.Add("X-Goog-Upload-File-Name", Path.GetFileName(filePath));

                var uploadResponse = await httpClient.PostAsync("https://photoslibrary.googleapis.com/v1/uploads", content);
                uploadToken = await uploadResponse.Content.ReadAsStringAsync();
            }
        }

        // --- 4. ライブラリに登録 ---
        var batchRequest = new BatchCreateMediaItemsRequest
        {
            NewMediaItems = new List<NewMediaItem>
            {
                new NewMediaItem
                {
                    Description = "アップロードテスト",
                    SimpleMediaItem = new SimpleMediaItem { UploadToken = uploadToken }
                }
            }
        };

        var createResponse = await service.MediaItems.BatchCreate(batchRequest).ExecuteAsync();
        Console.WriteLine("Google フォトへの登録完了!");
    }
}

このサンプルコードを実行すると、初回実行時はブラウザが立ち上がり・・・

まず「アカウント選択」を促されます。

ここは「続行」

このサンプルコードが「Google Photo」へのアクセスを求めるため、チェックONにして「続行」

すると、ブラウザに以下のメッセージが表示され、C#の処理が続きます。

このタイミングで「token.json」フォルダが作成され、2度目以降の実行ではブラウザでの確認は行われなくなります。このフォルダを削除してしまえば、再度初回のブラウザ確認から確認することが可能。

コンソールに官僚のメッセージが表示され・・・

Google photoを開くと、対象画像がアップロードされていることが確認できます。

Sponsored Link

備考

前述の「/photoslibrary.readonly ではなく /photoslibrary.readonly.appcreateddata です。」という記述。スコープ「readonly.appcreateddata」を指定することで「当アプリでアップロードした画像に関してのみ参照ができる」という状態になります。

参照部分のサンプルコードも記載しておきます。こちらは「Search」メソッドを使って参照するようです。ここで抽出条件なども指定できるようですが、現時点ではとりあえずここまで。

        // 3. 検索リクエストを使って最新の10枚を表示(フィルタなし=全件対象)
        Console.WriteLine("最新の写真を10枚取得中...");
        var searchRequest = new Google.Apis.PhotosLibrary.v1.Data.SearchMediaItemsRequest
        {
            PageSize = 10
        };

        // Searchメソッドを使ってリクエストを実行
        var response = await service.MediaItems.Search(searchRequest).ExecuteAsync();
        if (response != null && response.MediaItems != null)
        {
            foreach (var item in response.MediaItems)
            {
                Console.WriteLine($"ファイル名: {item.Filename} (ID: {item.Id.Substring(0, 10)}...)");
            }
        }
        else
        {
            Console.WriteLine("写真が見つからなかった。");
        }
タイトルとURLをコピーしました