Cover for YouTube API quota exceeded: what it means and how to fix it

YouTube API quota exceeded: what it means and how to fix it

Hit quotaExceeded on the YouTube Data API? Google's default limits, when quota resets, what the audit form asks for, and how to upload without a project.

Oct 30, 20268 min readAlexandroAlexandro
Table of Contents

A quotaExceeded (403) error means your Google Cloud project has used up its daily YouTube Data API allowance, and YouTube will refuse further requests from it until the quota resets1. Uploads have a bucket of their own, so the error can hit after 100 videos.insert calls even when the rest of your quota looks untouched2. The fastest way out is to stop uploading through your own project: connect the channel to PublishQ and send the video through its API, CLI or MCP server. You don't need a Google project, so there is no quota of yours to run out.

youtube data api quotaExceeded 403 error upload limit

What Google gives every project by default

Google's quota page lists the default allocation for any project that turns on the YouTube Data API2:

BucketDefault per dayCost per call
videos.insert (uploads)100 calls1 unit, in the Video Uploads bucket3
search.list100 calls1 unit
Everything else combined10,000 units1 for most reads, 50 for most writes

A few more rows from the same table matter for an upload pipeline. Setting a custom thumbnail with thumbnails.set costs 50 units from the shared 10,000, and so do videos.update, playlistItems.insert and captions.delete. Uploading a caption track with captions.insert costs 4002. Daily quotas reset at midnight Pacific Time2.

You can watch your usage on the Quotas page of the Google Cloud console2. If that page shows the uploads bucket at 100 of 100, you have your answer.

Why it runs out sooner than you expected

The allowance belongs to the project, and the project is shared by every script, cron job and user that authenticates through it. A few patterns burn through it quickly:

  • Retry loops. Every request costs at least one unit, invalid ones included4. A script that retries a failed upload ten times can spend up to ten upload calls on one video.
  • Paging. Each extra page of results is charged again2, so a sync job that walks a big channel's video list every few minutes adds up.
  • Thumbnails and edits on top of uploads. One upload plus a thumbnail plus a metadata fix is 1 call from the uploads bucket and 100 units from the shared pool.
  • Several apps on one project. A test harness and the production pipeline on the same project eat from the same 100 uploads.
  • Multi-tenant tools. If you built something your clients use, all of their channels upload through your one project.

None of this is a bug in your code. The default is sized for light use, and real automation outgrows it.

Your three options

Wait for the reset

The counter goes back to zero at midnight Pacific2. For a one-off spike that is fine. Queue the remaining videos and run them after the reset. For a pipeline that hits the ceiling every day, waiting just moves the error to tomorrow.

Request a quota extension

Google requires an audit before it grants more quota than the default. The audit checks that your project complies with the YouTube API Services Terms of Service, and you start it by submitting the Audit and Quota Extension Form5. Google's team contacts you after you submit it. An extension within 12 months of a passed audit uses the same form, and there is a separate appeals form if you fail5.

The form asks for a lot6:

  • your legal name, your organization's legal name, address and website
  • the API client's name (it must not contain the word "YouTube" without written approval), its access URL, privacy policy and terms
  • demo login credentials with full access, or an end-to-end screencast if there is no demo account
  • the Google Cloud project numbers, with one form per API client
  • screenshots of your privacy policy, homepage and OAuth consent flow
  • for upload tools, either a complete working upload script or a screencast of the full flow ending with the video live on YouTube
  • the per-day quota you want and a detailed justification

The form also says applications must show "significant independent value" to the YouTube ecosystem, and those that cannot may not get more quota6. For a personal automation or an internal script, that is a hard case to make.

Upload through a service that already handles it

The third option is to stop being the API client at all. With PublishQ you connect your YouTube channel once, and every upload goes through PublishQ. You never create a Cloud project, never fill in the audit form and never watch a quota counter. In your code, videos.insert becomes two calls: upload the file, then create a post.

upload video to youtube without api quota using cli

Uploading through PublishQ

Three routes reach the same API. Pick the one that matches how your pipeline already runs.

From the terminal or CI

npm i -g @publishq/cli
pq login
pq accounts list --platform YOUTUBE
pq media upload --file ./video.mp4
pq posts create --content "Weekly build log, episode 12" \
  --account <account-id> --media-id <media-id> --publish-now

Every command returns JSON, so a shell script or a CI job can read the IDs with jq. In CI, set PUBLISHQ_API_KEY=pq_live_... instead of logging in. Swap --publish-now for --scheduled-at 2026-12-01T09:00:00Z to queue it, or leave both off to keep a draft. The full command list is in the CLI docs and on the YouTube CLI page.

From your own code

Create a key at https://publishq.com/app/api-keys, upload the file to POST /media (or get a signed upload URL from POST /media/uploads for files up to 4 GB, see media uploads), then create the post:

curl -X POST https://publishq.com/api/v1/posts \
  -H "Authorization: Bearer pq_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Weekly build log, episode 12",
    "mediaIds": ["3b9f6c2e-71d4-4a8e-9c05-d2e8a6f41b77"],
    "accounts": [{
      "accountId": "a7c41e90-5d2b-4f63-8e1a-0c9b7d3f6e24",
      "platformSpecificSettings": {
        "description": "Changelog and repo links below.",
        "privacyStatus": "unlisted",
        "categoryId": "28",
        "madeForKids": false
      }
    }],
    "publishNow": true
  }'

content is the YouTube title (100 characters max). privacyStatus defaults to public, so set it if you want an unlisted test first. The rest of the YouTube fields, including thumbnailMediaId for a custom thumbnail, are on the YouTube API docs page. TypeScript users can use @publishq/sdk instead of raw HTTP. More on the REST side is on the YouTube API page.

From a coding agent

If you wrote your upload script with Claude Code, Cursor or Codex, you can hand the job back to the same agent. In Claude Code:

claude mcp add --transport http publishq https://publishq.com/mcp

Then run /mcp, choose Authenticate and approve in the browser. Cursor takes {"mcpServers":{"publishq":{"url":"https://publishq.com/mcp"}}} in ~/.cursor/mcp.json. For Codex, run npx @publishq/cli@latest login, then codex mcp add publishq -- npx -y @publishq/mcp@latest. After that, "upload ./out/ep12.mp4 to my YouTube channel as unlisted, category 28" is a whole request. The agent calls publishq_upload_media and publishq_create_post for you. There is a longer walkthrough in uploading to YouTube from Claude Code and on the YouTube MCP page.

The API, CLI and MCP server are on every plan, the Free plan included. See pricing for the rest.

Setup guides for other agents

Each of these pages has the setup for that agent and YouTube-specific prompts:

For any other agent, open https://publishq.com/agents and paste the line at the top of that page into your agent. It sets itself up and sends you a link to approve the login in your browser.

After the switch

automated youtube uploads published successfully

The nightly job that used to stop at video 100 now finishes the queue. A retry no longer spends a call from a 100-a-day bucket of yours. The same create call can also carry TikTok, Instagram and Facebook accounts, each with its own caption, so one render can go out everywhere. If you want to keep a calendar view of what is queued, the YouTube scheduler shows it, and YouTube limits lists the title, description and tag rules a post still has to meet.

Stop planning uploads around Google's reset clock. Create a PublishQ account, connect your channel and send the next video through it.

Footnotes

  1. Errors - YouTube Data API (2026-11) - quotaExceeded (403): the request cannot be completed because the quota is exceeded ↩

  2. Quota costs for API requests - YouTube Data API (2026-11) - default allocation of 100 search.list calls, 100 videos.insert calls and 10,000 units for other endpoints, separate buckets, per-method costs, paging charged per page, reset at midnight Pacific Time, Quotas page in Cloud console ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7

  3. Videos: insert - YouTube Data API (2026-11) - 100 calls per day, 1 unit per call in the Video Uploads quota bucket ↩

  4. Getting started - YouTube Data API (2026-11) - all requests, including invalid requests, cost at least one quota unit ↩

  5. Quota and Compliance Audits - YouTube Data API (2026-11) - audit required for quota beyond the default, Audit and Quota Extension Form, extensions within 12 months, appeals ↩ ↩2

  6. YouTube API Services - Audit and Quota Extension Form (2026-11) - information, evidence and justification the form requires, one form per API client, significant independent value requirement ↩ ↩2

Frequently Asked Questions

Direct answers extracted from this article.

The quotaExceeded (403) error means your Google Cloud project has used its daily YouTube Data API allowance. Uploads have their own bucket of 100 videos.insert calls a day by default, separate from the 10,000 units shared by other endpoints, so either one can run out first. Uploading through PublishQ avoids it, because you don't need a Google project of your own.
Google resets YouTube Data API daily quotas at midnight Pacific Time. Requests made after the reset draw from a fresh allowance.
Google's default allocation is 100 videos.insert calls per day per project, each costing 1 unit in the Video Uploads bucket. Thumbnails, edits and other writes come out of the separate 10,000-unit pool.
Submit the YouTube API Services Audit and Quota Extension Form. Google audits your project against its developer policies and asks for your organization details, privacy policy, demo access or a screencast, your Cloud project numbers, and a justification for the daily quota you want.
Yes. Connect your channel to PublishQ and upload through its API, CLI or MCP server. You never create a Google Cloud project or request quota, and the uploads don't count against a project of yours.
Start for Free

No credit card required • Set up in under 3 minutes