Google Photos API认证权限不足问题求助及官方支持咨询
调用Google Photos API遇403权限错误及官方客服联系方法
问题描述
调用Google Photos API获取媒体资源时触发403权限错误,具体日志如下:
Fetching first 10 media items... Traceback (most recent call last): File "gphotos_connectfetchtest.py", line 43, in <module> list_media_items() File "gphotos_connectfetchtest.py", line 31, in list_media_items results = service.mediaItems().list(pageSize=10).execute() File "D:\Program Files\Python\Python38\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper return wrapped(*args, **kwargs) File "D:\Program Files\Python\Python38\lib\site-packages\googleapiclient\http.py", line 938, in execute raise HttpError(resp, content, uri=self.uri) googleapiclient.errors.HttpError: <HttpError 403 when requesting https://photoslibrary.googleapis.com/v1/mediaItems?pageSize=10&alt=json returned "Request had insufficient authentication scopes.". Details: "Request had insufficient authentication scopes.">
已多次尝试常规排查步骤(如确认权限范围、重新生成Token等)但未解决,怀疑账号存在特殊限制设置,需联系谷歌官方客服获取针对性帮助。
补充信息
使用的代码
import os import json import csv from datetime import datetime from google.auth.transport.requests import Request from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow from googleapiclient.discovery import build SCOPES = ['https://www.googleapis.com/auth/photoslibrary.readonly'] CLIENT_SECRET_FILE = 'credentials.json' TOKEN_FILE = 'token.json' def authenticate(): creds = None # Load token if it exists if os.path.exists(TOKEN_FILE): creds = Credentials.from_authorized_user_file(TOKEN_FILE, SCOPES) # If no valid credentials available, let user log in. if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES) creds = flow.run_local_server(port=8080) # Save credentials for next run with open(TOKEN_FILE, 'w') as token: token.write(creds.to_json()) return creds def estimate_size(media_type, megapixels): try: if media_type == "Photo" and megapixels: return round(megapixels * 0.3, 2) # MB estimate else: return "" except: return "" def get_photos(): creds = authenticate() service = build('photoslibrary', 'v1', credentials=creds, static_discovery=False) media_items = [] next_page_token = None print("Fetching media items...") while True: results = service.mediaItems().list(pageSize=100, pageToken=next_page_token).execute() items = results.get('mediaItems', []) media_items.extend(items) next_page_token = results.get('nextPageToken') if not next_page_token: break timestamp = datetime.now().strftime('%d.%m.%Y_%H%M') output_file = f'google_photos_{timestamp}.csv' with open(output_file, 'w', newline='', encoding='utf-8') as csvfile: fieldnames = ['Name', 'Date Taken', 'Type', 'Extension', 'Resolution', 'Megapixels', 'Est. File Size (MB)', 'Link', 'mediaItemId'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames, delimiter='\t') writer.writeheader() for item in media_items: metadata = item.get('mediaMetadata', {}) mime_type = item.get('mimeType', '') media_type = 'Video' if mime_type.startswith('video') else 'Photo' width = metadata.get('width') height = metadata.get('height') resolution = f"{width} x {height}" if width and height else '' megapixels = round((int(width) * int(height)) / 1_000_000, 2) if width and height else '' estimated_size = estimate_size(media_type, megapixels) filename = item.get('filename', '') extension = os.path.splitext(filename)[1].lower().lstrip('.') writer.writerow({ 'Name': filename, 'Date Taken': metadata.get('creationTime', ''), 'Type': media_type, 'Extension': extension, 'Resolution': resolution, 'Megapixels': f"{megapixels} MP" if megapixels else '', 'File Size': get_file_size(base_url), 'Device Model': device_model, 'Link': base_url + '=d', 'mediaItemId': item.get('id'), }) print(f"Saved {len(media_items)} media items to '{output_file}'.") if __name__ == '__main__': get_photos()
生成的Token信息
{"token": "tokenTOKENtokenToKeNTOKENtokentokenTOKENtokenToKeNTOKENtokentokenTOKENtokenToKeNTOKENtokentokenTOKENtokenToKeNTOKENtokentokenTOKENtokenToKeNTOKEN_tokentokenTOKEN_tokenToKeNTOKENtokentokenTOKENtokenToKeNTOKENtokentokenTOKENtoken", "refresh_token": "1//0refresh_tokenrefresh_tokenAkSNwF-refresh_token-refresh_tokenrefresh_tokenrefresh_tokenrefresh_token", "token_uri": "https://oauth2.googleapis.com/token", "client_id": "client_id-CLIENT_IDclient.idClIeNt_Id.apps.googleusercontent.com", "client_secret": "SECRET-SECRETsecretSECRET-SeCrEtsecret-SECRET", "scopes": ["https://www.googleapis.com/auth/photoslibrary.readonly"], "universe_domain": "googleapis.com", "account": "", "expiry": "3485-06-25T00:39:18.310504Z"}
排查与客服联系方法
最后排查步骤(若未尝试)
- 删除旧Token重新授权:删除本地
token.json文件,重新运行代码完成授权流程,确保新Token的权限范围与代码中定义的一致。 - 确认Cloud项目API启用状态:登录Google Cloud控制台,进入对应项目,搜索并确认「Photos Library API」已启用。
- 检查账号权限限制:若使用Google Workspace账号,联系管理员确认是否存在API调用的全局限制。
联系谷歌官方客服的途径
- Google Workspace账号:直接联系企业管理员,管理员可通过Workspace管理控制台提交专属支持工单,获取官方技术支持。
- 个人账号:
- 登录Google Cloud控制台,进入对应项目,点击右上角问号图标,选择「提交支持请求」。若未开通付费支持计划,可先选择社区支持,或申请临时付费支持以获取官方工单通道。
- 在提交工单时,需提供完整的错误日志、代码片段、Token权限截图及账号相关信息,便于官方定位问题。
- 也可通过Google账号帮助中心,搜索「Google Photos API 权限不足」,找到对应分类的反馈入口提交问题。
内容的提问来源于stack exchange,提问作者Bogdan Nicolescu
相关产品推荐
相关产品推荐

