How can i retrieve a list of channels name ?
so for example :
( i'm searching for "abcde" ) so , if i type "ab" ,the link given below should give me the JSON with the channels name list :
ex.
-abc
-abbe
-abcd
-abcde
https://www.googleapis.com/youtube/v3/..../search=ab
i only found this https://www.googleapis.com/youtube/v3/channels?part=contentDetails&forUsername=USERNAMEUSER&key={API_KEY}
If you want to retreive all channel start with "ad" for example, you need to use the ressource search.list with the parameters:
part: snippet
q: "ad" //for example
type: channel
https://www.googleapis.com/youtube/v3/search?part=snippet&q=ad&type=channel&key={YOUR_API_KEY}
The result show you all the YouTube channel starting with "ad"
Related
It seems Youtube has gotten rid of /channel/XXXX urls on their page, its now /c/username? with username NOT really being a "username". For example
https://www.youtube.com/c/lukemiani
Running a lookup via
https://www.googleapis.com/youtube/v3/channels?part=snippet&forUsername=lukemiani&key=...
returns no results.
I've got a bunch of non-technical users who've been trained to look for /channel/x or /user/x and input the correct thing into my app. Now that /channel is gone how do I (or they) translate /c/x to a channel id?
I'm looking for an API solution, not a view source and reverse engineer code solution.
According to the official support staff, a given channel may have associated an URL of form:
https://www.youtube.com/c/CUSTOM_NAME.
In such a case, the respective channel's customUrl property is CUSTOM_NAME.
Now, your problem may be reformulated as follows:
Given a CUSTOM_NAME for which the URL above points to an existing channel, is there a procedure that is able to produce -- by making use of YouTube Data API -- that channel's ID, such that the respective procedure to be DTOS-compliant (i.e. the procedure works by not scraping the HTML text obtained from the respective custom URL)?
The short answer to the above question is no, there's none. (Please have a look at my answer and the attached comments I gave recently to a similar question).
The longer answer would be the following: yes, it can be imagined an algorithm that solves the problem, but only partially (since there's no guarantee that it'll always give positive results).
Here is the algorithm:
Call the Search.list API endpoint with the following parameters:
q=CUSTOM_NAME,
type=channel, and
maxResults=10.
Extract from the result set obtained the channel IDs (these IDs are located at items[].id.channelId);
For each channel ID in the list obtained at step 2:
Invoke Channels.list API endpoint for to obtain the channel's associated customUrl property (if any);
If the obtained customUrl is equal with CUSTOM_NAME, then stop the algorithm yielding the current channel ID; otherwise, continue executing the current loop;
Stop the algorithm by yielding channel ID not found.
Due to the fuzzy nature of the result sets provided by the Search.list endpoint, one cannot exclude the possibility that there could actually exist custom URLs (i.e. URLs of the form above that are pointing to existing channels) for which this algorithm is not able to yield the ID of the associated channel.
A final note: the Channels.list endpoint accepts its id parameter to be a comma-separated list of channel IDs. Therefore, one may easily modify the algorithm above such that instead of N invocations (N <= 10) of Channels.list endpoint to have only one.
An implementation of the algorithm above in Python language, using Google's APIs Client Library for Python:
def find_channel_by_custom_url(
youtube, custom_url, max_results = 10):
resp = youtube.search().list(
q = custom_url,
part = 'id',
type = 'channel',
fields = 'items(id(kind,channelId))',
maxResults = max_results
).execute()
assert len(resp['items']) <= max_results
ch = []
for item in resp['items']:
assert item['id']['kind'] == 'youtube#channel'
ch.append(item['id']['channelId'])
if not len(ch):
return None
resp = youtube.channels().list(
id = ','.join(ch),
part = 'id,snippet',
fields = 'items(id,snippet(customUrl))',
maxResults = len(ch)
).execute()
assert len(resp['items']) <= len(ch)
for item in resp['items']:
url = item['snippet'].get('customUrl')
if url is not None and \
caseless_equal(url, custom_url):
assert item['id'] is not None
return item['id']
return None
where the function caseless_equal used above is due to this SO answer.
I posted here a simple Python3 script that encompasses the function find_channel_by_custom_url above into a standalone program. Your custom URL applied to this script yields the expected result:
$ python3 youtube-search.py \
--custom-url lukemiani \
--app-key ...
UC3c8H4Tlnm5M6pXsVMGnmNg
$ python3 youtube-search.py \
--user-name lukemiani \
--app-key ...
youtube-search.py: error: user name "lukemiani": no associated channel found
Note that you have to pass to this script your application key as argument to the command line option --app-key (use --help for brief help info).
You can do that in python, or with any http request library, by requesting the link and parsing the response for the channel ID. The channel id is in the canonical link tag that handles the redirection:
import requests
import re
url = "https://www.youtube.com/shroud"
r = requests.get(url, allow_redirects=True)
print(re.search(r'(?<=<link rel="canonical" href="https:\/\/www\.youtube\.com\/channel\/)(-?\w+)*(?=">)', r.text).group(0))
# Returns UCoz3Kpu5lv-ALhR4h9bDvcw
It seems Youtube has gotten rid of /channel/XXXX urls on their page, its now /c/username? with username NOT really being a "username". For example
https://www.youtube.com/c/lukemiani
Running a lookup via
https://www.googleapis.com/youtube/v3/channels?part=snippet&forUsername=lukemiani&key=...
returns no results.
I've got a bunch of non-technical users who've been trained to look for /channel/x or /user/x and input the correct thing into my app. Now that /channel is gone how do I (or they) translate /c/x to a channel id?
I'm looking for an API solution, not a view source and reverse engineer code solution.
According to the official support staff, a given channel may have associated an URL of form:
https://www.youtube.com/c/CUSTOM_NAME.
In such a case, the respective channel's customUrl property is CUSTOM_NAME.
Now, your problem may be reformulated as follows:
Given a CUSTOM_NAME for which the URL above points to an existing channel, is there a procedure that is able to produce -- by making use of YouTube Data API -- that channel's ID, such that the respective procedure to be DTOS-compliant (i.e. the procedure works by not scraping the HTML text obtained from the respective custom URL)?
The short answer to the above question is no, there's none. (Please have a look at my answer and the attached comments I gave recently to a similar question).
The longer answer would be the following: yes, it can be imagined an algorithm that solves the problem, but only partially (since there's no guarantee that it'll always give positive results).
Here is the algorithm:
Call the Search.list API endpoint with the following parameters:
q=CUSTOM_NAME,
type=channel, and
maxResults=10.
Extract from the result set obtained the channel IDs (these IDs are located at items[].id.channelId);
For each channel ID in the list obtained at step 2:
Invoke Channels.list API endpoint for to obtain the channel's associated customUrl property (if any);
If the obtained customUrl is equal with CUSTOM_NAME, then stop the algorithm yielding the current channel ID; otherwise, continue executing the current loop;
Stop the algorithm by yielding channel ID not found.
Due to the fuzzy nature of the result sets provided by the Search.list endpoint, one cannot exclude the possibility that there could actually exist custom URLs (i.e. URLs of the form above that are pointing to existing channels) for which this algorithm is not able to yield the ID of the associated channel.
A final note: the Channels.list endpoint accepts its id parameter to be a comma-separated list of channel IDs. Therefore, one may easily modify the algorithm above such that instead of N invocations (N <= 10) of Channels.list endpoint to have only one.
An implementation of the algorithm above in Python language, using Google's APIs Client Library for Python:
def find_channel_by_custom_url(
youtube, custom_url, max_results = 10):
resp = youtube.search().list(
q = custom_url,
part = 'id',
type = 'channel',
fields = 'items(id(kind,channelId))',
maxResults = max_results
).execute()
assert len(resp['items']) <= max_results
ch = []
for item in resp['items']:
assert item['id']['kind'] == 'youtube#channel'
ch.append(item['id']['channelId'])
if not len(ch):
return None
resp = youtube.channels().list(
id = ','.join(ch),
part = 'id,snippet',
fields = 'items(id,snippet(customUrl))',
maxResults = len(ch)
).execute()
assert len(resp['items']) <= len(ch)
for item in resp['items']:
url = item['snippet'].get('customUrl')
if url is not None and \
caseless_equal(url, custom_url):
assert item['id'] is not None
return item['id']
return None
where the function caseless_equal used above is due to this SO answer.
I posted here a simple Python3 script that encompasses the function find_channel_by_custom_url above into a standalone program. Your custom URL applied to this script yields the expected result:
$ python3 youtube-search.py \
--custom-url lukemiani \
--app-key ...
UC3c8H4Tlnm5M6pXsVMGnmNg
$ python3 youtube-search.py \
--user-name lukemiani \
--app-key ...
youtube-search.py: error: user name "lukemiani": no associated channel found
Note that you have to pass to this script your application key as argument to the command line option --app-key (use --help for brief help info).
You can do that in python, or with any http request library, by requesting the link and parsing the response for the channel ID. The channel id is in the canonical link tag that handles the redirection:
import requests
import re
url = "https://www.youtube.com/shroud"
r = requests.get(url, allow_redirects=True)
print(re.search(r'(?<=<link rel="canonical" href="https:\/\/www\.youtube\.com\/channel\/)(-?\w+)*(?=">)', r.text).group(0))
# Returns UCoz3Kpu5lv-ALhR4h9bDvcw
I call YT.Channel API with a list of Ids and I get an error:
GoogleJsonResponseException: API call to youtube.channels.list failed with error: Request contains an invalid argument.
YouTube.Channels.list('id, snippet, statistics', {
id: resultsParentChannelIdsPerPage.join()
}).getItems()
id = UC5JU3rLOMvB7ZIXI2oi1ubg,UC4mKtxAtWQgmkFC6S6siNVg,UC-4hR9ralZoAW15tAwSbJ_A,UCvdwiASqQrIIozQcVAXvRXw,UCUIKx2bIjRcBWyIa3AQGSCg,UClkJAMCknefAzrYfpk1_0Nw,UCsDm3gAWuDRDLMjZLoUxOuA,UC-OkSUXpLrS2eBpztAJ78wg,UCb6RivygioXGs0icq4McBdg,UCmAf6BdYS-5QmXxBuJZgNpQ,UC6rDrJjome8e_iBQI1MLeZg,UCJ0lYZCucWTPc_IfE2vZNTg,UCVy5saLw3psF5laPWhahGHA,UCXskq-my9ltmT6SpdL7b_cw,UCpctmQs9AEwiIZgTcWSV0mg,UCv4ZlVO5-z-uVIm1Y6ol-DA,UCPtQnd-8OBSzvqnQVKaA_8g,UC_uQYR3lHS36jkBRqdvQIFw,UCoJuf64ajKTOZ6mX30zulKg,UCM-GJfgjXFajHll_uGeZPBQ,UC2ojGYd_fg8oU71beXUMW9g,UCT_dVMJ2eSGKugeXnMZcbfQ,UC6PHRps6wOfBJKoDxEI37Ew,UC2Ra3RK4FW38skAoYEtXJbQ,UC2u7_TuItL4on_9SuwJhO_A,UCt-gKqNg_k2bb-bSe7y3z4g,UC2UotqDGeOMUl-gQG3t9sKw,UCdbVBcrKBtu8oUcp4JuLpvw,UCKHpDyswx5VskURci4FPqUA,UCiNHdTU2jYRbUf1cbMCxdaQ,UC3osMa_MdseDVrXlbZFSZDw,UCbnwaC-Tbi1duuDbjfV-Thg,UCBOrTOryVc2JKsNOu7_wO6g,UCM8UoJ4z4NMvp5pwYQjx8uQ,UCnU2sysDk58MuMQHxqgDd7w,UCuldUFBFddgeVN6HJ-yIBjA,UCsEgNI5S2Vdy3Q7LizK2OSA,UClN9w3sTTs6lpntoeHyYvSA,UCgZlOI3AqanZW0tjCSJCKfA,UCqS9WhAUJ-6PiC-8mZ0rDSQ,UCBH5Es0HeCBBlHvWG9c2ipA,UCpPgyVE8TKJr-MnpB44Au4w,UCJxgQl6TU8FGmMzG24xxYFg,UCpe9hHSEkTs5BD6Ufi0-XuA,UCrk1G4da0dsnLsPjsov5fTA,UCtF629dMzswzAupMUEO-bPw,UCsRcjJkUmU_Ny5D9pn5ZGDw,UC5Wm0eXXRAA6Pcjlq8-EaLw,UCOakkksW_nWRDkPl43VzAQA,UC4JhVBsy-Yfr3dQy7G1EYuQ,UCfS8vOYmleKZU8zNjzsZ6qg,UCPWsJzhhZSPlfQ7DOjSA4Fg,UCPKKa8RgdfoMRBkyt8BhIqA,UCa3bfoq50eqErBDgq0p2cQA,UCyH05wKVW-96Lz2mqhGnzVw,UCiXjl5HwqmuCjr5ZmW00csQ,UCA9tlIHeg-k8z3PUpozkUmA,UC_Bc8M2p5fpYqlfWvbVmw2g,UCnD86huZnRWKDMZISbQx6kg,UCtRn5U4Uz2vbREF0qD0TLuA
I didn't get this in previous similar runs. What has changed?
API explorer
Nothing has changed, as far as I know. Fact is that -- with the exception of CommentThreads.list, Comments.list and Members.list endpoints -- all YouTube Data API endpoints that are providing result sets would not return result sets of more than 50 items.
Therefore, when using the Channels.list endpoint's request parameter id, you'll have to limit yourself to pass to it a comma-separated list of channel IDs of at most 50 elements.
Using this code allows me to search for YouTube channels and return their statistics; for some reason, however, only about half the channels return any results.
For example, if I use this link to test the API, you can see that I searched for Animal Planet, and that yields no results. However, if we go to YouTube's website and search for the same thing, we get the channel as needed.
Why does this happen and how can this be fixed?
This is the code I used:
#commands.command()
async def yt_test(self, ctx, *, search):
api_key = '...'
youtube = build('youtube', 'v3', developerKey=api_key)
request = youtube.channels().list(
part="snippet,statistics",
forUsername=search,
maxResults=1
)
response = request.execute()
try:
for item in response['items']:
link = item['id']
thumb_image = item['snippet']['thumbnails']['default']['url']
views = "{:,}".format(int(item['statistics']['viewCount']))
subs = "{:,}".format(int(item['statistics']['subscriberCount']))
vidCount = "{:,}".format(int(item['statistics']['videoCount']))
except:
Notfound = discord.Embed(description= "Sorry, but this Channel was not located, check spelling" , color=0xfc0328)
await ctx.send(embed=Notfound)
finalresult = discord.Embed(title = search, url='https://www.youtube.com/channel/' + link,
description= '**Statistics**\nViews: ' + views + '\nSubscribers: ' + subs + "\nVideos: " + vidCount, color=0x00ff00)
finalresult.set_thumbnail(url = thumb_image)
await ctx.send(embed=finalresult)
print(f"{ctx.author} looked up the profile of {search} --- in #{ctx.guild.name}")
You have to acknowledge that invoking the Channels.list API endpoint, by passing to it the parameter forUsername, is by no means the same thing as going to the YouTube's Web UI for to apply a manual search. For these things to come to light, do bear with me for a little while...
According to the official docs, the Channels.list endpoint invoked with forUsername=... produces the meta-data associated to the channel of which username is given as argument to the parameter forUsername:
forUsername (string)
The forUsername parameter specifies a YouTube username, thereby requesting the channel associated with that username.
According to an official Google staff post from 2013-07-11, it's not a requisite that every channel have attached an username. Hence, is perfectly possible for Channels.list endpoint to return no channel at all, if the argument of forUsername does not represent a YouTube username.
If you use one of my public (MIT licensed) Python 3 script -- youtube-search.py --, you'll see that it returns nothing for your queried username Animal Planet:
$ python3 youtube-search.py --user-name "Animal Planet"
youtube-search.py: error: user name "Animal Planet": no associated channel found
But if you invoke that script as follows:
$ python3 youtube-search.py --search-term "Animal Planet" --type channel
UCkEBDbzLyH-LbB2FgMoSMaQ: Animal Planet
UCuTSm59-_kap6J7Se-orUVA: Animal Planet Latinoamérica
UCpvajaPSWvFlyl83xvzs65A: animalplanet românia
UCgyOEJZJLPKclqrDyUkZ6Ag: Animal planet 1
UCypzlOdJyyOR2NhKv0o3zig: 動物星球頻道/ Animal Planet Taiwan
UCmMm-p51c14XJ1p294faCmA: Animal Planet Brasil
UCejVe2sNPjjvfCXg35q_EQQ: Animal Planet Videos
UClQLf_zw2A_nRaB45HWTbtA: Your Animal Planet
UChQEdt9dBiCkcCch6LyrjtA: Cute Animal Planet
UCRIS8Y1kfrFvFF_6vt6_3Cg: Animal Planet Videos
you'll see pretty much the same output as the YouTube's Web UI will show when queried for the same search term and filtered for TYPE being Channel.
Do note that your own results (the one obtained from youtube-search.py and the other provided by the YouTube Web UI) may very likely differ from the above ones; this is so because Google searches are tailored for the user that initiates the query.
The explanation behind the matching results sets obtained from youtube-search.py and YouTube Web UI is the following:
The API endpoint that corresponds to YouTube's own search feature accessible via its Web UI is none other than Search.list.
Do convince yourself about this claim by reading the code of youtube-search.py: when invoking it with --search-term "Animal Planet" --type channel, that script executes the function Service.search_term:
class Service:
...
def search_term(self, term, type = None):
resp = self.youtube.search().list(
q = term,
type = type,
part = 'id,snippet',
fields = 'items(id,snippet(title))',
maxResults = self.max_results
).execute()
...
with term equal to the string Animal Planet and type equal to the string channel. Consequently, this script is calling for the Search.list endpoint, passing to it the parameters q and type as mentioned.
I'm trying to figure out the best way to get a channel's upload playlistID given the channel's channelID. E.g. for the channel with channelID
UC9CuvdOVfMPvKCiwdGKL3cQ
The corresponding upload playlistID is
UU9CuvdOVfMPvKCiwdGKL3cQ
Notice the second character has changed from a "C" to a "U"
I can do this transformation via string manipulation, but I'm curious if there's a better, less hacky way to find the upload playlist ID through the official youtube api.
Here's some Kotlin code that shows my issue:
I can find the ChannelID for the "Game Grumps" channel through the following youtube api v3 search:
val req = youtube.search().list("snippet");
req.key = {API_KEY}
req.q = "Game Grumps"
req.type = "channel"
val response = req.execute();
The resulting Channel id (response.items[0].snippet.channelId) is UC9CuvdOVfMPvKCiwdGKL3cQ
But when I run the following to try to get the videos uploaded by the channel, I have to use the transformed ChannelID (starting with UU instead of UC)
val req = youtube.PlaylistItems().list("snippet")
req.playlistId = "UU9CuvdOVfMPvKCiwdGKL3cQ"
req.key = {API_KEY}
val response = req .execute()
If I use the untransformed "UC" channelID, I get the following error: The playlist identified with the requests playlistId parameter cannot be found.
Instead of just replacing the second character with a "U", what's the more robust way (e.g. using the youtube API) of translating a ChannelID to a PlaylistID (for the uploads from that channel)?
I would suggest using the official Youtube API, instead of trying to manipulate the strings. You can follow the instructions here:
Instructions to get video ids for all uploaded videos for a channel in V3
Get the channel id for the channel you want (you probably only need to do this once, then you can save it)
Use search.list
Set type to channel
Set q to the name of the channel you want
Grab the channel id (something like this: "channelId": "UC0X2VuXXXXXXXXXXXXXXXX")
Get the playlist id for the channel uploads using the channel id from step 1 (you probably only need to do this once, then you can save it)
Use channels.list
Set id to UC0X2VuXXXXXXXXXXXXXXXX from step 1
Grab the uploads key from contentDetails (something like this: "uploads": "UU0XXXXXXXXXXXXXXXXXXXX")
Get the videos via the playlistitems in the playlist using the playlist id from step 2
Use playlistItems.list
Set playlistId to UU0XXXXXXXXXXXXXXXXXXXX from step 2
Go through each PlaylistItem and pull out the video id