I am using the YouTube Data API to gather channel and video data. I have my app deployed to Streamlit but any request that requires oauth instead of a api key gives me the error below. I can run the oauth required requests all day in a local Streamlit server. The function to authenticate that works locally is below along with the error.
Traceback (most recent call last):
File "/home/adminuser/venv/lib/python3.9/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 535, in _run_script
exec(code, module.__dict__)
File "/mount/src/concord/app_scripts/app.py", line 67, in <module>
create_playlists_from_data()
File "/mount/src/concord/app_scripts/app_create_playlist_add_videos_from_existing_playlist_data.py", line 161, in create_playlists_from_data
youtube = authenticate_youtube_api()
File "/mount/src/concord/app_scripts/app_create_playlist_add_videos_from_existing_playlist_data.py", line 43, in authenticate_youtube_api
credentials = flow.run_local_server(port=9000)
File "/home/adminuser/venv/lib/python3.9/site-packages/google_auth_oauthlib/flow.py", line 444, in run_local_server
webbrowser.get(browser).open(auth_url, new=1, autoraise=True)
File "/usr/local/lib/python3.9/webbrowser.py", line 65, in get
raise Error("could not locate runnable browser")
I have managed to find a flow that does allow me to use a link to perform the oauth. But I never go back to where I was and it never finishes processing my original API request. Plus I get a 403 error saying the YouTube Data API is not enabled in my project. The project number given is not the same as my actual project number. My client secrets file is up to date.
Here is one of the scripts for an API request
import streamlit as st
import googleapiclient.discovery
import pandas as pd
from google.oauth2 import service_account
from google_auth_oauthlib.flow import Flow
from extract_channel_info import extract_info
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()
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.