スマホで撮った画像、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が表示された状態に。

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

⑤ 各種設定を行います。
【アプリ情報】

| アプリ名 | 好きなものを入れます。 |
| ユーザーサポートメール | ご自身のメールアドレス |
入力できたら「次へ」ボタン
【対象】

「外部」を選択。※「内部」は組織アカウント専用なので、個人は「外部」になるとのこと。
で、次へ
【連絡先情報】

連絡先となるメールアドレスを入力。ここは複数指定可能な模様。
で、次へボタンをクリック。
【作成】ボタン押下 一通り入力が完了し利用規約にチェックを入れて進むと「作成」ボタンがクリックできるようになります。

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

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

⑦ 画面右側にタブが表示されますので、そこの「フィルタ」に「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」ボタンをクリック。スコープの設定が完了しました。

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

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

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

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

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

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


ここまでが前準備。長いですね・・・
Sponsored LinkVisual 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を開くと、対象画像がアップロードされていることが確認できます。

備考
前述の「/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("写真が見つからなかった。");
}
