Can’t get my YouTube API app to process requests on Streamlit server

Here is my code that I am trying to run without errors. I was having troubles with the Oauth in Streamlit since it’s a headless server, but got this to at least give me the link to go to in order to perform the Oauth. Once access is granted though the app does not continue to process the info already input and I get a 403 Error. The project number in the error also does not match my cloud-console project for the API. But in my project I do have the YouTube Data api enabled.

googleapiclient.errors.HttpError: <HttpError 403 when requesting https://youtube.googleapis.com/youtube/v3/channels?part=brandingSettings%2CcontentDetails%2CcontentOwnerDetails%2Cid%2Clocalizations%2Csnippet%2Cstatistics%2Cstatus%2CtopicDetails&id=UCz4LzmevHDOY4dFiHw9I-kQ&alt=json returned “YouTube Data API v3 has not been used in project 868231854759 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/youtube.googleapis.com/overview?project=868231854759 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.”. Details: “[{‘message’: ‘YouTube Data API v3 has not been used in project XXXXXXXXXXXXXX before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/youtube.googleapis.com/overview?project=868231854759 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.’, ‘domain’: ‘usageLimits’, ‘reason’: ‘accessNotConfigured’, ‘extendedHelp’: ‘https://console.developers.google.com’}]”>

import streamlit as st
import googleapiclient.discovery
import pandas as pd
from google.oauth2 import service_account
from google_auth_oauthlib.flow import Flow

# My Modules
from extract_channel_info import extract_info

# Define the scopes you need to access
SCOPES = ['https://www.googleapis.com/auth/youtube.readonly']

def authorize():
    # Create a flow instance using the client ID and client secret obtained from the Google Developers Console
    flow = Flow.from_client_secrets_file(
        'client_secrets.json',  # Replace this with the path to your client secret JSON file
        scopes=SCOPES,
        redirect_uri='https://concordmusic.streamlit.app'
    )

    # Construct the authorization URL
    auth_url, _ = flow.authorization_url(prompt="consent")

    # Print the authorization URL and prompt the user to visit it
    st.write("Please visit this URL to authorize access:", auth_url)
    
    # Ask the user to enter the authorization code obtained after authorizing access
    authorization_code = st.text_input("Enter the authorization code: ")
    # Check if the authorization code has been provided
    if authorization_code:
        # Fetch the access token using the authorization code
        flow.fetch_token(code=authorization_code)
        # Get the credentials
        credentials = flow.credentials
        return credentials
    else:
        st.write("Authorization code is required.")

def get_authenticated_service():
    # Authorize and get the credentials
    credentials = authorize()

    # Build the YouTube Data API service
    service = googleapiclient.discovery.build('youtube', 'v3', credentials=credentials)

    return service

def get_single_channel_info():
    channel_id = st.text_input("What is the Channel ID?")
    filename = st.text_input("Output File Name:")

    if st.button("Perform Call"):
        # Check if either input field is blank
        if not channel_id or not filename:
            st.warning("Both Channel ID and Output File Name are required.")
            return  # Stop further execution

        st.write("Running your request now...")

        # Authenticate and get the service
        service = get_authenticated_service()

        channel_info_list = []

        request = service.channels().list(
            part="brandingSettings,contentDetails,contentOwnerDetails,id,localizations,snippet,statistics,status,topicDetails",
            id=channel_id
        )
        response = request.execute()

        if "items" in response:
            for item in response["items"]:
                channel_info = extract_info(item)
                channel_info_list.append(channel_info)

        # Create a DataFrame from the video information
        df = pd.DataFrame(channel_info_list)

        if filename:
            # Ensure file name ends with ".xlsx"
            if not filename.endswith(".xlsx"):
                filename += ".xlsx"
        # Save the DataFrame to an Excel file
        df.to_excel(filename, index=False, engine="openpyxl")
        st.write("Results have been saved to", filename)
        # Provide a download button for the output file
        with open(filename, 'rb') as file:
            file_content = file.read()
        st.download_button(label="Download Excel File", data=file_content, key='download_excel', file_name=filename)

        print(f"Channel info saved to {filename}")

if __name__ == "__main__":
    get_single_channel_info()

Leave a Comment