メインコンテンツへスキップ

Veoの動画ダウンロードが403になる原因と直し方:APIキーを付ける

Gemini APIでVeoが返す動画のURIは、キーなしで開くと403になります。生成に使ったAPIキーをヘッダーに付けて2日以内に保存し、ブラウザにはURIを直接渡しません。

LaoZhang AI Team公開23 分で読めます
目次
Veoの動画が403になるときはAPIキーを付けるという見出しと、キーなしは403、無効なキーは400、同じAPIキーで2日以内に保存という3枚のカード

Gemini APIでVeo(Googleの動画生成モデル)の生成が完了し、レスポンスに動画のURIが入っているのに、そのURIを開くと403が返る。この場合、原因はほぼ決まっていて、ダウンロードのリクエストにAPIキーが付いていません。video.uriに入っているhttps://generativelanguage.googleapis.com/v1beta/files/{FILE_ID}:download?alt=mediaは誰でも開ける共有リンクではなく、認証が必要なAPIリソースです。公式ドキュメントのRESTサンプルも、ダウンロードの行にx-goog-api-keyヘッダーを付けています。

直し方は、生成に使ったのと同じAPIキーをダウンロードのリクエストにも付けることです。どう付けるかは、リクエストを出す場所で変わります。

ダウンロードする場所取得方法注意点
サーバー側のSDK(Python、Node.js、Go)APIキーで作ったクライアントのfiles.downloadを使うURIを自分で取り出して別のHTTPクライアントで叩くと、キーが付かない
curlや素のHTTPリクエストx-goog-api-keyヘッダーを付け、リダイレクトを追従するポーリングと同じヘッダーをダウンロードにも付ける
n8nなどのHTTPノードダウンロード用のノードにも同じヘッダーを設定する生成用ノードの認証は、別ノードには引き継がれない
ブラウザのvideoタグやリンクURIを直接渡さない。サーバーで保存し、自前のURLを渡すタグはヘッダーを付けられず、URLにキーを付けると利用者に見える

APIの有効化、IAMの変更、キーの作り直しでは、この403は消えません。エラー文に出てくるプロジェクト番号を探す必要もありません。理由は次の節のとおりです。

「project 542708778979」が出る403:キーなしのリクエストが原因

フォーラムで報告されているエラーは、HTTP 403、"status": "PERMISSION_DENIED"で、メッセージは次の形です。

Generative Language API has not been used in project 542708778979 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/generativelanguage.googleapis.com/overview?project=542708778979 then retry

詳細にはreason: SERVICE_DISABLEDが付きます。メッセージどおりに読むと「自分のプロジェクトでAPIが無効になっている」と受け取れますが、542708778979は報告者の誰のプロジェクトでもありません。Google AI Developers Forumのスレッドや別のスレッドでは、ユーザーもキーも違うのに同じ番号が出ています。報告は2025年5月〜9月、Veo 2とVeo 3.0のもので、環境はSupabase Edge Functions、Python(FastAPI、Django)、n8nのHTTP Requestノード、Node 22などです。

この番号がなぜ表示されるのかを、Googleはこれらのスレッドで説明していません。「キーのないリクエストがGoogle側の既定のプロジェクトに割り当てられる」という説明はフォーラム利用者の推測です。確かなのは次の2点です。

  • 同じスレッドでSDKのメンテナーとして回答しているMark Daoust氏が、2025年10月23日に「キーなしのURLをブラウザに貼ればそのエラーになるのは“普通”だが、ai.files.downloadから返ってくるはずはない」と書いています。
  • 報告者たちは、自分のプロジェクトでのAPI有効化、IAMの変更、キーの再作成、output_gcs_uriの指定を試しましたが、どれも効きませんでした。解決として受け入れられたのは、ダウンロードのリクエストに自分のAPIキーを足す方法で、2025年8月、2025年9月、2026年4月に別のユーザーが「これで直った」と書き込んでいます。

スレッドの投稿者はこの現象を「Project Mismatch」と呼んでいますが、これは投稿者の付けた呼び名で、公式の診断名ではありません。コンソールでこの番号のプロジェクトを探しても見つからないのは、あなたの設定の問題ではないからです。

キーなしは403、無効なキーは400:2026年10月2日のレスポンス

ここからは実際に送ったリクエストの結果です。実行したのは、存在しないファイルID(abc123xyz000)を使ったcurlのリクエスト3本です。実行していないのは、Veoでの実際の生成と、ダウンロードが成功するところまでの確認です。課金を有効にしたGemini APIキーがない環境だったため、成功する経路は公式ドキュメントとフォーラムの報告に基づいています。

リクエストHTTPステータス本文
キーなしで/v1beta/files/abc123xyz000:download?alt=mediaをGET403PERMISSION_DENIED
キーなしで/download/v1beta/files/abc123xyz000:download?alt=mediaをGET403同じ本文
無効なキーをx-goog-api-keyに入れて同じURLをGET400INVALID_ARGUMENT、reasonはAPI_KEY_INVALID

キーなしの場合のレスポンスは次のとおりです。

json
{
  "error": {
    "code": 403,
    "message": "Method doesn't allow unregistered callers (callers without established identity). Please use API Key or other form of API consumer identity to call this API.",
    "status": "PERMISSION_DENIED"
  }
}

無効なキーの場合は、メッセージがAPI key not valid. Please pass a valid API key.に変わり、ステータスは400です。

キーなしのGETは403のPERMISSION_DENIED、無効なキーは400のAPI_KEY_INVALID、生成と同じキーを付けると動画を保存できるという3つの分岐を並べた図

この結果から読み取れることは3つあります。

  1. ファイルIDが存在しなくても403が返るので、キーなしのリクエストはファイルを探す前に拒否されています。URIが正しいかどうか、動画が残っているかどうかとは関係がありません。
  2. 2026年10月2日時点のメッセージは、2025年のスレッドにあるproject 542708778979の文面とは違います。どちらの文面でも、ステータスは403のPERMISSION_DENIEDで、リクエストにキーがないことを指しています。手元のエラーが「unregistered callers」のほうでも、対処は同じです。
  3. キーを付けたのに間違っている場合は、403ではなく400のAPI_KEY_INVALIDになります。ダウンロードで403が出ているなら、まず疑うのは「キーが違う」ではなく「キーが届いていない」です。

実行環境別:動画のURIにAPIキーを付けて取得する

以下のコードは公式ドキュメントに載っている形か、フォーラム由来と明記したものです。前節のとおり、ダウンロード成功までの動作はこの環境では確認していません。

Python・Node.js・GoのSDKではfiles.downloadを使う

SDKでは、APIキーを持ったクライアントがダウンロードも行います。URIを取り出して別のHTTPライブラリに渡す必要はありません。Pythonの公式サンプルは次の形です。

python
generated_video = operation.response.generated_videos[0]
client.files.download(file=generated_video.video, destination="dialogue_example.mp4")

JavaScript(@google/genai)は次の形です。

javascript
await ai.files.download({
    file: operation.response.generatedVideos[0].video,
    downloadPath: "dialogue_example.mp4",
});

公式サンプルはai.files.downloadをawaitなしで呼んでいますが、ここではawaitを付けています。downloadPathはローカルのファイルに書き出す引数なので、これはNode.jsなどサーバー側で動かす呼び出しです。ブラウザのコードには使えません。Goではclient.Files.Download(ctx, video.Video, nil)が同じ役割です。

SDKを使っているのに403になる、という報告もスレッドにはあります。Daoust氏は「チームでは再現できなかった」と書き、全員がSupabaseのDeno/Edge Functionsを使っているのかを尋ねています。翌日の2025年10月24日には、Node向けダウンローダーの修正コミット(googleapis/js-genai@127c9bf)を紹介しました。ただしこのコミットが直したのは、download()をawaitした時点でファイルの書き込みが終わっていない問題で、空のファイルや途中で切れたファイルができる不具合です。403とは別の失敗で、SDKのいずれかのバージョンが403を起こしていたかどうかは分かっていません。この修正で403が直ったという書き込みもありません。

SDK経由で403が出る場合に確かめられるのは、クライアントに渡したキーが生成時と同じかどうかと、SDKを新しいバージョンに上げても変わらないかどうかです。それでも直らなければ、次のHTTPリクエストの形に切り替えると、キーが付いているかどうかを自分の目で確認できます。

curlや素のHTTPリクエストではx-goog-api-keyヘッダーを付ける

公式のRESTサンプルは、完了したオペレーションのレスポンスからURIを取り出し、ヘッダーにキーを付けてダウンロードします。

bash
video_uri=$(echo "${status_response}" | jq -r '.response.generateVideoResponse.generatedSamples[0].video.uri')

# Download the video using the URI and API key and follow redirects.
curl -L -o dialogue_example.mp4 -H "x-goog-api-key: $GEMINI_API_KEY" "${video_uri}"

見落としやすいのは2点です。ポーリングで使ったのと同じヘッダーを、ダウンロードの行にも付けること。そして-Lでリダイレクトを追従することです。ドキュメントのコメントも「URIとAPIキーを使い、リダイレクトを追従してダウンロードする」と書いています。fetchやrequestsなど、ほかのHTTPクライアントでも同じヘッダーを付けます。

フォーラムで解決策として受け入れられたのは、ヘッダーではなくクエリにキーを足す書き方です。

javascript
// Google AI Developers Forum のスレッド 96867 に投稿されたコード
const url = decodeURIComponent(generatedVideo.video.uri);
const res = await fetch(`${url}&key=${process.env.API_KEY}`);

URIにはすでに?alt=mediaが付いているので、&key=で足しています。投稿者は出どころを「AI StudioのVeo3サンプル」と書いています。この書き方は公式のVeoドキュメントには載っておらず、載っているのはヘッダーの形だけです。サーバー側のコードなら、公式ドキュメントどおりヘッダーを使うほうが、キーがURLに残りません。

n8nなどのHTTPノードではダウンロード用ノードにも同じキーを設定する

n8nでの報告は、どれも同じ流れです。生成のリクエストとポーリングは成功し、そのあと別のHTTP Requestノードで返ってきたURIを取りにいくと403になります。認証は生成用のノードに設定しただけで、ダウンロード用のノードは何も付けずにURIへGETしているためです。

フォーラムの回答(2025年6月13日)は「生成とダウンロードに同じAPIキーを使っていれば動くはず」としています。ダウンロード用のノードにも、ヘッダー名x-goog-api-key、値に生成と同じキーを設定してください。返ってくるのはJSONではなくMP4のデータなので、ノード側ではファイルとして受け取り、リダイレクトの追従も有効にします。HTTPリクエストを部品として組むほかのノーコードツールでも考え方は同じで、認証はリクエストごとに設定します。

ブラウザのvideoタグやリンクにはURIを直接渡さない

videoタグのsrcやリンクのhrefにこのURIを入れると、ブラウザはヘッダーなしでGETするので403になります。タグにはx-goog-api-keyヘッダーを付ける手段がありません。

実際に、Genkitの@genkit-ai/google-genaiプラグインがこのURIをそのままmedia.urlとして返し、Developer UIがvideoタグで読み込んで403になるというIssueが2025年12月30日に立てられ、2026年10月2日時点でも未解決のままです。提案されている修正は、URLにkey=を足すものです。

開発中に自分だけが見る画面なら、キー付きのURLでも用は足ります。利用者に届くページでは使えません。URLに付けたキーは、ページを開いた人がそのまま読めるからです。

エンドユーザーに動画を見せるには:サーバーで保存して自前のURLを渡す

利用者に動画を見せるサービスでは、サーバー側でキーを付けてダウンロードし、ファイルを自前のストレージに置いて、そのストレージのURLを利用者に渡します。これはGoogleが定めている構成ではありません。公式ドキュメントのダウンロード手順、後述の保存期限、そしてキーをブラウザに出せないという制約から導いた提案です。

流れは次のとおりです。

  1. サーバーでオペレーションの完了を確認し、前節のSDKまたはヘッダー付きのリクエストで動画を取得する。
  2. 取得したデータを自分のストレージ(オブジェクトストレージなど)に保存する。
  3. 利用者には、そのストレージが発行するURLを渡す。公開範囲や期限は自分のストレージ側で決める。

動画のURIをブラウザに直接渡すと403になる経路と、サーバーでキーを付けて取得し自分のストレージに保存してそのURLを利用者に渡す3ステップを比べた図

「APIから署名付きURLや公開URLを直接もらえないか」という質問は、同じスレッドに2025年12月30日に投稿されています。投稿者は、利用者がアクセスするのでURLにキーを出すわけにはいかず、サーバーレス環境では一時保存も扱いにくい、と書いています。この質問には誰も回答していません。公式のVeoドキュメントにも、Gemini APIが署名付きURLを返すという記載はありません。

サーバーレス環境で一時ファイルを置きにくい場合は、ダウンロードのレスポンスをディスクに書かず、そのままストレージへのアップロードに流す形になります。その場合はSDKのdownloadPathではなく、ヘッダー付きのHTTPリクエストを自分で出します。

保存期限は2日:403をリトライせず、先にファイルを保存する

生成された動画がサーバーに残るのは2日間です。公式ドキュメントは「生成から2日以内にダウンロードしないとローカルに残せない」と明記しています。延長(extension)した動画は新しく生成したものとして扱われ、延長の元として参照された動画は2日のタイマーがリセットされます。

期限を過ぎたファイルにアクセスしたときに返るHTTPステータスは、公式ドキュメントに記載がなく、実際に試した結果もありません。分かっているのは、キーなしのリクエストはファイルの有無に関係なく403になる、という前節の結果だけです。キーを付けたうえで別のエラーが返るなら、生成からの経過時間を確認してください。

403が返ったときに同じリクエストを繰り返しても、結果は変わりません。Gemini APIのトラブルシューティングは、再試行するのは429、408、5xxなどの一時的なエラーだけで、400、402、403のようなクライアント側のエラーは再試行しないよう書いています。原因を直さないままリトライのループを回すと、その間に2日の期限だけが進みます。

動画がすでに課金済みで期限が迫っているなら、原因の調査より先に、キーを付けたcurlを1回実行してファイルを手元に保存するのが安全です。

キーを付けても直らない403:ポーリングやBatchなど別の段階

ここまでの対処が当てはまるのは、生成が成功してURIを受け取り、そのURIを取りにいく段階で403になる場合です。どの段階で失敗したかで、原因も対処も変わります。

403が出た段階状況取るべき行動
生成リクエスト自体キーの制限、ブロックされたキー、APIの未有効化などの可能性「Gemini APIキーの403権限エラー:拒否された処理から直す手順」の切り分けに進む
ポーリング(operations.get)URIがまだ存在しない段階での403下記のとおり未解決の報告。キーを足す対処は当てはまらない
動画のURIの取得キーなしのリクエスト生成と同じAPIキーをダウンロードのリクエストに付ける
Batch APIの結果ファイルの取得キーを付けても拒否されたという報告が1件下記のとおり未解決

ポーリングでの403。 2026年9月29日に、veo-3.1-generate-previewのオペレーションは作成できるのに、operations.get()が403 PERMISSION_DENIEDを返すという報告が投稿されています。google-genai Python 2.25.0で、6件のオペレーションすべてで発生したという内容です。2026年10月2日時点で返信はなく、原因は分かっていません。1人のユーザーの報告で、ダウンロードの403とは別の段階の問題です。

Batch APIの結果ファイル。 2025年11月24日には、Batch APIの結果ファイルを/download/v1beta/files/...から取得する際、x-goog-api-keyヘッダーでもkey=でも拒否されたという書き込みがあります。同じキーでステータスの取得はできていたそうです。Veoではなく別のエンドポイントの話で、これも解決していません。「キーを付ければ必ず通る」とは言い切れないことを示す例です。

別のプロジェクトのキー。 生成とダウンロードで違うキーを使っている場合は、生成に使ったキーに揃えてください。フォーラムの回答が「動くはず」としているのは、同じAPIキーを使う場合だけです。

Vertex AI経由のVeo。 Vertex AIはそもそもこのURIを返しません。Vertex AIのリファレンスによると、リクエストにstorageUri(gs://BUCKET_NAME/SUBDIRECTORYの形)を指定するとレスポンスにgcsUriが入り、指定しなければbase64でエンコードされた動画がbytesBase64Encodedとして返ります。gs://で始まるURIはCloud Storageのオブジェクトのパスで、HTTPのリンクではありません。読み出すには、呼び出す側にCloud Storageへのアクセス権が必要です。逆に、Gemini API側にoutput_gcs_uriを渡しても、返ってきたのはgenerativelanguage.googleapis.comのURIのままだったという報告があります。

サードパーティのAPIゲートウェイ経由。 Googleではない事業者のエンドポイントを通している場合、返ってくるURL、保存期間、403の原因はその事業者のものです。2日という期限やx-goog-api-keyの扱いは、Googleのエンドポイントを直接呼んでいる場合の話なので、その事業者のドキュメントを確認してください。

Veo 3.1の生成からポーリング、ダウンロードまでの一連の流れを実装し直す場合は、「Sora 2からVeo 3.1へ移行するには?APIの違いと実装手順」で長時間実行オペレーションの扱いを確認できます。

さらに読む: API ガイド
Gemini 3.8 Flash TTS と Flash-Lite TTS の1分あたり料金、台本・演出・声に分ける入力、2027年からの単価2倍を示す図
API ガイド

Gemini 3.8 Flash TTS API:料金と移行手順

演技なら Flash、量産なら Flash-Lite。音声1分の料金は$0.0135と$0.009(2026年)、無料枠あり。3.1 preview とは書き方が5点違います。

29 分