使用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)
错误成因
- Scope拼写错误:代码中
YOUTUBE_UPLOAD_SCOPE的地址多了一个2,正确的Scope应为https://www.googleapis.com/auth/youtube.upload,错误的Scope会导致OAuth流程异常,触发误导性的URI不匹配提示。 - 旧认证缓存干扰:本地保存的
token.pickle文件存储了之前错误的认证信息,即使修改配置,程序仍会优先读取旧缓存,导致认证流程异常。 - 客户端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
相关产品推荐
相关产品推荐

