0

I'm developing a backend application using a Google Service Account to upload videos to YouTube via the YouTube Data API v3.

  1. The service account is granted OAuth scopes:

    https://www.googleapis.com/auth/adwords
    https://www.googleapis.com/auth/youtube

  2. I'm able to access the Google Ads API successfully using this service account.

  3. However, when trying to upload a video using the following API:

    POST https://www.googleapis.com/upload/youtube/v3/videos?part=snippet,status&uploadType=resumable
    

I get a 401 Unauthorized error with this response:

  "error": {
    "code": 401,
    "message": "Unauthorized",
    "errors": [
      {
        "message": "Unauthorized",
        "domain": "youtube.header",
        "reason": "youtubeSignupRequired",
        "location": "Authorization",
        "locationType": "header"
      }
    ]
  }
}

My question: How can I correctly authorize a Google Service Account to access the YouTube Data API and upload videos?

It seems like YouTube channel ownership is required, but service accounts don't have a YouTube channel by default. Is there a recommended workaround (such as impersonation via domain-wide delegation or OAuth flow with a real user account)? Any guidance from Google engineers or those who’ve dealt with this before would be appreciated.

1 Answer 1

0

You're absolutely right — Google Service Accounts cannot directly upload videos to YouTube via the YouTube Data API because:

YouTube requires access to a real user’s channel, and

Service accounts do not have YouTube channels associated with them.

❗️Why Service Accounts Don’t Work for YouTube Uploads

Service accounts are designed for server-to-server API access. But YouTube APIs require a YouTube channel, and only Google user accounts can own channels. There's no domain-wide delegation workaround because YouTube is not part of Google Workspace-supported services for that feature.

✅ Recommended Workaround (by YouTube API team & community)

Use a regular Google account (with a YouTube channel) and perform an OAuth 2.0 flow once manually, then store and reuse the refresh token on your backend.

🧰 Implementation Steps

1. Create OAuth 2.0 Client in google Cloud Console

Go to: https://console.cloud.google.com/apis/credentials

Create an OAuth 2.0 Client ID

Type: Desktop App or Web App

Enable the YouTube Data API v3

2. Request OAuth Consent

Scopes required:
https://www.googleapis.com/auth/youtube.upload

https://www.googleapis.com/auth/youtube

Run a manual OAuth flow (use Google’s OAuth Playground or your own app)

Get the refresh token and save it securely (DB, encrypted file)

3. Use the Refresh Token on Server

Use a library like google-auth-library (Node.js), google-auth (Python), or equivalent to:

Load client ID/secret and refresh token

Exchange for access token

Call the YouTube Data API to upload video

//python code

from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build

creds = Credentials(
    None,
    refresh_token="YOUR_REFRESH_TOKEN",
    token_uri="https://oauth2.googleapis.com/token",
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
    scopes=["https://www.googleapis.com/auth/youtube.upload"]
)
youtube = build("youtube", "v3", credentials=creds)

request = youtube.videos().insert(
    part="snippet,status",
    body={
        "snippet": {"title": "My Video", "description": "Test"},
        "status": {"privacyStatus": "private"}
    },
    media_body="video.mp4"
)
response = request.execute()
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build

creds = Credentials(
    None,
    refresh_token="YOUR_REFRESH_TOKEN",
    token_uri="https://oauth2.googleapis.com/token",
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
    scopes=["https://www.googleapis.com/auth/youtube.upload"]
)
youtube = build("youtube", "v3", credentials=creds)

request = youtube.videos().insert(
    part="snippet,status",
    body={
        "snippet": {"title": "My Video", "description": "Test"},
        "status": {"privacyStatus": "private"}
    },
    media_body="video.mp4"
)
response = request.execute()

Sign up to request clarification or add additional context in comments.

1 Comment

1.Using a service account to impersonate a real user account that has a YouTube channel allows uploading videos to YouTube. 2. Based on that, if it were somehow possible to enable a YouTube channel for the service account itself, would that allow the service account to upload videos directly via the API, without impersonating a user?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.