Google REST APIs - YouTube

Hi all,

I’ve hit a brick wall trying to access the YouTube API from Anvil… I’ve read https://anvil.works/docs/integrations/google/google-rest-apis and followed https://anvil.works/docs/integrations/google/linking-google-and-anvil with complete success for OAuth login using example scopes for Google Drive and Gmail, but get this error with the youtube.readonly scope:

Is there something special about the YouTube API? Is it blocked in server to server calls somehow - I ask that because I can successfully access the youtube.readonly scope using an alternate API Project which I set up as an “Installed App” API using just OAuth (no need for Client ID or Client secret) and an unverified Consent Screen.

Sample of my Anvil code:

        scopes = [#"https://www.googleapis.com/auth/gmail.readonly",]
                  "https://www.googleapis.com//auth/youtube.readonly"]
        self.gmail = anvil.google.drive.login()
        self.token = anvil.google.auth.get_user_access_token()
        print(self.gmail)
        folder = anvil.google.drive.get_user_files()
        self.token = anvil.google.auth.get_user_access_token()
        for f in folder.list_files():
          print(f)
        self.gmail = anvil.google.auth.login(scopes) # fails here
        self.token = anvil.google.auth.get_user_access_token()
        print(self.token)

On the desktop version of my app I’ve been successfully using the following, again with an unverified Consent Screen, so I’m pretty sure that’s not the problem:

import googleapiclient.discovery
import google_auth_oauthlib.flow
import google.auth.transport.requests

scopes = ["https://www.googleapis.com/auth/youtube.readonly"]
youtube_api = googleapiclient.discovery.build("youtube", "v3", credentials=get_google_api_credentials(scopes))
results = youtube_api.channels().list(mine=True, part='contentDetails').execute()

where get_google_api_credentials() is almost a direct copy of a sample from the googleapiclient docs:

def get_google_api_credentials(scopes):
    """ Returns credentials for given Google API scope(s) """
    credentials = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if Path('token.pickle').is_file():
        with open('token.pickle', 'rb') as token:
            credentials = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not credentials or not credentials.valid:
        if credentials and credentials.expired and credentials.refresh_token:
            credentials.refresh(google.auth.transport.requests.Request())
        else:
            flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file('credentials-windows.json', scopes)
            credentials = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(credentials, token)
    return credentials

Hello @AWSOM,

There’s nothing special about the YouTube API, it looks like you have an extra ‘/’ before the auth in your URL.

Thanks,
Ryan

1 Like

You can also have a look here. The example is for the drive API but all the common bits apply.

1 Like

How embarassing, but thanks so much for spotting that and putting me out of my misery @ryan.

Not the first time and not the last time a silly typo rather than Anvil is the root cause of all my stress!

No problem, we have all been there! :smile: