Using the YouTube Data API v3 with API Keys and OAuth 2.0
The final result of this post is a functional Python Flask web server application that queries YouTube information using the YouTube Data API v3 (YouTube API
) and OAuth 2.0 authorisation. We review the official documentation and discuss how to set up a Google Cloud Project that wraps the YouTube API. Next, we describe how to obtain credentials, including both the API key and OAuth 2.0 tokens, for the project. Finally, we present a functional Python Flask web server application. This example application also includes a function to manage the refresh_token
, which is available only once during the first OAuth 2.0 authorization request.
Using the YouTube Data API v3 with API Keys and OAuth 2.0 |
A few years ago, I experimented with the YouTube API
using
NodeJs.
Unfortunately, I didn’t document that learning process, nor did I complete
the project. Now, I’m revisiting this topic, but this time, I’m using Python
and documenting my progress in this post.
My goal is straightforward: for my own YouTube channel, I want to retrieve
specific information about each video, including the ID
, title
,
description
, search tags
, and file name
.
Interestingly, while most of this information can be obtained using an API key, retrieving the video file name requires OAuth 2.0 authorisation. As a result, we’ll need both an API key and OAuth 2.0 credentials.
💥 Please note, my Gmail address for my developer account and YouTube channel is the same.
The primary objective of this post is to document the key points for getting
started with the YouTube API
, rather than creating a complete
working application. In terms of coding, we will modify an
existing official YouTube Data API v3 example.
Table of contents
- ❶ Review the Relevant Official YouTube Data API v3 Documentation
- ❷ Create a New Google Cloud Project
- ❸ The Billing Account
- ❹ The Google API Playground
-
❺ The Complete Example Application
-
⓵ Modifications to the Official
quickstart_web.py
Example - ⓶ Listing of the Complete Code and a Detailed Code Walkthrough
- ⓷ Running the Example Application and Checking the Output
- ⓸ Executing the Example Application on a Different Machine Using the Granted Credentials
- ⓹ Attempt to Retrieve the File Name of a Video from a Different Channel
-
⓵ Modifications to the Official
- ❻ Some Helpful Links for Managing Google Cloud API Projects
- ❼ Existing Posts on the Google Gmail API
- ❽ Concluding Remarks
❶ Google APIs come with an extensive set of documentation and examples, which I find more than sufficient. However, I did get a bit lost in it. In this post, I’m listing the resources I’ve found most relevant for my needs. I encourage you to explore them as well. Keep in mind that this list is not exhaustive. While you can jump directly to the create a new project section, reading through these resources will make the later sections much easier to follow. Skipping the reading might not be the best approach.
- Obtaining authorization credentials
- YouTube Data API Overview
- Using OAuth 2.0 to Access Google APIs
- Using OAuth 2.0 for Web Server Applications.
⓵ Note on OAuth 2.0 Authorized Redirect URIs:
In the section Create authorization credentials, specifically point 4, please pay attention to the following statement:
For testing, you can specify URIs that refer to the local machine, such as
http://localhost:8080
. With that in mind, please note that all of the examples in this document usehttp://localhost:8080
as the redirect URI.We recommend that you design your app’s auth endpoints so that your application does not expose authorization codes to other resources on the page.
Similarly, in the section
Step 1: Set authorization parameters,
the explanation for the required parameter
redirect_uri
reads:
Determines where the API server redirects the user after the user completes the authorization flow. The value must exactly match one of the authorized redirect URIs for the OAuth 2.0 client, which you configured in your client’s API Console Credentials page. If this value doesn’t match an authorized redirect URI for the provided
client_id
you will get aredirect_uri_mismatch
error.Note that the
http
orhttps
scheme, case, and trailing slash (‘/’) must all match.
Please note that, in a later section,
we configure the value of redirect_uri
to
http://localhost:5000/oauth2callback
.
⓶ Note on OAuth 2.0 Refresh Token:
While reading, I did take note of essential points about the refresh token.
However, it didn’t fully register at the time. Initially, I got the code to
work. But when I returned to run it again 2 or 3 days later, I encountered a
RefreshError
exception. I’ve included this section after
troubleshooting the exception.
💥 Despite the extensive amount of documentation, it is not explicitly stated
that the refresh_token
is provided only once, during the initial
authorisation from users. This
Stack Overflow answer clarifies this point.
● Note the example immediately preceding the section Refreshing an access token (offline access):
authorization_url, state = flow.authorization_url(
# Enable offline access so that you can refresh an access token without
# re-prompting the user for permission. Recommended for web server apps.
access_type='offline',
# Enable incremental authorization. Recommended as a best practice.
include_granted_scopes='true')
In my understanding, this section reiterates and emphasizes that it is
more beneficial to set access_type
to offline
.
The reason is included in the comment in the above code block.
● This document, Implementing OAuth 2.0 Authorization, also reinforces the same point using different wording:
For example, a server-side web application exchanges the returned token for an access token and a refresh token. The access token lets the application authorize requests on the user’s behalf, and the refresh token lets the application retrieve a new access token when the original access token expires.
● And the last one I would like to quote is from the Python official example documentation:
Refresh and access tokens: When a user grants your application access, the OAuth 2.0 authorization server provides your application with refresh and access tokens. These tokens are only valid for the scope requested. Your application uses access tokens to authorize API calls. Access tokens expire, but refresh tokens do not. Your application can use a refresh token to acquire a new access token.
Warning: Keep refresh and access tokens private. If someone obtains your tokens, they could use them to access private user data.
🚀 To sum up, developers must save the refresh token in permanent storage and include it during subsequent authorisation requests. This ensures that a new access token can be generated if the current access token expires.
⓷ Note on OAuth 2.0 RefreshError
Exception:
As mentioned in the previous section,
I encountered the RefreshError
exception because the access token
had expired, and I had not included the refresh_token
in the
authorisation request. The text of the exception is:
google.auth.exceptions.RefreshError: The credentials do not contain the necessary fields need
to refresh the access token. You must specify refresh_token, token_uri, client_id, and client_secret.
Fortunately, this problem has been thoroughly discussed in the following GitHub issue: https://github.com/googleapis/google-auth-library-python/issues/659.
🚀 Summary of the Solution:
- Visit https://myaccount.google.com/u/0/permissions.
-
Select
youtube data api scraper
. -
Click on
Delete all connections you have with youtube data api scraper
. - This action revokes the previously granted authorisation.
- The next time we request authorisation, the Google Cloud API will guide us through the entire OAuth 2.0 user authorisation process again.
-
Ensure that we save the
refresh_token
to permanent storage this time.
❷ Create a Google Cloud Project using the Google Cloud Console. This project will house the YouTube Data API. Please follow the steps below.
- Sign into your Google account. Typically, signing into Gmail is sufficient.
-
Navigate to the Google Cloud Console:
https://console.cloud.google.com.
If this is your first time accessing the Cloud Console,
you’ll encounter a welcome pop-up window. Agree to the
Terms of Service
, then click theAGREE AND CONTINUE
button. -
On the Google Cloud page:
- Click on the project drop-down list in the top right-hand corner (RHS).
-
In the pop-up window, click the
NEW PROJECT
button on the RHS.
Please refer to the screenshot illustration below:
-
On the
New Project
page, enter an appropriate project name, such asYouTube 02
. -
Click on the
CREATE
button. - After the project is created, select it. You will be taken to a screen as shown below:
-
Click on the
API Explore and enable APIs
link. -
On the new screen, click on the
+ ENABLE APIS AND SERVICES
button (or link) in the top band, toward the left-hand side (LHS). -
In the next screen, titled
Welcome to the API Library
, type “YouTube Data API” into the search box and hit the Enter key. - You will be taken to the result page, which looks similar to the screenshot below:
-
Select the first entry:
YouTube Data API v3
. -
On the next page, click on the
ENABLE
button. - This will take you to a new page that looks like the screenshot below:
I am not familiar with the CREATE CREDENTIALS
button
in the above screen. The next step is to create credentials, both the
API key
and OAuth 2.0
. Click on the
Credentials
link on the left-hand side (LHS). We will be
taken to the following new screen:
⓵ Click on API key
to create a new API key.
⓶ Click on OAuth consent screen
to start creating a new OAuth 2.0 credential:
-
For
User Type
, we can only selectExternal
. Then click onCREATE
. -
On the next screen:
-
Enter something meaningful for
App name*
. I useyoutube data api scraper
. -
For
User support email *
, I use the email I currently sign in with, which is also the email associated with my YouTube channel. -
Under Developer contact information , in the
Email addresses *
section, I also use the same email as the one inUser support email *
. -
Click the
SAVE AND CONTINUE
button.
-
-
On the next screen, click on the
ADD OR REMOVE SCOPES
button. Then select the../auth/youtube.readonly
scope, as illustrated in the screenshot below:Click the
UPDATE
button. The newly selected scope is now added under the Your sensitive scopes section of the screen.Click the
SAVE AND CONTINUE
button. -
On the new screen, under the Test users section, click on
+ ADD USERS
. Use the same email forUser support email *
.Click the
SAVE AND CONTINUE
button. -
You will be taken to the OAuth consent screen summary page. We have completed the OAuth consent.
⓷ Create the OAuth 2.0 Client ID and Secret:
-
Click on the
Credentials
link on the LHS. -
Then click
+ CREATE CREDENTIALS
and selectOAuth client ID
, as shown in the screenshot below:
On the new screen:
-
For
Application type *
, selectWeb application
. -
For
Name *
, enter something meaningful. I useYouTube 02 Test Client
. -
Under the section Authorized redirect URIs, click on the
+ ADD URI
button. Specifyhttp://localhost:5000/oauth2callback
. Please refer to the quoted documentation for an explanation of whyhttp://localhost:5000
is a valid choice. Later, in the code, we will see howhttp://localhost:5000/oauth2callback
is implemented. -
Click the
CREATE
button. After a few seconds, aOAuth client created
notification screen will appear, as illustrated in the screenshot below:Click on
DOWNLOAD JSON
to save the OAuth 2.0 credential file to disk. Our applications will need this client secrets file.
We have completed creating an OAuth 2.0 credential. We can now use the downloaded credential file in our applications to obtain authorisation for using the YouTube Data API.
🚀 Note: If you already have a project selected, you can directly access its credentials page using the following URL: https://console.cloud.google.com/apis/credentials. Here, you can make changes to existing credentials.
❸ The Billing Account:
Please note that you might be asked to set up a billing account. A few years ago, I set one up, but unfortunately, I didn’t document the process. I don’t recall the exact steps off the top of my head. However, I haven’t been charged anything yet, as my usage has always remained below the free quota.
❹ Google API Playground is a valuable tool that allows us to explore how any API works in terms of parameter requirements. This understanding will greatly assist us when coding later on. For our purposes, we will focus on three specific APIs. The way the playground operates should be consistent across other APIs as well.
In our code example, we will create three methods corresponding to these three APIs. These methods will use OAuth 2.0 authorisation to retrieve data, although an API key can also be used for some methods.
To begin, visit the YouTube Data API documentation. Click on the Search for content header, which will take you to the Search: list page https://developers.google.com/youtube/v3/docs/search/list. On this page, pay attention to the three links: video, channel, and playlist — these are the APIs we are interested in. Also, take note of the ★ Quota impact warning.
⓵ Retrieving a Channel’s Upload Playlist ID Using a Channel ID:
Click the channel link. On the new page, under the Methods header, click the list link. This will take you to the YouTube Data API Channels: https://developers.google.com/youtube/v3/docs/channels/list.
Please note the following general format:
- The middle pane contains the documentation for this API, including explanations for all input parameters and the HTTP request endpoint address.
- The RHS pane is where we can try out the API.
Let’s try with the following parameter values:
-
part
:contentDetails
-
id
:my own channel ID
-
Leave both
Google OAuth 2.0
andAPI key
checked.
Click the Execute
button, then follow the instructions.
You should receive a response similar to the one below:
{
"kind": "youtube#channelListResponse",
"etag": "76zI1v9YitYCtGvsZ6X_K11enRQ",
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 5
},
"items": [
{
"kind": "youtube#channel",
"etag": "lXsff8mgRvFZ4QLKCa2LX-6JYDc",
"id": "UCPB9BdRkJRd3aGm9qAY3CTw",
"contentDetails": {
"relatedPlaylists": {
"likes": "LL",
"uploads": "UUPB9BdRkJRd3aGm9qAY3CTw"
}
}
}
]
}
The equivalent HTTP request, using the API key set up when creating your Google Cloud Project, is as follows:
https://www.googleapis.com/youtube/v3/channels?
key=<API key>&
part=contentDetails&
id=<a YouTube channel ID>
⓶ Retrieving Videos from a Channel’s Playlist using the Playlist ID:
On the Search: list page, click the playlist link. Then, on the new page, click the playlistItems.list link:
We can try this API with the following parameter values:
-
part
:snippet
-
playlistId
: for example, thedefault upload playlist ID
-
maxResults
:1
to50
-
Either
Google OAuth 2.0
orAPI key
will suffice.
Click the Execute
button, then follow the instructions.
We should get a valid response. It is rather long, so we will not list it here.
And this is the HTTP request equivalent, using the API key which we have set up when creating our Google Cloud Project:
https://www.googleapis.com/youtube/v3/playlistItems?
key=<API key>&
part=snippet&
playlistId=<a YouTube playlist ID>
maxResults=2
⓷ Retrieving a Video’s File Name using a Video ID:
On the Search: list page, click the video link. Then, on the new page, under the Methods header, click the list link:
We can try it with the following parameter values:
-
part
:fileDetails
-
id
:my own video ID
-
Check only
Google OAuth 2.0
.
We should get a response similar to the below:
{
"kind": "youtube#videoListResponse",
"etag": "hKdZjPcW_VDYbyPRxoJ_WXoYj6A",
"items": [
{
"kind": "youtube#video",
"etag": "CMbJrlI-T_BK7YezgVi1Jpkb2-0",
"id": "hMG1JjBwVx4",
"fileDetails": {
"fileName": "20240319-con chó giữa chúng ta-1.movie.mp4"
}
}
],
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 1
}
}
It seems that this API requires OAuth 2.0, which requires an authorisation code. For this reason, I have not tried out the HTTP request. According to the above page, the endpoint is:
GET https://www.googleapis.com/youtube/v3/videos
❺ The Complete Example Application:
We will begin with the
quickstart_web.py
example from the official YouTube API Samples in Python.
⓵ We will make the following changes:
-
The scope is set to
https://www.googleapis.com/auth/youtube.readonly
to match the project scope. -
The
refresh_token
is written into a local JSON file after the first successful authorisation request. In this implementation, we will simply write the entire granted credentials into the local JSON file. - Every time the application needs credentials, it first checks if the credentials JSON file exists. If it does, the application will attempt to load and use these credentials rather than submitting a new authorisation request.
-
As mentioned previously, we implement
three methods corresponding to the three APIs we have studied. Accordingly,
the official example method
channels_list_by_username(client, **kwargs):
is replaced by three new methods:channels_get_upload_playlist_id(client, **kwargs):
,playlist_get_videos(client, **kwargs):
, andvideos_get_file_names(client, **kwargs):
.
⓶ Listing the complete example code: Below is the content of youtube_data_api.py
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
import os
import json
import flask
import google.oauth2.credentials
import google_auth_oauthlib.flow
import googleapiclient.discovery
# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains
# the OAuth 2.0 information for this application, including its client_id and
# client_secret.
CLIENT_SECRETS_FILE = "client_secret_youtube.json"
# Credentials obtained from Google Clould YouTube Data API v3.
CREDENTIALS_FILE = 'credentials_youtube.json'
# This OAuth 2.0 access scope allows for full read/write access to the
# authenticated user's account and requires requests to use an SSL connection.
SCOPES = ['https://www.googleapis.com/auth/youtube.readonly']
API_SERVICE_NAME = 'youtube'
API_VERSION = 'v3'
app = flask.Flask(__name__)
# Note: A secret key is included in the sample so that it works, but if you
# use this code in your application please replace this with a truly secret
# key. See http://flask.pocoo.org/docs/0.12/quickstart/#sessions.
app.secret_key = 'REPLACE ME - this value is here as a placeholder.'
@app.route('/')
def index():
# Attempt to load previous credentials stored on local JSON file...
if 'credentials' not in flask.session:
load_credentials()
# There is no credentials stored on local JSON file. Try to authorise.
if 'credentials' not in flask.session:
return flask.redirect('authorize')
# Load the credentials from the session.
credentials = google.oauth2.credentials.Credentials(
**flask.session['credentials'])
client = googleapiclient.discovery.build(
API_SERVICE_NAME, API_VERSION, credentials=credentials)
"""
return channels_get_upload_playlist_id(client,
part='contentDetails',
id='UCPB9BdRkJRd3aGm9qAY3CTw')
"""
"""
return playlist_get_videos(client,
part='snippet,contentDetails',
maxResults=2,
playlistId='UUPB9BdRkJRd3aGm9qAY3CTw')
"""
"""
# Note: hMG1JjBwVx4 is my own video. That is, the email address
# associated with the hMG1JjBwVx4's channel is also the email
# address I used to obtain the OAuth 2.0 credentials.
#
# ACTION ITEM for readers:
# You have to replace hMG1JjBwVx4 with your own.
#
return videos_get_file_names(client,
part='fileDetails',
id='hMG1JjBwVx4')
"""
return f'<h2>Please enable either channels_get_upload_playlist_id(...), \
playlist_get_videos(...), or videos_get_file_names(...) call \
to see a YouTube Data API v3 in action.</h2>'
@app.route('/authorize')
def authorize():
# Create a flow instance to manage the OAuth 2.0 Authorization Grant Flow
# steps.
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
CLIENT_SECRETS_FILE, scopes=SCOPES)
flow.redirect_uri = flask.url_for('oauth2callback', _external=True)
authorization_url, state = flow.authorization_url(
# This parameter enables offline access which gives your application
# both an access and refresh token.
access_type='offline',
# This parameter enables incremental auth.
include_granted_scopes='true')
# Store the state in the session so that the callback can verify that
# the authorization server response.
flask.session['state'] = state
return flask.redirect(authorization_url)
@app.route('/oauth2callback')
def oauth2callback():
# Specify the state when creating the flow in the callback so that it can
# verify the authorization server response.
state = flask.session['state']
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
CLIENT_SECRETS_FILE, scopes=SCOPES, state=state)
flow.redirect_uri = flask.url_for('oauth2callback', _external=True)
# Use the authorization server's response to fetch the OAuth 2.0 tokens.
authorization_response = flask.request.url
flow.fetch_token(authorization_response=authorization_response)
# Store the credentials in the session.
# ACTION ITEM for developers:
# Store user's access and refresh tokens in your data store if
# incorporating this code into your real app.
credentials = flow.credentials
credentials_as_dict = credentials_to_dict(credentials)
flask.session['credentials'] = credentials_as_dict
# Store the credentials as JSON to a file on disk.
with open(CREDENTIALS_FILE, 'w') as f:
json.dump(credentials_as_dict, f)
return flask.redirect(flask.url_for('index'))
def credentials_to_dict(credentials):
return {'token': credentials.token,
'refresh_token': credentials.refresh_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret,
'scopes': credentials.scopes}
def load_credentials():
in_error = False
try:
with open(CREDENTIALS_FILE) as f:
credentials = json.load(f)
f.close()
keys = ['token', 'refresh_token', 'token_uri', 'client_id', 'client_secret', 'scopes']
for key in keys:
in_error = (key not in credentials)
if in_error: break
except Exception as e:
in_error = True
finally:
if not in_error:
flask.session['credentials'] = {
'token': credentials['token'],
'refresh_token': credentials['refresh_token'],
'token_uri': credentials['token_uri'],
'client_id': credentials['client_id'],
'client_secret': credentials['client_secret'],
'scopes': credentials['scopes']
}
return in_error
def channels_get_upload_playlist_id(client, **kwargs):
response = client.channels().list(
**kwargs
).execute()
return flask.jsonify(**response)
def playlist_get_videos(client, **kwargs):
response = client.playlistItems().list(
**kwargs
).execute()
return flask.jsonify(**response)
def videos_get_file_names(client, **kwargs):
response = client.videos().list(
**kwargs
).execute()
return flask.jsonify(**response)
if __name__ == '__main__':
# When running locally, disable OAuthlib's HTTPs verification. When
# running in production *do not* leave this option enabled.
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
app.run('0.0.0.0', 5000, debug=True)
The example code should be self-explanatory, but let’s go over some of the key points:
● For the /oauth2callback
endpoint, there are two key points:
⑴ In the section
Note on OAuth 2.0 Authorized redirect URIs
we mentioned configuring http://localhost:5000/oauth2callback
as the value for redirect_uri
. This /oauth2callback
is the endpoint, and the application has been coded to listen to
port 5000
at line 191: app.run('0.0.0.0', 5000, debug=True)
.
⑵ In the
endpoint handler method oauth2callback():
, lines 124 to 126:
124
125
126
# Store the credentials as JSON to a file on disk.
with open(CREDENTIALS_FILE, 'w') as f:
json.dump(credentials_as_dict, f)
This is where we write the entire granted credentials to a local JSON file as discussed in point 2 above.
● For the method load_credentials()
, we attempt to load credentials
from an existing credentials JSON file.
Please see point 3 above.
● The default endpoint handler method index()
:
This is like the “main” function of this example “program”:
⑴ If the application has not been authorised yet, we attempt to load the previously acquired credentials from the local JSON file. If there are no previous credentials, or the local JSON content is in error, we attempt to request authorisation from the Google Cloud API.
We optimistically assume that one of the above steps will succeed. This is not production-ready code as stated in the introduction.
⑵ The rest of the code in this method is as per the official example. 💥 Please note that the three API call methods discussed in point 4 above have all been commented out. You will need to enable each one of them to see how they work.
⓷ To run the example application, we need to install the required packages onto the active virtual environment as per the official instructions:
pip install --upgrade google-api-python-client
pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
pip install --upgrade flask
From the active virtual environment venv
, launch the example as follows:
▶️Windows 10:venv\Scripts\python.exe youtube_data_api.py
▶️Ubuntu 22.10:./venv/bin\python youtube_data_api.py
🚀 Then, on the same machine, access the example URL http://localhost:5000/.
For the first time requesting authorisation, the Google Cloud API will initiate the OAuth 2.0 user process, requesting the user to grant permissions. Please see the screenshots of this process below. Your experience should look similar:
The default endpoint method handler index():
was calling videos_get_file_names(...)
.
After the user granted permissions and the OAuth 2.0 process was successful, we should have a response similar to the one illustrated below:
💥 Most importantly, the credentials JSON file credentials_youtube.json
should have been written to the directory where youtube_data_api.py
is located.
Please check this for yourself.
⓸ Using the credentials_youtube.json
file on another machine:
For learning purposes, I copied both the
youtube_data_api.py
and credentials_youtube.json
files to Ubuntu 22.10, set up the virtual environment, and ran the example without
reconfiguring redirect_uri
.
The Google Cloud API happily accepted these credentials. Please see the screenshot below:
⓹ The method videos_get_file_names(client, **kwargs):
can only work with videos which belong to
our own YouTube channel. For understanding purposes, I tried to access a public video from another public channel, and below is the response:
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://youtube.googleapis.com/youtube/v3/videos?part=fileDetails&id=97t-8NF7oz4&alt=json returned “The request is not properly authorized to access video file or processing information. Note that the fileDetails
, processingDetails
, and suggestions
parts are only available to that video’s owner.”. Details: “[{‘message’: “The request is not properly authorized to access video file or processing information. Note that the fileDetails
, processingDetails
, and suggestions
parts are only available to that video’s owner.”, ‘domain’: ‘youtube.video’, ‘reason’: ‘forbidden’, ‘location’: ‘part’, ‘locationType’: ‘parameter’}]”>
❻ Here are some helpful links for managing Google Cloud API projects.
- https://console.cloud.google.com: Google Cloud Console.
- https://console.developers.google.com/apis/credentials: API credentials console.
- https://myaccount.google.com/u/0/permissions: Revoke OAuth 2.0 authorisations previously granted.
❼ Please note: We have previously discussed the Google Gmail API in the following posts:
- GMail API: quick start with Python and NodeJs
- GMail API: send emails with NodeJs
- CI/CD #02. Jenkins: basic email using your Gmail account
- Sending emails via Gmail account using the Python module smtplib
In addition to the Google Gmail API, I have also used the Cloud Text-to-Speech API with Python. The Text-to-Speech API is comparatively easier to set up than both the Gmail API and the YouTube API.
❽ I did not intend for this post to be this long. There are just so many details to cover. Hopefully, this post will serve as a stepping stone for trying other Google Cloud APIs. I have learned a lot writing this post. And I apologise for not being able to make it shorter.
Thank you for reading. I hope you find the information in this post useful. Stay safe, as always.
✿✿✿
Feature image source: