tmi.js bot messages display as broadcaster account despite correct token/scopes/moderator status

Bot account (hroth_bot) sends chat messages via tmi.js to my own channel (hrothgar_gaming), where it has Moderator status (not Editor). Messages display in chat — both the official website and the official mobile app — under the broadcaster’s name/badges instead of the bot’s, even though:

  • https://id.twitch.tv/oauth2/validate confirms the token belongs to hroth_bot (login: hroth_bot), with correct client_id (my own registered app, not a shared one)

  • Scopes: chat:edit, chat:read, moderator:read:chatters

  • Server log confirms Connected to irc-ws.chat.twitch.tv:443 as hroth_bot

  • Application-level logging confirms the exact outgoing message text and intended sender before the client.say() call

  • Verified with only one active connection (killed all duplicate Node processes)

  • Verified with no other bot/tool (Firebot, StreamElements, Nightbot, WarpWorldBot) connected during testing

  • Reproduced from a third-party test account, ruling out “viewing own chat” as a cause

  • Confirmed via two independent clients (twitch.tv website and Twitch mobile app) — same misattribution on both

This started after regenerating the bot’s OAuth token partway through development (same account, same custom Client ID, just a new token). The very first token generated for this bot worked correctly before regeneration.

Then the token you “regenerated” is for hrothgar_gaming not hroth_bot, which suggests a full reauth was done not, say, a “use the refresh token to get a new token”

Take the token and use the validation endpoint or a token tester such as mine Token Checker | Twitch API Example to test the user/userID in the token.

You’ll find when you regenerated the token you did it as the channel not the bot user in error.

Adding force_verify to the oAuth entry might help here to prevent (re)authing the wrong, and/or disconnecting your App from your channel account via settings/connections. Since here you at some point granted chat scope, to your app from yout channel account.

Since IRC will ignore the username during login, additionally consider using eventsub instead as that will explicitly bounce if doing pure websockets and the token/user do not match/permissions are missing. Where IRC is more “forgiving” and only cares about the token.

Or send chat via the API where you verbosely say “send as this user”

This suggests the wrong token was tested (ie the first one and not the regenerated one). Since you connected and starting sending as the wrong user.

So best solve here is to unauth on settings/connections and force verify and on regenerate check you are regenerating the right account using force_verify on the oAuth entry point

Well nightbot can/will only ever send as nightbot it doesn’t offer a bring your own bot name here.

You might have been caught out by AI here making a mistake.

You can’t check the “intended sender” under TMI.js here, since client.say just goes “fire it over the socket” theres no “I’m authed as x” there.

off hand I forgot what the server says when you fire off the wrong token and/or what tmi.js intrepretes the messaging as. These days I’m all eventsub.

Check the docs for the oAuth method used: to add force_verify to help prevent cross talk Getting OAuth Access Tokens | Twitch Developers and check which account is authing.

It’s easy when regenerating implicit tokens to breeze thru and auth the wrong account if/when using a browser that isn’t authed to Twitch as your bot account.

So check for that or use something less cross talky like EventSub with send chat instead of IRC.