Skip to main content

YouTube API Quota

The YouTube Data API v3 enforces a daily quota of 10,000 units per project (resets at midnight Pacific Time). Lumio's backend makes several types of YouTube API calls through the channel connection credentials (app_credentials table). This page documents every call, its cost, and the estimated daily consumption.

Quota Cost Reference

Official costs per YouTube Data API v3 operation:

OperationEndpointCost (units)
List broadcastsliveBroadcasts.list1
List chat messagesliveChatMessages.list5
Send chat messageliveChatMessages.insert200
List channelschannels.list1
List videosvideos.list1
Searchsearch.list100
List subscriptionssubscriptions.list1
Transition broadcastliveBroadcasts.transition50

The default daily limit is 10,000 units. Higher limits require passing Google's Quota and Compliance Audit.

Lumio API Calls

Quota-Consuming Calls (YouTube Data API v3)

These calls count against the daily quota:

Broadcast Discovery

AspectDetails
EndpointliveBroadcasts.list
Cost1 unit
Sourcecrates/lo-youtube-api/src/client.rs get_live_broadcasts()

Only the YouTube Polling Worker makes this API call. The Copyright Worker and YouTube Bot read from the shared Redis cache instead (zero quota).

CallerFileIntervalDaily Units (per channel)
YouTube Polling Workerapps/api/src/workers/youtube.rs60s1,440
Copyright Detection Workerreads from Redis cache--0
YouTube Bot (channel sync)reads from Redis cache--0

The YouTube Worker stores active broadcasts in Redis at lumio:youtube:active_streams:\{account_id\} (TTL 120s). Both the Copyright Worker and YouTube Bot consume this cache instead of making independent API calls.

Chat Message Polling (REST Fallback)

AspectDetails
EndpointliveChatMessages.list
Cost5 units
Sourcecrates/lo-youtube-api/src/client.rs get_live_chat_messages()

Only used when gRPC streaming is unavailable (after 3+ consecutive failures). Can be disabled entirely via configuration (see below).

CallerFileIntervalDaily Units (per channel)
YouTube Worker (REST fallback)apps/api/src/workers/youtube.rs10s active / 30s idleup to 43,200 (worst case)
YouTube Bot (chat poll)apps/youtube-bot/src/bot.rs10s (configurable)up to 43,200 (worst case)

In practice the worker uses gRPC streaming (zero quota), so REST fallback rarely fires.

Channel Info Lookup

AspectDetails
Endpointchannels.list
Cost1 unit
Sourceapps/api/src/routes/connections.rs fetch_channel_info()
TriggerOnce per YouTube channel connection (OAuth callback)
Daily UnitsNegligible (< 10)

Quota-Free Calls

These do not count against the YouTube Data API quota:

ComponentAPIPurpose
gRPC Chat StreamingliveChatMessages.streamList (gRPC)Primary chat ingestion mode. Persistent server-push connection, zero quota.
InnerTube Embed Scrapeyoutube.com/live_chat (HTTP)Extracts InnerTube API key and continuation token for badge harvesting.
InnerTube Chat Pollyoutubei/v1/live_chat/get_live_chat (HTTP)Undocumented internal API for member badge image URLs.

Configuration

REST Fallback Toggle

The REST polling fallback can be disabled to save quota when gRPC is the only desired chat ingestion mode:

[youtube]
# Set to false for gRPC-only mode. Chat ingestion stops when gRPC is unavailable.
# ENV: LUMIO__YOUTUBE__REST_FALLBACK_ENABLED
rest_fallback_enabled = true # default

When disabled:

  • gRPC failures do not trigger REST polling fallback
  • The worker retries gRPC instead of switching to REST
  • Quota from liveChatMessages.list drops to zero

Daily Quota Calculator

Use this table to estimate daily quota consumption per account.

Per active channel (stream is live):

ComponentQuota per callCalls/hourQuota/hourQuota/day (8h stream)
YouTube Worker (broadcast poll)16060480
Copyright Worker0 (Redis)--00
Bot (channel sync)0 (Redis)--00
Chat (gRPC -- primary)0--00
Chat (REST -- fallback only)53601,80014,400
Subtotal (gRPC mode)60480
Subtotal (REST fallback)1,86014,880

Per idle channel (no stream):

ComponentQuota per callCalls/hourQuota/hourQuota/day
YouTube Worker (broadcast poll)160601,440
Copyright Worker0 (Redis)--00
Bot (channel sync)0 (Redis)--00
Subtotal601,440

Example: 1 Channel, 8h Stream (gRPC mode)

Idle hours (16h): 16 * 60 = 960 units
Stream hours (8h): 8 * 60 = 480 units
─────────
Total: 1,440 units / 10,000 limit (14%)

Example: 1 Channel, 8h Stream (REST fallback)

Idle hours (16h): 16 * 60 = 960 units
Stream hours (8h): 8 * 1860 = 14,880 units
─────────
Total: 15,840 units / 10,000 limit (158% -- OVER QUOTA)

Quota Safeguards

The backend handles quota exhaustion gracefully:

MechanismDetails
DetectionHTTP 403 (REST) or RESOURCE_EXHAUSTED (gRPC)
Backoff5-minute pause on quota exhaustion (QUOTA_BACKOFF_SECS = 300)
gRPC prioritygRPC streaming is preferred over REST polling (zero quota)
Adaptive pollingREST fallback respects polling_interval_millis from YouTube's response
Fallback chaingRPC fails 3x in 60s -> REST polling -> re-attempt gRPC after recovery
REST togglerest_fallback_enabled = false disables REST fallback entirely
Shared cacheCopyright Worker and Bot read broadcast status from Redis, not YouTube API

Requesting Higher Quota

To request a quota increase from Google:

  1. Pass the Quota and Compliance Audit
  2. Demonstrate compliance with YouTube API Terms of Service
  3. If previously audited within 12 months, use the Audited Developer Requests Form
  4. There is no published maximum -- increases are granted case-by-case