YouTube Subscriptions API: Why mine Works But mySubscribers Returns Nothing
subscriptions.list looks like one endpoint. It is actually four separate, mutually exclusive feeds, and three of them need OAuth 2.0 before they return a single row.
Four filters, one method
mine
OAuth requiredReturns the channels the authenticated user is subscribed to. Works reliably in testing because it is your own account and your own data.
channelId
Public data onlyReturns another channel's subscriptions, but only if that channel has chosen to make its subscriptions public. Google's own guide states this call returns a 403 Forbidden response otherwise.
mySubscribers
OAuth requiredReturns channels subscribed to the authenticated user's own channel, in no particular order. Google's documentation notes the maximum number returned through this API might be limited.
myRecentSubscribers
OAuth requiredSame audience as mySubscribers, ordered newest first. Carries the identical might-be-limited caveat; it is not a promised full export of a subscriber base.
Quota cost is not the blocker
| Method | Quota cost | Authorization |
|---|---|---|
| subscriptions.list | 1 unit | OAuth 2.0 for mine / mySubscribers / myRecentSubscribers; open for a public channelId |
| subscriptions.insert | 50 units | OAuth 2.0, youtube.force-ssl, youtube, or youtubepartner scope |
Where teams get stuck
Subscriptions vs subscribers
Building an audience-analytics feature on mine when the requirement was actually who-follows-this-channel, the parameter needed is mySubscribers, a different OAuth-authorized call entirely.
The 403 on channelId
Reading a partner channel's subscriptions with channelId works against a handful of test channels, then returns subscriptionForbidden (403) the moment it hits a channel that keeps its list private, which is most channels.
Might be limited is not zero, but not complete either
mySubscribers and myRecentSubscribers do not promise a full export. A channel with a large subscriber base can see a partial list returned even with correct OAuth and a valid scope.
subscriptionForbidden on insert too
The same error type blocks subscriptions.insert for three separate reasons: the maximum subscription count is reached, the target is the user's own channel, or too many subscriptions were created recently.
accountClosed / accountSuspended
A list call can fail for reasons unrelated to your integration; the subscriber's account itself is closed or suspended, and the API surfaces that as a 403, not a 404.
subscriberNotFound on delete
Removing a subscription is a two-step read-then-delete flow. If the subscription ID from the list call is stale, the delete call returns a 404 instead of a quiet no-op.
The access path, at a high level
- 1
Decide which of the four feeds the feature actually needs: who a user follows, who follows a user, or a public channel's list, before writing a single request.
- 2
Confirm which calls need OAuth 2.0 user consent versus which can run against a public channel without it.
- 3
Design for the documented error set, subscriptionForbidden, accountClosed, accountSuspended, subscriberNotFound, as expected states rather than exceptions.
- 4
Build the UI around a possibly partial subscriber list rather than assuming mySubscribers returns every follower.
- 5
Budget subscriptions.insert separately; its 50-unit cost and its own throttling behave nothing like the 1-unit list call.
What a correctly scoped integration looks like
Reading this correctly the first time, which feed to call, which OAuth consent screen it needs, and which documented 403/404 state to design for, is exactly the kind of detail that turns into a support ticket weeks after launch if it is guessed instead of verified. If you are scoping a subscriber-facing or cross-promotion feature on the YouTube Data API, get the OAuth and scope decisions checked before you build against them. See related coverage on API key vs OAuth 2.0, the Google OAuth verification guide, and the YouTube quota increase audit process.