I’m using the Python client library (google-api-python-client) to call captions.update, but I keep getting a 403 forbidden even though I’ve granted all the obvious scopes. I’d appreciate any insight into what I’m missing. Environment Language: Python 3.10 Library: google-api-python-client v2.x OAuth scopes requested in my code: SCOPES = [ 'https://www.googleapis.com/auth/youtube.upload', 'https://www.googleapis.com/auth/youtube', 'https://www.googleapis.com/auth/youtube.force-ssl', 'https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/drive' ] What I’m doing Load saved credentials from token.pickle, refresh if expired. Build YouTube service: from google.oauth2.credentials import Credentials from googleapiclient.discovery import build creds = Credentials.from_authorized_user_file('token.pickle', SCOPES) youtube = build('youtube', 'v3', credentials=creds) Call captions.update: request = youtube.captions().update( part='snippet', body={ 'id': '<CAPTION_TRACK_ID>', 'snippet': { 'language': 'en', 'name': 'English captions', 'isDraft': False } }, media_body=MediaFileUpload('captions_en.vtt', mimetype='text/vtt') ) response = request.execute() print(response) Error message { "error": { "code": 403, "message": "The permissions associated with the request are not sufficient to update the caption track. The request might not be properly authorized.", "errors": [ { "domain": "youtube.caption", "reason": "forbidden", "message": "The permissions associated with the request are not sufficient to update the caption track. The request might not be properly authorized.", "location": "id", "locationType": "parameter" } ] } } Despite all that, I still get the same 403 error. Has anyone encountered this? Is there another permission or parameter I need to include, especially for non-brand channels? Any help would be greatly appreciated! Verified via the tokeninfo endpoint that my access token includes youtube.force-ssl. Deleted token.pickle and re-ran OAuth flow to force new token with updated scopes. Called youtube.videos().list(mine=True) to confirm the video’s channelId matches my channel. Tried uploading a brand-new caption with captions.insert instead of updating the existing track. Ensured the video has no auto-generated caption track (since those cannot be updated). Continue reading...