Перейти к основному содержанию

Veo: ошибка 403 при скачивании видео — запросу нужен API-ключ

Видео Veo готово, а ссылка из video.uri отдаёт 403: запрос ушёл без API-ключа. Передайте ключ в заголовке x-goog-api-key или скачайте файл через SDK.

LaoZhang AI TeamОпубликовано9 мин чтения
Содержание
Обложка: ошибка 403 при скачивании видео Veo — запрос без ключа получает 403 PERMISSION_DENIED, неверный ключ даёт 400 API_KEY_INVALID, решение — ключ в заголовке x-goog-api-key

Операция Veo в Gemini API завершилась, генерация оплачена, в ответе лежит video.uri — а запрос по этому адресу возвращает 403. Причина почти всегда одна: адрес вида https://generativelanguage.googleapis.com/v1beta/files/FILE_ID:download?alt=media — это не публичная ссылка на файл, а такой же метод API, как запрос генерации. Он отвечает только вызывающему, который предъявил ключ. Браузер, тег video, отдельный HTTP-узел в n8n или fetch без заголовков ключ не передают и получают отказ.

Исправление: скачивайте файл тем же ключом, которым создавали операцию. В документации Veo это делается либо методом SDK files.download, либо HTTP-запросом с заголовком x-goog-api-key и следованием перенаправлениям. Включать API в проекте, менять роли IAM и пересоздавать ключ для этого случая не нужно: авторам веток на форуме Google AI Developers это не помогло.

Дальше по порядку: что именно возвращает сервер и как по ответу понять свой случай, запросы для четырёх сред, показ видео конечным пользователям, срок хранения файла и случаи, где ключ в запросе скачивания ничего не изменит.

Что отвечает сервер: 403 без ключа и 400 с неверным ключом

Сначала о том, что из сказанного ниже запускалось, а что нет.

Запускалось. 2 октября 2026 года на адрес скачивания были отправлены три запроса curl с выдуманным идентификатором файла abc123xyz000: без ключа по пути /v1beta/files/..., без ключа по пути /download/v1beta/files/... и с заведомо неверным ключом в заголовке x-goog-api-key.

Не запускалось. Реальная генерация Veo и успешное скачивание файла не выполнялись: в среде проверки не было ключа Gemini API с подключённой оплатой. Поэтому рабочие запросы ниже приведены по документации Google и по сообщениям пользователей форума, с пометкой у каждого, и не являются записью удачного запуска.

Запрос без ключа, оба варианта пути, вернул одно и то же:

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"
  }
}

Запрос с неверным ключом вернул уже не 403, а 400:

json
{
  "error": {
    "code": 400,
    "message": "API key not valid. Please pass a valid API key.",
    "status": "INVALID_ARGUMENT",
    "details": [
      { "reason": "API_KEY_INVALID", "domain": "googleapis.com" }
    ]
  }
}

Из этих двух ответов следуют два вывода. Первый: отказ без ключа приходит ещё до поиска файла — файла abc123xyz000 не существует, а сервер ответил 403, а не 404. То есть 403 на скачивании говорит о вызывающем, а не о видео. Второй: если ключ дошёл до сервера, но он неверный, код будет 400 с API_KEY_INVALID. Значит, 403 с текстом про unregistered callers означает, что ключ до сервера не дошёл совсем — потерялся заголовок, переменная окружения пуста или запрос отправила среда, которая о ключе не знает.

Проверить собственный случай можно одной командой с вашим адресом из video.uri, без ключа:

bash
curl -s "https://generativelanguage.googleapis.com/v1beta/files/FILE_ID:download?alt=media"
Что пришло в ответЧто это значитЧто делать
403 PERMISSION_DENIED, Method doesn't allow unregistered callersВ запросе скачивания нет ключаПередать ключ: SDK или заголовок x-goog-api-key
403 PERMISSION_DENIED, SERVICE_DISABLED, проект 542708778979Тот же случай в формулировке из веток 2025 годаТо же самое; чужой проект в консоли не искать
400 INVALID_ARGUMENT, API_KEY_INVALIDКлюч дошёл, но он неверныйПроверить, какое значение реально подставляется в запрос
403 на запросе генерации, до появления операцииОтказ на другом этапеРазбирать ключ, проект и ограничения, а не скачивание
403 на опросе операции operations.getОтказ до появления video.uriГотового решения нет, см. последний раздел

Схема разбора ответа сервера при скачивании видео Veo: 403 без ключа, 403 с проектом 542708778979, 400 с неверным ключом и отказы на этапах генерации и опроса операции

Почему в ошибке чужой проект 542708778979 и SERVICE_DISABLED

Потому что запрос пришёл без учётных данных, и сервер отнёс его не к вашему проекту. В ветках форума за май–сентябрь 2025 года (96867, 106512, 85592) ответ на такой запрос выглядел так:

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 и consumer: projects/542708778979. Авторы веток подтверждают: такого проекта у них нет, а номер одинаков у разных людей с разными ключами. Среды при этом самые разные: Supabase Edge Functions на Deno, Python с FastAPI, Django, узел HTTP Request в n8n, Node 22.

Сообщение сбивает с толку, потому что предлагает включить API. Люди открывают консоль, не находят проект, включают Generative Language API в своём, правят IAM, выпускают новый ключ — и получают тот же ответ. Откуда берётся именно этот номер, Google в ветках не объяснял. Версия участников форума — запросы без ключа приписываются служебному проекту Google — остаётся их догадкой. Название «Project Mismatch», которое встречается в одной из веток, придумал её автор; официального диагноза с таким именем нет.

Практический вывод не зависит от разгадки: и текст 2025 года про проект 542708778979, и текст про unregistered callers от 2 октября 2026 года описывают запрос без ключа. Марк Дауст (Mark Daoust), отвечавший в ветке от имени команды SDK, 23 октября 2025 года написал прямо: «Getting that error is "normal" when pasting the URL with no key into a web-browser. But it should not be coming back from ai.files.download» — при вставке адреса в браузер без ключа такая ошибка ожидаема, а из метода SDK она приходить не должна.

Как скачать видео Veo: способ зависит от того, кто шлёт запрос

Ключ должен попасть именно в запрос скачивания; как это сделать, определяется средой.

СредаКак передать ключОткуда способ
Серверный код с SDK: Python, Node.js, GoМетод files.download того же клиентаДокументация Veo
Запрос без SDK: curl, fetch, requestsЗаголовок x-goog-api-key, следовать перенаправлениямДокументация Veo
Узел HTTP Request в n8n и подобныеТот же заголовок в узле скачиванияВетки форума
Браузер: тег video, ссылка, fetch на страницеНапрямую никак: скачать на сервере и отдать свою ссылкуВывод из устройства адреса

SDK на сервере: files.download тем же клиентом

Клиент, созданный с ключом, сам подписывает запрос скачивания. Фрагменты из документации Veo, после завершения операции:

python
generated_video = operation.response.generated_videos[0]
client.files.download(file=generated_video.video, destination="dialogue_example.mp4")
javascript
ai.files.download({
    file: operation.response.generatedVideos[0].video,
    downloadPath: "dialogue_example.mp4",
});

В JavaScript-примере документации вызов стоит без await. Если следующий шаг сразу читает файл, добавьте await: коммит googleapis/js-genai@127c9bf, на который в ветке сослались 24 октября 2025 года, исправил загрузчик так, что после ожидания запись файла гарантированно завершена. Этот коммит лечит пустой или обрезанный файл, а не 403. Параметр downloadPath пишет в локальную файловую систему, поэтому вызов рассчитан на Node.js, а не на страницу в браузере.

Если 403 приходит именно из files.download, это не штатное поведение. Команда SDK воспроизвести такой случай не смогла и спрашивала в ветке, все ли пострадавшие работают в Supabase Edge Functions на Deno; подтверждённой причины там нет. Рабочий обход для этой ситуации — взять video.uri и скачать файл обычным HTTP-запросом с заголовком, как в следующем разделе.

Запрос без SDK: заголовок x-goog-api-key и флаг -L

REST-пример из документации Veo берёт адрес из поля .response.generateVideoResponse.generatedSamples[0].video.uri и скачивает файл так:

bash
# 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}"

Здесь важны две детали. Заголовок тот же, что в запросе генерации и в опросе операции. Флаг -L заставляет curl идти по перенаправлениям; в собственном HTTP-клиенте проверьте, что он делает то же самое и что переменная с ключом не пуста в том процессе, который скачивает файл.

В ветке 96867 принят другой вариант — ключ в строке запроса. Код с форума, автор ссылается на пример Veo 3 в AI Studio:

javascript
const url = decodeURIComponent(generatedVideo.video.uri);
const res = await fetch(`${url}&key=${process.env.API_KEY}`);

Не менее четырёх участников подтвердили, что это сработало: в августе и сентябре 2025 года и в апреле 2026 года. В документации Veo формы с key= нет, там показан только заголовок. Заголовок предпочтительнее и по другой причине: ключ в адресе попадает в журналы запросов и виден всем, кто видит ссылку.

n8n и другие HTTP-узлы: ключ нужен и в узле скачивания

В автоматизациях генерация и опрос проходят успешно, потому что в этих узлах ключ настроен, а файл забирает отдельный узел HTTP Request, которому передали только адрес. Он отправляет запрос без ключа и получает 403 — так описан случай в ветке 85592. Ответ там короткий: если генерация и скачивание идут с одним и тем же ключом, всё должно работать.

Добавьте в узел скачивания заголовок x-goog-api-key с тем же ключом, что в узле генерации, и убедитесь, что узел следует перенаправлениям. Основание для этого шага — документированный запрос curl выше и сообщения пользователей; записи запуска в самом n8n за ним нет.

Браузер и тег video: заголовок добавить нельзя

Тег video и обычная ссылка на странице отправляют запрос без x-goog-api-key, и добавить заголовок в них нельзя. Поэтому адрес из video.uri, вставленный в src или href, всегда даст 403. Именно это описано в открытой заявке Genkit № 4025 от 30 декабря 2025 года: плагин @genkit-ai/google-genai отдаёт необработанный адрес как media.url, интерфейс разработчика подставляет его в плеер и получает отказ. На 2 октября 2026 года заявка остаётся открытой.

Видео для конечных пользователей: ключ в ссылке виден в браузере

Отдавать пользователям адрес Google с дописанным key= нельзя: всё, что попало в браузер, пользователь может прочитать, а вместе со ссылкой он получает ваш ключ. Об этом же спрашивали в ветке 30 декабря 2025 года — нужна подписанная ссылка для браузера, потому что раскрывать ключ в адресе недопустимо. Ответа на вопрос нет, и в документации Veo подписанных или публичных ссылок для Gemini API не описано.

Остаётся серверная схема. Это рекомендация, вытекающая из устройства адреса, а не предписание Google:

  1. Сервер дожидается завершения операции и скачивает файл с ключом.
  2. Сервер кладёт байты в собственное хранилище — объектное хранилище, диск, CDN.
  3. Пользователь получает ссылку на ваше хранилище, с вашими правилами доступа и сроком жизни.

Серверная схема показа видео Veo: сервер скачивает файл с ключом, кладёт его в своё хранилище, пользователь получает вашу ссылку; прямой запрос браузера по video.uri получает 403

Схема заодно снимает вопрос о сроке хранения на стороне Google.

Сколько живёт ссылка: файл удаляется через 2 дня

Сгенерированные видео хранятся на сервере 2 дня, после чего удаляются; чтобы сохранить копию, файл нужно скачать в течение 2 дней после генерации — так сказано в документации Veo. Продлённое видео считается новым, а обращение к видео для продления сбрасывает его двухдневный отсчёт.

Какой код вернёт сервер по адресу удалённого файла, в документации не сказано, и проверка этого не проводилась. Если запрос с верным ключом перестал работать на третий день, сначала сверьте дату генерации.

Повторять запрос в цикле при 403 бессмысленно. Руководство по устранению неполадок Gemini API советует повторять только временные ошибки — 429, 408 и 5xx — и прямо говорит не повторять клиентские, включая 403. Пока в запросе нет ключа, каждый повтор получит тот же ответ, а два дня хранения продолжат идти.

Когда ключ в запросе скачивания не поможет

Всё сказанное выше относится к одному случаю: операция Veo в Gemini API завершилась, video.uri получен, отказ приходит при скачивании. В остальных ситуациях действовать нужно иначе.

403 пришёл на сам запрос генерации. Операция не создана, скачивать нечего. Причины лежат в ключе, проекте, ограничениях ключа или регионе; порядок проверки описан в материале «Gemini API key: ошибка 403 Permission Denied — диагностика по месту отказа». К этой же группе относится недоступность Gemini API и AI Studio из России напрямую: до ошибки скачивания доходит только код, который уже работает на зарубежной инфраструктуре.

403 пришёл при опросе операции. В сообщении от 29 сентября 2026 года operations.get() возвращал 403 PERMISSION_DENIED для шести из шести операций veo-3.1-generate-preview, успешно созданных через google-genai для Python версии 2.25.0. Это единичное сообщение без ответов и без установленной причины; адреса видео на этом этапе ещё нет, и ключ в запросе скачивания тут ничего не меняет. Как в целом устроена длительная операция Veo 3.1 и её опрос, разобрано в статье «Переход с Sora 2 на Veo 3.1: сравнение API и перенос интеграции».

Файлы Batch API. Один пользователь 24 ноября 2025 года сообщил, что результаты пакетной обработки по пути /download/v1beta/files/... не скачивались ни с заголовком, ни с key=, хотя запросы статуса с тем же ключом проходили. Решения в ветке нет. Это другой тип файлов, но случай показывает, что «добавить ключ» — не универсальный ответ для любого скачивания.

Vertex AI. На этом маршруте адреса generativelanguage.googleapis.com/.../files/...:download нет вовсе. По справочнику Veo в Vertex AI, при указанном storageUri в ответе приходит gcsUri вида gs://BUCKET_NAME/TIMESTAMPED_FOLDER/sample_0.mp4, а без него — байты видео в base64. Путь gs:// — это объект Cloud Storage, а не HTTP-ссылка, и читать его может только тот, у кого есть доступ к бакету. Перенести этот параметр в Gemini API не получится: автор ветки 106512 передавал output_gcs_uri и всё равно получал адрес generativelanguage.

Сторонний шлюз или прокси. Если запрос идёт не к generativelanguage.googleapis.com, а к посреднику, он может возвращать собственный адрес файла, со своим сроком жизни и своими причинами 403. Срок в 2 дня и заголовок x-goog-api-key относятся к API Google; для посредника смотрите его документацию.

Вопросы об ошибке 403 при скачивании видео Veo

Generative Language API уже включён — почему всё равно 403?

Потому что сообщение относится не к вашему проекту. Запрос скачивания ушёл без ключа, сервер не знает, чей он, и в ветках 2025 года называл проект 542708778979, которого у вас нет. Включение API в своём проекте, роли IAM и новый ключ авторам веток не помогли; помог ключ в самом запросе скачивания.

Можно ли получить публичную или подписанную ссылку на видео Veo?

В документации Veo для Gemini API такой возможности нет, а вопрос о подписанной ссылке на форуме остался без ответа. Чтобы показать видео другим людям, скачайте файл на сервере и раздавайте его из собственного хранилища.

Нужно ли для скачивания использовать тот же ключ, что и для генерации?

Да, скачивайте тем же ключом, которым создавали операцию: так устроены примеры документации, и это же условие названо в ответе на форуме. Что вернёт сервер действующему ключу из другого проекта, в документации не описано.

Ключ передаётся, а ответ всё равно 403 — что проверить?

Сначала посмотрите текст ошибки. Если это unregistered callers или проект 542708778979, ключ до сервера не доходит: проверьте, что переменная окружения задана в процессе, который скачивает файл, и что заголовок действительно уходит из промежуточного узла или прокси. Если текст другой, сверьте этап по таблице в начале: 403 на генерации и на опросе операции имеют другие причины.