TwurpleAuthenticationGetting dataExamplesFAQMigration

Migration from v5 to v6

Make sure your Node version is new enough

We don't test on Node versions below 16 anymore, so make sure you are running a supported Node version.

Replace the @twurple/eventsub package with @twurple/eventsub-http

There have mostly just been naming changes here. Replace the package and update your imports.

A few classes and interfaces now additionally have Http in their names:


Additionally, please use .start() instead of .listen() and .stop() instead of .unlisten(). The respective deprecated counterparts have been removed.

Update all packages to the same version

Make sure that all Twurple packages are up-to-date and on the same version.

On a unix-like system with the jq utility installed, you can use one of these handy one-liners for that:

# for yarn
jq -r '.dependencies | keys[] | select(. | startswith("@twurple/"))' package.json | xargs yarn add
# for npm
jq -r '.dependencies | keys[] | select(. | startswith("@twurple/"))' package.json | xargs printf '%s@latest\n' | xargs npm install --save

Update any AuthProvider usage

The AuthProvider interface and its implementations have been completely reworked. Now, instead of creating an AuthProvider and ApiClient for each of your users and your app separately, you can manage all your users using just one of each.


You can just use the addUserForToken method to add your users to the provider. It will also take care of app tokens using the supplied client ID and secret.

const authProvider = new RefreshingAuthProvider(
		onRefresh: async (newTokenData) => await fs.writeFile(`./tokens.json`, JSON.stringify(newTokenData, null, 4), 'UTF-8'),
		onRefresh: async (userId, newTokenData) => await fs.writeFile(`./tokens.${userId}.json`, JSON.stringify(newTokenData, null, 4), 'UTF-8'),

await authProvider.addUserForToken(tokenData);

Alternatively, if you already know the ID of the user you're adding, you can use addUser instead as a minor optimization:

authProvider.addUser('125328655', tokenData);


The ClientCredentialsAuthProvider has been renamed to AppTokenAuthProvider to reflect its outcome better. Anything using it will, as before, only support calling APIs using app tokens, not representing any user.


There have been no changes, as a static token can only represent one user.


In your chat clients, the account to connect with is determined using the chat intent by default. The required intent can be configured using the authIntents option.

Now you might be asking, what are intents?


You can set intents on every user in an auth provider. A user can have more than one intent, but an intent can only be used for one user.

To use them with the RefreshingAuthProvider, just add another parameter to addUser or addUserForToken:

await authProvider.addUserForToken(tokenData, ['chat']);

You can also add intents to a user after the fact:

authProvider.addIntentsToUser('125328655', ['chat']);

Custom AuthProvider implementations

If you wrote your own provider, please refer to the AuthProvider reference page to reimplement it from scratch. There is no straightforward migration strategy here.

Update API calls that now require a broadcaster ID to determine the token to use

In order for the ApiClient to properly determine the user to execute requests as, a few methods now require you to additionally pass a user to them:

UsersHelixUserApi#getAuthenticatedUser (renamed from getMe)
UsersHelixUserApi#updateAuthenticatedUser (renamed from updateUser)
UsersHelixUserApi#updateAuthenticatedUser (renamed from updateUser)
UsersHelixUserApi#getExtensionsForAuthenticatedUser (renamed from getMyExtensions)
UsersHelixUserApi#updateActiveExtensionsForAuthenticatedUser (renamed from updateMyActiveExtensions)

Make sure that not too many of your calls use the app token

Now that authentication works on a basic level, you should probably read the page on choosing the correct user for your requests.

The methods listed there should probably use a user context override (as documented on the bottom of that page) whenever possible, otherwise you might quickly exhaust the rate limit for your app token.

Rename subscription methods in EventSub packages

In the eventsub-http and eventsub-ws packages, the naming convention for the subscription methods has been changed.

Now, instead of starting with subscribeTo and ending in Events, the subscription methods start with on and dropped the suffix. For example, subscribeToChannelUpdateEvents was renamed to onChannelUpdate.

The respective API calls are not affected by this change.

Use synchronous EventSubMiddleware#apply

Historically, the apply method did some async operations. Now it doesn't anymore, so we got rid of the pretty much useless async attribute, which means that the function does not return a Promise anymore.

You may need to adapt your Promise based code due to this.

Listen to more failure events

A lot of the APIs relating to persistent connections (chat, pubsub, eventsub-ws) or at least pose as if they were (eventsub-http) were updated from a Promise based API to a more event based API. This means that instead of having the promises reject (possibly fatally), there are now events that report these failures.

Old rejecting methodNew event

Configure a port for your EventSub & ngrok development setup

Previously, the NgrokAdapter would find a port to listen on using the portfinder package. This behavior was removed. Instead, you can configure the port you want now.

If you want the old behavior back, use the portfinder package directly.

Switch from the old badges API

There were two different badges APIs, one of which (apiClient.badges) is obsolete now. Please use the very similar methods within HelixChatApi instead.

Switch from the old chatters API

Similarly, there was a chatters API available under the apiClient.unsupported namespace. This was now removed in favor of the new Helix API under HelixChatApi#getChatters.

Switch chat actions to the Helix API

All chat actions other than ones relating to sending messages (like banning, changing sub/follower only mode etc.) were removed by Twitch. You need to switch to the respective Helix APIs instead.

Most of them are in HelixChatApi or HelixModerationApi.

Create bans & clips: update request body

When creating bans & clips, the banned user / the channel to create the clip in could always have been a user ID or a user object, just like in most places in the library. The parameter names were updated to reflect that. So instead of giving a userId to ban, you now give a user (which can still be an ID). Similarly, replace the channelId for the clip with just channel.

Adapt for additional minor renames and removes

There's not that much to say about these (most were just to align more to the documentation or for consistency), so I'll just list them:

HelixBanUser#broadcasterIdremoved (you needed this ID for fetching anyway)
HelixUser#viewsremoved (removed by Twitch)

Make sure your EventSub HTTP host name configuration is correct (or configure the listener accordingly)

The strictHostCheck configuration option now defaults to being on. This means that requests that go to the wrong host name but still reach the listener (for example wide-range port scanners) will automatically be filtered. In some cases, this can filter out legitimate requests, for example with a misconfigured reverse proxy.

While we recommend you to fix your reverse proxy (or any other part of your setup) instead, you may disable this behavior explicitly by setting strictHostCheck: false in the constructor options.

Clear your EventSub HTTP subscriptions (or opt to do it a bit later)

In the past, your EventSub secret was augmented with an internal ID for each subscription in order to create different secrets for different subscriptions. This is pretty much unnecessary and in some cases may even reduce entropy.

This behavior is now disabled by default, which means you have to delete all subscriptions and re-subscribe to them.

Alternatively, you can set legacySecrets: true in the constructor options to postpone this, but be aware that this flag will go away in the next major release of Twurple.