1

I'm attempting to use Youtube's Reporting API to access my company's Youtube data and analyze it. However, when I run an example script that Google has supplied, I receive the follow error:

HttpError: <HttpError 403 when requesting https://youtubereporting.googleapis.com/v1/media/%20?alt=json returned "The caller does not have permission">

I've created an Oauth 2.0 client ID, downloaded the client secrets file, and pointed the script to that. I am also being redirected to Google's authorization page, where I log in to the Youtube account that I'm trying get data from and authorize the script. For reference, the scope I'm using is:

https://www.googleapis.com/auth/yt-analytics-monetary.readonly

This is my first time trying to use Google's API so I'm sure I'm missing something, but I can't seem to figure it out. If anyone could offer some guidance I'd really appreciate it.

Edit: I've included the code that I'm using from Google's sample script below.

import urllib
import json
import os
from io import FileIO

import google.oauth2.credentials
import google_auth_oauthlib.flow
from oauth2client import client
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.http import MediaIoBaseDownload

def get_service():
    flow = InstalledAppFlow.from_client_secrets_file(client_secrets_file=client_secrets, scopes=scope)
    credentials = flow.run_console()
    return build(api_service_name, api_version, credentials = credentials)

def execute_api_request(client_library_function, **kwargs):
    response = client_library_function(**kwargs).execute()

    print(response)

scope = ['https://www.googleapis.com/auth/yt-analytics-monetary.readonly']
api_service_name = 'youtubereporting'
api_version = 'v1'
client_secrets = 'client_secret_397754690264-ba1rtbpi731qkveqb11361q4ggui2bmd.apps.googleusercontent.com.json'

youtube_analytics = get_service()
youtube_analytics.jobs().create(body={'reportTypeId':'channel_combined_a2', 'name':'test_job'}).execute()

# this lists all the reports that are generated after you've created a job
# so it might take a while before you're able to get list a report
youtube_analytics.jobs().reports().list(jobId = job_id).execute()

# this uses a reportId from one of the reports that are listed above
report_url = youtube_analytics.jobs().reports().get(jobId = job_id, reportId = 'REPORTIDGOESHERE').execute()['downloadUrl']

request = youtube_analytics.media().download(resourceName = " ")
request.uri = report_url

fh = FileIO('yt_test.txt', mode='wb')
downloader = MediaIoBaseDownload(fh, request, chunksize=-1)

done = False
while done is False:
    status, done = downloader.next_chunk()
    if status:
        print('Download %d%%.' % int(status.progress() * 100))
print('Download Complete!')

Edit #2: Just wanted to update this with a solution that I found for anyone that might stumble upon it.

The problem was that I wasn't setting the request's uri with a report url that's created when you create a job that in turn generates a report. I was under the assumption that this was its own report, but actually this is just the method in which you download said reports. So, I went ahead and created a job which generated a report. Then, I grabbed the "downloadUrl" from the reports metadata, set the request's uri as the url, and ran the downloader as usual. I've updated the code above to reflect this.

Alec
  • 11
  • 5
  • If you're running google's sample script and it's failing, it sounds like a question for google support, not stackoverflow. We can;t help you unless you provide the code you're running. – G. Anderson Oct 25 '18 at 17:39
  • I didn't think it was necessary to provide my code since I believe this is an issue with how I'm authorizing the script rather than a coding issue, but I've edited my post to include the code regardless. – Alec Oct 25 '18 at 17:55
  • Is there a reason you can't get an answer from google about why their sample code doesn't work? [Here](https://stackoverflow.com/questions/51291769/appengine-server-to-server-authentication-and-google-domain-wide-authority) is another SO question regarding the same error, maybe that will help as well – G. Anderson Oct 25 '18 at 18:31
  • Thanks, I'll take a look and see if it helps. I didn't ask Google because I don't think it's a problem with their sample code, it's a problem with the way I'm authorizing my application. – Alec Oct 25 '18 at 18:59

1 Answers1

0

Adding this so I can mark it as answered. My solution is below:

The problem was that I wasn't setting the request's uri with a report url that's created when you create a job that in turn generates a report. I was under the assumption that this was its own report, but actually this is just the method in which you download said reports. So, I went ahead and created a job which generated a report. Then, I grabbed the "downloadUrl" from the reports metadata, set the request's uri as the url, and ran the downloader as usual. I've updated the code above to reflect this.

Alec
  • 11
  • 5