EventSub 403: Failed to fulfill the request: Forbidden

Hello :smile: , I’m using nearly 1:1 the example code from the twitchio help page to subscribe to follow events.

I get always “Exception subscribing event: 403: Failed to fulfill the request: Forbidden”.

I setup everything needed:

  • From outside working callback endpoint with ssl veryfied hostname
  • Requests are forwarded to the according machine via port 4000
  • Created an application in the developer console and use the working client secret and id
  • Working token for the Bot (was existing already before I generated the application client secret and id)
  • Channel name is correct
  • broadcaster and moderator ID is the same (my own twitch integer ID)

I have no idea why this is happening. I replaced the bot listener by an own webserver to see if there is an attemp to call the callback. But this does not happen.

Any idea what causes this problem? Is there somewhere a token scope missing I didn’t see?

Here is the used code

import twitchio
from twitchio.ext import commands, eventsub

esbot = commands.Bot.from_client_credentials(
    client_id = 'working_client_id',
    client_secret = 'working_client_secret')

esclient = eventsub.EventSubClient(esbot,
    webhook_secret = 'a_secret',
    callback_route = 'https://working_and_signed_ssl_hostname/callback')

class Bot(commands.Bot):

    def __init__(self):
        super().__init__(
            token = 'a_working_token', 
            prefix = '!', 
            initial_channels=['channel'])

    async def __ainit__(self) -> None:
        self.loop.create_task(esclient.listen(port=4000))
        try:
            await esclient.subscribe_channel_follows_v2(
                broadcaster=12345, moderator=12345)
            print('subscribe_channel_follows_v2 done')
        except twitchio.HTTPException as e:
            print('Exception subscribe follow event: ' + str(e))

    async def event_ready(self):
        print('Bot is ready!')


bot = Bot()
bot.loop.run_until_complete(bot.__ainit__())

@esbot.event()
async def event_eventsub_notification_followV2(
    payload: eventsub.ChannelFollowData) -> None:
    print('Received followV2 event!')
    channel = bot.get_channel('channel')
    await channel.send(f'{payload.data.user.name} followed woohoo!')

bot.run()

Execute script

$ ./eventsub.py 
Exception subscribing event: 403: Failed to fulfill the request: Forbidden
Bot is ready!

Has the broadcaster/moderator authed to your app with the moderator:read:followers scope?

As the documentation https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types/#channelfollow, states, that scope is required for that topic.

Good hint!
I created a new token on twitchtokengenerator.com with this scope, but unfortunately it behaves the same as before and the subscription attempt still fails with 403

You really shouldn’t be using 3rd party token generators as that just complicates debugging and has its own issues. Did you use your credentials on that site, so when you went through the OAuth flow with that scope it was authorizing your account to your app, and not that other devs token gen app?

Other things to check is that you’re sending the broadcaster and moderator ID’s correctly in the request, they’re strings not integers. Also it would be helpful for you to log the response body as that will give you a full error.

Thanks @Dist !
Passing the IDs as string and add moderator:read:followers scope fixed it. I get now follower events. :star_struck:
Because the Twitchio lib is handling everything needed for EventSubs I didnt find a way to see the payload of the communication behind. However, its working now.
Also thanks for the warning this was the first try and later I will no more use the 3rd party token generator.

It took me another day to get it to run without the 3rd party Twitchtokengenerator.
Finally:

  • I use the “Authorization code grant flow” to produce the user token with the scopes. This is neccessary only once.
  • As redirect use a localhost address in the ‘Application’ settings in the dev console as mentioned in the documentation.
  • The application uses later the refresh token to get a new token every time it starts connection.
  • I could only get the TwitchIO example above to work if I also add the chat:read scope. Without I could subscribe to the events but couldn’t start the bot. (… Login unsuccessful with token …)
  • With these scopes it works for me:
    moderator:read:followers channel:read:subscriptions chat:edit chat:read

A can’t understand why I need chat:read scope. I dont read any chat messages, I just want to get the channel events and respond with a chat message, thats it.
However, I just can tell: It was not funny to figure this out! I think I generated millions of tokens before it worked :sweat_smile:
Again thanks to every response to my question!

In order to read any responses to a chat send you need to be able to read chat.

So read is requried to write, when connecting via IRC

1 Like