How to use YouTube Subscriber API

Recently I’ve seen some games such as Bubble Gum Simulator, allow you to input your channel id and get in-game rewards if you’re subscribed to them. With that being said there are two things that need to be done. We need to make an API Key on Google and insert it into the module code.



How do I make my API key?

Step 1
Go to console.developers.google.com and click “Create Project”, and create a new project.

Step 2
When the project is created you will be sent to this screen and click, “Explore and enabled APIs

Step 3
Click the “Enable APIs and Services” button

Step 4
Click the “YouTube Data API v3” button

Step 5
Click "Create Credentials"

Step 6
In the red boxes make those selections match mine. Then, click "What Credentials do I need?"

Step 7
Click the icon that’s arrowed to copy the API Key. Then, click "Done"




Setting up the module

  • Paste your API key into the variable, “API_KEY”
  • Paste your YouTube channel you want players to be subscribed to channel’s id
-- YouTube Subscriber API
-- author: OnlyRoids (Stephen)
-- date: 18 NOV 2020


--[[
	Don't know what a channel id is?
	*	The channel id is the unique number/letter combination in the URL-
		-of a YouTube channel.
	
	Example:
	https://www.youtube.com/channel/UCO_8hF-oulap_6lXy0oXLjg
	
	The channel id is:
	UCO_8hF-oulap_6lXy0oXLjg
]]


---- ROBLOX SERVICES ----
local HttpService = game:GetService("HttpService")

---- PRIVATE VARIABLES ----
local MAX_RESULTS_PER_PAGE = 50
local TARGET_CHANNEL_ID = "" -- YouTube channel id player is supposed to be subscribed to
local API_KEY = "" -- Your API Key

---- URL'S ----
local URL = "https://youtube.googleapis.com/youtube/v3/subscriptions?part=snippet&channelId=%s&maxResults=%d&key=%s"
local NEXT_PAGE_URL = "https://youtube.googleapis.com/youtube/v3/subscriptions?part=snippet&channelId=%s&maxResults=%d&pageToken=%s&key=%s"



---- PRIVATE FUNCTIONS ----
function get_channel_subscriptions(channelId, pageToken)
	local URL = pageToken and string.format(NEXT_PAGE_URL, channelId, MAX_RESULTS_PER_PAGE, pageToken, API_KEY) or string.format(URL, channelId, MAX_RESULTS_PER_PAGE, API_KEY)
	
	local success, channelSubscriptions = pcall(function()
		return HttpService:GetAsync(URL)
	end)
	
	if (success) then
		return HttpService:JSONDecode(channelSubscriptions)
	else
		warn(channelSubscriptions) -- error
		return nil
	end
end


function get_page_numbers_left(channelSubData)
	local pages = 0
	
	local pageInfo = channelSubData.pageInfo
	local totalResults = pageInfo.totalResults
	local resultsPerPage = pageInfo.resultsPerPage
	
	if (not channelSubData.nextPageToken) then
		return pages
	end
	
	pages = tostring((totalResults - #channelSubData.items) / resultsPerPage)
	if (string.find(pages, ".")) then
		pages = tonumber(string.split(pages, ".")[1]) + 1
	end	
	
	return pages
end


function check_if_subbed_to_channel(subData, targetChannelId)
	assert(typeof(targetChannelId) == "string", "targetChannelId must be of type [string]")
	
	for _, v in pairs(subData) do
		if (v == targetChannelId) then
			return true
		end
	end
	return false
end


---- RETURN FUNCTION ----
return function(channelId)
	local channelsSubscribedTo = {}
	local pageToken = nil
	local channelSubs = get_channel_subscriptions(channelId)
	
	if (channelSubs) then
		local pagesRemaining = get_page_numbers_left(channelSubs)

		for _, v in pairs(channelSubs.items) do
			if (v and v.snippet) then
				table.insert(channelsSubscribedTo, v.snippet.resourceId.channelId)
			end
		end

		if (pagesRemaining) then
			pageToken = channelSubs.nextPageToken
			for i = 1, pagesRemaining do
				local pageChannelSubs = get_channel_subscriptions(channelId, pageToken)

				if (pageChannelSubs and pageChannelSubs.items and pageChannelSubs.nextPageToken) then
					for _, v in pairs(pageChannelSubs.items) do
						if (v and v.snippet) then
							table.insert(channelsSubscribedTo, v.snippet.resourceId.channelId)
						end
					end
					pageToken = pageChannelSubs.nextPageToken
				elseif (not channelsSubscribedTo) then
					warn("Failed to retrieve channel subscription info")
					return false
				end
			end
		end

		return check_if_subbed_to_channel(channelsSubscribedTo, TARGET_CHANNEL_ID)
	end
	warn("channel sub info has failed to load!")
	return false
end


Using the module

-- The channelId argument is the players channel id you are checking (The channel id they input)

local YouTubeAPI = require(modulePath)

function PlayerIsSubscribed(channelId)
    return YouTubeAPI(channelId) -- returns true or false
end

local isSubbed = PlayerIsSubscribed(channelId)
if (isSubbed) then
    print("Player is subscribed")
else
    print("Player is not subscribed")
end
45 Likes

very good this tutorial, one of the most useful Tutorials I’ve ever seen
Thanks!
I will use this in a game

8 Likes

I’m curious if this is against TOS because I remember that you aren’t suppose to ask for players to do actions for rewards

I don’t know if asking for Subscribes are allowed but it is an exchange for something so :man_shrugging:

It is a great resource, good work.

4 Likes

Bubble Gum Simulator and Strucid has been using this API for some time, so it’s probably fine.

1 Like

No can do, we can’t assume that it’s fine just because other people do it, that’s not how the Law or TOS works.

A real example: people putting Discord invites (any 3rd party link) in their game description, group description, player description and such. This isn’t allowed, but people do it and some get punished for it some don’t.

Also the games you mentioned are Front page games, they are profitable to Roblox so they slip by sometimes because Roblox wouldn’t cannibalizes itself unnecessarily.

In regards to that, I would rather not gamble with Roblox Moderation, enough said.

(I think Roblox should change their TOS to be honest)

4 Likes

You’re right, but that is why I said “probably”. It is just interesting considering those games, and even more, have had it implemented for some time and been unnoticed by moderators, if so.

I’ll try to contact a staff member regarding it. (I will update this reply if I get a response)

The ROBLOX quote explains itself. “As they are not in exchange for something (e.g, in exchange for a thumb up on your game).” This is just checking if people are subscribed on YouTube. Basically, the same thing as using a Twitter code.

2 Likes

Eh. Kinda of. Lumber Tycoon 2 had a axe which was available if you followed Defaultio in twitter. I don’t find much of a issue with it.

Great tutorial! I don’t fully understand the code going on, but what I do understand that the players need to input their channel Id in order to redeem the stuff. Does this account for the fact that some players could use the same channel ID for like 5 different accounts? lol

1 Like

No, you would have to use a GlobalDataStore to check to see if the channel id is used.

1 Like

How do I use this where the user inputs their channel ID and it checks, I can’t manage to get this working

1 Like