You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python调用YouTube Data API时遇redirect_uri_mismatch错误求助

解决YouTube Data API OAuth2认证的redirect_uri_mismatch错误

问题场景

使用Python结合Google OAuth2调用YouTube Data API上传视频时,在用户认证环节触发redirect_uri_mismatch错误,已核对Google Cloud Console中的重定向URI、重新生成过客户端密钥,但问题仍存在。相关代码如下:

import pickle
from google.oauth2.credentials import Credentials
import google_auth_oauthlib
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from googleapiclient.http import MediaFileUpload
import os

# credentials
CLIENT_SECRETS_FILE = "client_secret.json"
YOUTUBE_UPLOAD_SCOPE = "https://www.googleapis.com/auth2/youtube.upload"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"

def get_authenticated_service():
    credentials = None
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            credentials = Credentials.from_authorized_user_info(info=pickle.load(token))
    if not credentials or not credentials.valid:
        flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, [YOUTUBE_UPLOAD_SCOPE])
        credentials = flow.run_local_server(port=8080)
        with open('token.pickle', 'wb') as token:
            pickle.dump(credentials.to_authorized_user_info(), token)
    return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, credentials=credentials)

def upload_to_youtube(video_path, title, description):
    try:
        youtube = get_authenticated_service()

        # Create the MediaFileUpload object for the video
        media = MediaFileUpload(video_path, chunksize=-1, resumable=True)

        # Create the video on YouTube
        video = youtube.videos().insert(
            part="snippet,status",
            body={
                "snippet": {
                    "title": title,
                    "description": description,
                },
                "status": {
                    "privacyStatus": "private",
                },
            },
            media_body=media,
        ).execute()

        print(f'Uploaded video: {video["id"]}')

    except HttpError as e:
        print(f'An error occurred: {e}')
        return False
    return True

if __name__ == '__main__':
    video_path = "test.mp4"
    title = "My video title"
    description = "My video description"
    upload_to_youtube(video_path, title, description)

错误成因

  1. Scope拼写错误:代码中YOUTUBE_UPLOAD_SCOPE的地址多了一个2,正确的Scope应为https://www.googleapis.com/auth/youtube.upload,错误的Scope会导致OAuth流程异常,触发误导性的URI不匹配提示。
  2. 旧认证缓存干扰:本地保存的token.pickle文件存储了之前错误的认证信息,即使修改配置,程序仍会优先读取旧缓存,导致认证流程异常。
  3. 客户端ID类型不匹配:若在Google Cloud Console创建的是Web应用类型的客户端ID,而代码使用的是适用于本地/桌面应用的InstalledAppFlow,两者的重定向URI规则不兼容,会引发匹配错误。

修复步骤

  • 修正Scope地址:将代码中的YOUTUBE_UPLOAD_SCOPE替换为正确值:
    YOUTUBE_UPLOAD_SCOPE = "https://www.googleapis.com/auth/youtube.upload"
    
  • 清除旧缓存:删除本地的token.pickle文件,让程序重新执行完整的OAuth认证流程。
  • 确认客户端ID类型:在Google Cloud Console的「API和服务」→「凭据」页面,创建或切换为桌面应用类型的客户端ID,下载新的client_secret.json替换本地文件。
  • 验证重定向URI:在客户端ID的配置页面,确保已添加http://localhost:8080/(注意末尾的斜杠,需与代码中flow.run_local_server(port=8080)的默认回调URI严格匹配)。

修正后的完整代码

import pickle
from google.oauth2.credentials import Credentials
import google_auth_oauthlib
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from googleapiclient.http import MediaFileUpload
import os

# credentials
CLIENT_SECRETS_FILE = "client_secret.json"
YOUTUBE_UPLOAD_SCOPE = "https://www.googleapis.com/auth/youtube.upload"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"

def get_authenticated_service():
    credentials = None
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            credentials = Credentials.from_authorized_user_info(info=pickle.load(token))
    if not credentials or not credentials.valid:
        flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, [YOUTUBE_UPLOAD_SCOPE])
        credentials = flow.run_local_server(port=8080)
        with open('token.pickle', 'wb') as token:
            pickle.dump(credentials.to_authorized_user_info(), token)
    return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, credentials=credentials)

def upload_to_youtube(video_path, title, description):
    try:
        youtube = get_authenticated_service()

        # Create the MediaFileUpload object for the video
        media = MediaFileUpload(video_path, chunksize=-1, resumable=True)

        # Create the video on YouTube
        video = youtube.videos().insert(
            part="snippet,status",
            body={
                "snippet": {
                    "title": title,
                    "description": description,
                },
                "status": {
                    "privacyStatus": "private",
                },
            },
            media_body=media,
        ).execute()

        print(f'Uploaded video: {video["id"]}')

    except HttpError as e:
        print(f'An error occurred: {e}')
        return False
    return True

if __name__ == '__main__':
    video_path = "test.mp4"
    title = "My video title"
    description = "My video description"
    upload_to_youtube(video_path, title, description)

内容的提问来源于stack exchange,提问作者Mohammed Chaaraoui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 07:52:51