Skip to main content

YouTube CLI uploader

This is a small Python client for uploading videos to an owned YouTube channel through the YouTube Data API v3. It uses OAuth authorization, resumable uploads, and private uploads by default.

The uploader can send a title, description, tags, category, language, audience setting, synthetic media disclosure, thumbnail, and caption track. It then checks YouTube until processing succeeds.

Installation

Install the CLI from PyPI with uv:

uv tool install youtube-cli-uploader

This installs the youtube-upload, youtube-authorize, and youtube-delete commands.

Authorization

Create an OAuth desktop client in Google Cloud for a project with the YouTube Data API v3 enabled. Download the client JSON to:

~/.config/youtube-api-uploader/client_secret.json

Authorize the channel:

youtube-authorize

Authorization prints the channel title, ID, and URL. On a headless host, forward the selected port over SSH and run authorization with --no-browser --port PORT.

Upload

youtube-upload video.mp4 \
  --title "Example upload" \
  --description-file description.txt \
  --tag example \
  --thumbnail thumbnail.jpg \
  --captions captions.srt \
  --contains-synthetic-media

Uploads are private unless --privacy unlisted or --privacy public is provided. API projects that have not completed YouTube's compliance audit may be restricted to private uploads.

The uploader saves the video ID and completed steps beside the video in VIDEO.youtube-upload.json. Run the same command again after a failure to resume the existing upload instead of creating a duplicate. Use --state PATH to choose another state location.

Delete an uploaded video by ID:

youtube-delete VIDEO_ID

Example

example/ contains a ready-to-upload private test with a 5.2 KB MP4, thumbnail, description, and captions.

API operations

  • videos.insert creates the video, sends its metadata, and uploads the MP4 in resumable chunks.
  • thumbnails.set attaches the optional JPEG thumbnail.
  • videos.list checks upload and processing status.
  • captions.insert attaches the optional caption file after video processing succeeds.
  • captions.list checks that the caption track reaches serving status.

The client requests the youtube.upload and youtube.force-ssl OAuth scopes. OAuth client secrets and user tokens remain in the local configuration directory and are excluded from Git.

Tests

uv --no-config run --locked python -m unittest discover -s tests
uv --no-config build --no-sources

The acceptance demo builds a wheel, installs it in a clean environment, records a deterministic upload and deletion against a local YouTube API fixture, checks the transcript, and stores the wheel, recording, transcript, and checksums as CI artifacts. It does not need GitHub secrets or use YouTube quota.

Live verification recording

Create a reviewer-facing recording against the authorized YouTube channel with:

demo/record-live.sh

Pass a different token or artifact directory as the first and second arguments. The script runs the locked tests, builds one wheel, installs that wheel in a clean environment, records a private upload using the committed example assets, prints the channel URL returned by YouTube, and deletes the test video. An exit trap also attempts deletion if a later upload step fails. The token is neither shown in the recording nor copied into the artifacts. Idle gaps longer than two seconds are shortened in the saved cast without changing its output, and the final screen remains visible for five seconds.

The recording, transcript, wheel, and checksums are written to artifacts/live-demo/. Review the recording before sharing it and provide the printed channel URL in the verification email.

Data handling

The scripts run locally and communicate directly with Google's OAuth and YouTube API endpoints. They do not operate a server, collect analytics, or send video data or credentials to any other service. OAuth tokens and upload state are stored locally with owner-only permissions. Revoking the app in the Google Account permissions page disables future access.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

youtube_cli_uploader-0.2.0.tar.gz (54.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

youtube_cli_uploader-0.2.0-py3-none-any.whl (9.4 kB view details)

Uploaded Python 3

File details

Details for the file youtube_cli_uploader-0.2.0.tar.gz.

File metadata

  • Download URL: youtube_cli_uploader-0.2.0.tar.gz
  • Upload date:
  • Size: 54.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for youtube_cli_uploader-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c2bc3f00307ba6c91fd5fc8bec4ca997f11a3e59c9fb98099b55057ded5cf124
MD5 5c0bf350a032ccfc523a9cdfa7d3144a
BLAKE2b-256 9577fa3642f5442a0249065b9f34a35c4507e1046f43dfba69cddf098ea6ed81

See more details on using hashes here.

File details

Details for the file youtube_cli_uploader-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: youtube_cli_uploader-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 9.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for youtube_cli_uploader-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ae14c03386df22af28b3d01e3536cfcc49b88e56eeb2821a963624df4f95ea6f
MD5 6f3f1faf4d2fb1a11f2767776430f7b1
BLAKE2b-256 5a9702f24af1e5c986f426184b1d598a26f481e1074d55f6b993afbfa8c1bc14

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page