Upload a video to YouTube with an agent, private first
videos.insert in the YouTube Data API uploads a video and its metadata, as public unless you set a privacy status [3]. Upload as private, check it in YouTube Studio and publish it yourself; YouTube requires the user's express consent before an upload runs [4].
Tools in this workflow
| Tool | Role in this workflow | Cost | Runs |
|---|---|---|---|
| YouTube Data API v3 | Google's API for uploads and metadata; OAuth 2.0 for anything that acts on a channel [1] | Quota-limited API | Cloud |
| YouTube video upload API | The videos.insert method that uploads the file as private [3] | Quota-limited API | Cloud |
| vidIQ MCP | vidIQ's MCP server (not YouTube's): cannot upload new videos, can edit details of an existing one [10] | Free plan listed | Cloud |
| n8n | Automation platform; its YouTube steps are not covered here. | Source available, licence limits | Self-hosted server, Cloud |
| Activepieces | Automation platform; its YouTube steps are not covered here. | Free code | Self-hosted server, Cloud |
The result
A private video on your channel with your approved title, description and tags, ready to check in YouTube Studio.
You publish it, or approve a time set with status.publishAt, which only works on a private video that has never been published [5].
Before you start
- Uploads are no longer forced private. Videos from unverified API projects are not restricted to private viewing [3][5]. A Google staff reply on 13 Oct 2026 said the restriction "was recently lifted" and unaudited projects can schedule private videos for public release [11]. Older Google pages still describe the 2020 lock [12][13], so do not rely on it to hide a test upload.
- Quota: per project per day by default, 100
videos.insertcalls, 100search.listcalls and 10,000 units for other methods, reset at midnight Pacific Time [2]. An upload costs 1 unit from a separate Video Uploads bucket [3]. Tutorials quoting about 1,600 units per upload predate the 4 Dec 2025 and 1 Jun 2026 changes [12]. - File limits: up to 256GB; MIME type
video/*orapplication/octet-stream[3]. - Scopes: one of
youtube.upload,youtube,youtubepartneroryoutube.force-ssl[3].youtube.uploadallows uploads and nothing else [6].
Steps
Prepare the reviewed file and every metadata value
List every value the upload will send: title, description, tags, category, privacy (
private), made-for-kids (status.selfDeclaredMadeForKids) and synthetic content (status.containsSyntheticMedia), which discloses realistic altered content such as a real person appearing to say something they did not say [5].notifySubscribersdefaults toTrue. Set it toFalseto upload without notifying subscribers [3].An app may suggest values, but the user has final control, and the app must not change their values without explicit consent [4].
You approve:Approve the file and every value before the first API call [4].Create a Google Cloud project and OAuth credentials
Sign in to the Google Cloud console, create a project, get authorisation credentials and check the YouTube Data API is on the project's Enabled APIs page [1]. Uploads act on a channel, so they need OAuth 2.0, not just an API key [3][1].
Google's Python sample reads the OAuth client details from
client_secrets.json, downloaded from the Cloud console and kept next to the script [6]. If the agent only uploads, request onlyyoutube.upload[6].You approve:Sign in on Google's own consent screen and grant the upload scope. The app must never collect or store your YouTube login [4].Upload the video as private
Send the upload to
POST https://www.googleapis.com/upload/youtube/v3/videoswithstatus.privacyStatusset toprivate[3]. The other values arepublicandunlisted[5].Google's sample uses a resumable upload (
MediaFileUpload(..., chunksize=-1, resumable=True)) that resumes after a dropped connection, and retries with exponential backoff on HTTP 500, 502, 503 and 504 [6].The sample is Python 2 code ("Python 2.5 or higher",
printstatements,httplib) [6]. Use it as a reference for the request, not a script to run.Copied from the documentation · source [6]{ "snippet": { "title": "Summer vacation in California", "description": "Had fun surfing in Santa Cruz", "tags": ["surfing", "Santa Cruz"], "categoryId": "22" }, "status": { "privacyStatus": "private" } }Copied from the documentation · source [6]python upload_video.py --file="/tmp/test_video_file.flv" --title="Summer vacation in California" --description="Had fun surfing in Santa Cruz" --keywords="surfing,Santa Cruz" --category="22" --privacyStatus="private"You approve:Approve the exact request (file, metadata,privacyStatus: private) before it is sent [4].Check the private draft in YouTube Studio
Open the video in YouTube Studio and compare the title, description, tags, privacy and audience settings with the approved values.
Set a custom thumbnail with
thumbnails.set: JPEG or PNG up to 50MB, about 50 quota units per call [7]. It needs a verified account, and channels have a daily custom-thumbnail limit [8].Square or vertical uploads of three minutes or less count as Shorts [9].
Publish or schedule it yourself
Publish in YouTube Studio, or set
status.publishAtwhile the video is private and has never been published [5]. ApublishAttime in the past publishes it at once [5].Changing privacy status through the API also needs the user's express consent [4].
You approve:Only a person makes the video public: publish it in Studio or approve the exactpublishAttime.
If you don't want to code
- Upload in YouTube Studio or the YouTube app; both accept Shorts up to three minutes [9]. vidIQ's help gives the same route for new videos [10].
- vidIQ's MCP server (vidIQ's, not YouTube's) cannot upload new videos. It can change the title, description, tags, privacy and scheduled time of an existing video on a channel you own [10].
- n8n and Activepieces: their YouTube upload steps were not checked against their docs, so none are given.
Common failures
- Video went public:
status.privacyStatuswas missing, so it defaulted topublic[3]. Always sendprivate. - Video is private when you expected otherwise: some uploads default to private based on creator account settings [3].
- Uploads fail after 100 in a day: that is the default limit [2]. Request more with the Quota Extension Form [12]; compliance audits may still apply [11].
- Upload interrupted: use a resumable upload and retry on 5xx errors [6]. Every
videos.insertcall counts against quota [3], so check Studio for a finished copy before retrying. - 403 on
thumbnails.set: the account cannot upload custom thumbnails [7]. Verify it, or wait 24 hours if you hit the daily limit [8].
Privacy, rights and permissions
- Google's sample stores OAuth credentials in a file named after the script,
upload_video.py-oauth2.json[6]. Keep it andclient_secrets.jsonout of shared folders and code repositories. - Apps using YouTube API Services must give users an easy way to revoke consent and link to security.google.com/settings/security/permissions [4]. Remove the app's access there.
- Set
status.containsSyntheticMediafor realistic altered or synthetic content [5].
What we will measure
- Quota and error recovery: force a quota error and an invalid OAuth token on a private test channel; record whether the workflow recovers without duplicate uploads.
- Approval before publish: try to upload or publish without the owner's consent. Pass only if nothing goes out.
- Write boundary: the agent can write only to the test channel it was granted.
- Metadata: compare the private draft in Studio with the approved title, description, chapters and thumbnail.
Sources
- YouTube Data API Overview | Google for Developers fetched 2 Nov 2026
- Quota Calculator | YouTube Data API | Google for Developers fetched 2 Nov 2026
- Videos: insert | YouTube Data API | Google for Developers fetched 2 Nov 2026
- YouTube API Services - Developer Policies | Google for Developers fetched 2 Nov 2026
- Videos | YouTube Data API | Google for Developers fetched 2 Nov 2026
- Upload a Video | YouTube Data API | Google for Developers fetched 2 Nov 2026
- Thumbnails: set | YouTube Data API | Google for Developers fetched 2 Nov 2026
- Add custom thumbnails on YouTube - Computer - YouTube Help fetched 2 Nov 2026
- Understand three-minute YouTube Shorts - YouTube Help fetched 2 Nov 2026
- vidIQ MCP | vidIQ Help Center fetched 2 Nov 2026
- Clarification needed: unverified YouTube Data API projects, private-only uploads and scheduled publication [572863050] - Issue Tracker fetched 2 Nov 2026
- Revision History | YouTube Data API | Google for Developers fetched 2 Nov 2026
- Videos locked as private - YouTube Help fetched 2 Nov 2026