How To Use YouTube API To Upload Videos

Upload videos with the YouTube API using videos.insert: OAuth 2.0 setup, a resumable Python upload, retry handling, and the 1,600 unit quota cost per upload.

Sreshtha Das
Content Lead at Phyllo, overseeing editorial strategy and long-form content.
August 6, 2026
August 6, 2026
Summarize this article with AI
GeminiChatGPTClaudePerplexityGrok

TL;DR The YouTube API enables developers to upload videos programmatically, retrieve video details, manage channels, and automate content workflows. This guide covers key use cases, step-by-step upload processes, data retrieval methods, and best practices for building scalable video integrations.

This is some text inside of a div block.
  • Uploading videos with the YouTube API runs through the videos.insert endpoint, called with part=snippet,status and a resumable media body.
  • OAuth 2.0 with the youtube.upload scope is required, since an API key alone cannot post to a user's channel.
  • Each upload costs 1,600 quota units, so the default 10,000 unit daily cap covers roughly 6 uploads.
  • Resumable uploads in 5 MB chunks survive dropped connections and report real progress on large files.
  • Phyllo pulls post-upload performance data, including views, audience, and revenue, across 10+ platforms through one API with refresh under 24 hours.

Last verified: July 6, 2026 — flow confirmed against the official videos.insert reference.

TL;DR

Upload runs on the videos.insert endpoint. You need OAuth 2.0 (not just an API key), the youtube.upload scope, and a resumable upload for anything over a few MB. Each upload costs 1,600 quota units. Full working script is below — no punting to Google's docs.

What you need before you upload

Uploading requires user authorization, so an API key alone will not work.

  • Python 3.8+.
  • google-api-python-client, google-auth-oauthlib.
  • A Google Cloud project with YouTube Data API v3 enabled.
  • OAuth 2.0 client credentials (client_secret.json) from the Cloud Console.
  • The https://www.googleapis.com/auth/youtube.upload scope.

Install the libraries:

pip install google-api-python-client google-auth-oauthlib

Step 1: Authenticate with OAuth 2.0

Uploads act on a user's channel, so you need their consent via OAuth.

from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build

SCOPES = ["https://www.googleapis.com/auth/youtube.upload"]

flow = InstalledAppFlow.from_client_secrets_file("client_secret.json", SCOPES)
credentials = flow.run_local_server(port=0)   # opens the consent screen
youtube = build("youtube", "v3", credentials=credentials)

Step 2: Upload the video (resumable)

Use a resumable upload. It survives network drops and works for large files.

from googleapiclient.http import MediaFileUpload

request_body = {
    "snippet": {
        "title": "My uploaded video",
        "description": "Uploaded via the YouTube Data API",
        "tags": ["phyllo", "youtube api"],
        "categoryId": "22",          # People & Blogs
    },
    "status": {
        "privacyStatus": "private",  # public | private | unlisted
    },
}

# 5 MB chunks → real progress updates + resume after a dropped connection.
media = MediaFileUpload("video.mp4", chunksize=5 * 1024 * 1024, resumable=True)

request = youtube.videos().insert(
    part="snippet,status",
    body=request_body,
    media_body=media,
)

Step 3: Execute with progress and error handling

This is what makes the upload production-ready — retry on transient errors, report progress.

import time
from googleapiclient.errors import HttpError

RETRIABLE = {500, 502, 503, 504}

def upload(request, max_retries=5):
    response = None
    retry = 0
    while response is None:
        try:
            status, response = request.next_chunk()
            if status:
                print(f"Uploaded {int(status.progress() * 100)}%")
        except HttpError as e:
            if e.resp.status in RETRIABLE:
                retry += 1
                if retry > max_retries:
                    raise
                time.sleep(2 ** retry)   # exponential backoff
                continue
            raise   # non-retriable: quotaExceeded, invalid request, or auth error
    print("Done. Video ID:", response["id"])
    return response["id"]

video_id = upload(request)  # each upload costs 1,600 quota units

That is the full working upload — OAuth, resumable transfer, retry, progress. No link-out.

After the upload: pull the performance data

Uploading is half the job. Next you need to know how those videos perform — views, watch time, and audience — often across many creators and channels.

Here the native API gets painful. Analytics needs a separate OAuth flow per channel, quota is capped at 10,000 units/day, and refresh is all on you. Tracking performance for a roster of creators blows past the quota fast.

This is where Phyllo fits. Once videos are live, Phyllo pulls their performance data at scale through one API. That includes content metrics, audience demographics, and revenue. No per-channel OAuth or quota rotation. Data refreshes in under 24 hours, and the same integration covers 10+ platforms.

Pull video performance through Phyllo

Phyllo uses HTTP Basic auth with your client_id and client_secret. Call it server-side only. account_id comes from linking the creator through Phyllo Connect.

import requests

CLIENT_ID = "YOUR_PHYLLO_CLIENT_ID"
CLIENT_SECRET = "YOUR_PHYLLO_CLIENT_SECRET"
ACCOUNT_ID = "YOUTUBE_ACCOUNT_ID"  # from the Phyllo Connect flow

resp = requests.get(
    "https://api.getphyllo.com/v1/social/contents",
    auth=(CLIENT_ID, CLIENT_SECRET),   # HTTP Basic, not Bearer
    params={"account_id": ACCOUNT_ID},
    timeout=10,
)
resp.raise_for_status()
for content in resp.json()["data"]:
    print(content["title"], content["engagement"]["view_count"])

Proof point: one integration returns performance for every video across every connected creator — no separate OAuth or quota approval per channel.

Get your free API key →    Book a demo

Upload best practices

  1. Use OAuth 2.0, not an API key. Uploads need user authorization.
  2. Always upload resumable. It handles large files and dropped connections.
  3. Retry only transient errors. Back off on 5xx. Do not retry quotaExceeded.
  4. Set metadata and privacy up front. Title, description, tags, and privacyStatus.
  5. Poll processing status. Check videos.list before telling users the video is ready.

FAQs

Which endpoint uploads a video? videos.insert, with part=snippet,status and a resumable media_body.

Do I need an API key or OAuth? OAuth 2.0. Uploads act on a user's channel, so a plain API key is not enough.

How much quota does an upload cost? 1,600 units. Your 10,000-unit daily cap allows about 6 uploads before a quota increase.

How do I handle upload errors? Retry 5xx errors with exponential backoff. Do not retry quotaExceeded — wait for the reset.

How do I track a video's performance after upload? Use videos.list for basics, or a unified API like Phyllo to pull performance across many creators without per-channel OAuth.

Related: Is the YouTube API free? (quota costs) · YouTube API limits explained · YouTube API functionalities & common errors

Which YouTube API endpoint uploads a video?

The videos.insert endpoint uploads a video. Call it with part=snippet,status and a resumable media_body, and it sends the file and the metadata in a single request.

Do I need an API key or OAuth to upload to YouTube?

OAuth 2.0, not an API key. An upload acts on a user's channel, so you need their consent through the youtube.upload scope before videos.insert will accept the file.

How much quota does a YouTube video upload cost?

One upload costs 1,600 quota units. Against the default allowance of 10,000 units per day, that is roughly 6 uploads before you have to request a quota increase.

How do I handle YouTube upload errors and retries?

Retry transient 5xx responses, 500, 502, 503 and 504, using exponential backoff and a cap of about 5 attempts. Do not retry quotaExceeded, which clears at the daily reset.

Why should a YouTube upload be resumable?

A resumable upload survives dropped connections and handles large files. Setting MediaFileUpload with a 5 MB chunksize also gives you real progress percentages while it runs.

What do I need installed to upload videos with Python?

Python 3.8 or newer, plus the google-api-python-client and google-auth-oauthlib packages from pip, and a client_secret.json file from your Google Cloud OAuth credentials.

Are videos uploaded through the YouTube API public by default?

You choose the privacyStatus value yourself: public, private or unlisted. Videos from unverified API projects created after 28 July 2020 stay private until Google audits the project.

How do I track a video's performance after uploading it?

Poll videos.list for basic stats, or route it through Phyllo to get views, watch time, audience and revenue for every connected creator without a separate OAuth flow per channel.

How does Phyllo help once the videos are live?

Phyllo is a social data infrastructure platform for creator data. One API returns content metrics, audience demographics and revenue across 10+ platforms, refreshed inside 24 hours.

Download our detailed guide on how to leverage Instagram Stories for influencer marketing

Download Now
Table of Content
See Phyllo in action
  • No Credit card required
  • GDPR & SOC2 Type II
  • 30-min Onboarding
Book a Demo

Be the first to get insights and updates from Phyllo. Subscribe to our blog.

Ready to get started?

Sign up to get API keys or request us for a demo