Slack RTM API Deprecated: What rtm.connect Returns for a New App, and the Socket Mode Fix
A Slack app created today cannot use the RTM API. We called rtm.connect and rtm.start with every token a new app gets on 2 October 2026, tried to request the rtm:stream scope, and ran the same bot over Socket Mode.
On this page
A Slack app created today cannot use the RTM API. With its bot token, rtm.connect and rtm.start return not_allowed_token_type. With its user token they return missing_scope for rtm:stream, a scope a new app is not allowed to request. RTM only works with tokens from classic apps, and Slack stopped letting anyone create classic apps on 4 June 2024. The replacement is Socket Mode: the same kind of WebSocket connection, opened with an app-level xapp- token.
We checked all of this on 2 October 2026 with throwaway apps in a test workspace. Every error below is a response we got.
rtm.connect and rtm.start with each token
curl -s -X POST https://slack.com/api/rtm.connect -H "Authorization: Bearer $TOKEN"
| Token | rtm.connect | rtm.start |
|---|---|---|
Bot token, xoxb- | not_allowed_token_type | not_allowed_token_type |
User token, xoxp- | missing_scope, needed rtm:stream | missing_scope, needed rtm:stream |
App-level token, xapp- | not_allowed_token_type | not_allowed_token_type |
| No token | not_authed | not tried |
The user token response in full:
{
"ok": false,
"error": "missing_scope",
"needed": "rtm:stream",
"provided": "identify,channels:read,groups:read,chat:write"
}
The bot token one has no hint at all:
{"ok": false, "error": "not_allowed_token_type"}
not_allowed_token_type on an rtm.* call means the token comes from a modern app. No scope fixes it.
A new app cannot request rtm:stream
The missing_scope error suggests adding rtm:stream, so we tried. Adding it as a user scope through apps.manifest.update was refused:
{
"ok": false,
"error": "invalid_manifest",
"errors": [
{
"code": "illegal_user_scopes",
"message": "Illegal user scopes found `rtm:stream`",
"pointer": "/oauth_config/scopes/user"
}
]
}
As a bot scope it failed with illegal_bot_scopes, "Illegal bot scopes found rtm:stream". The old umbrella scope bot, which is what gave classic bots RTM access, failed the same way: "Illegal bot scopes found bot".
We also tried the old v1 install URL, https://slack.com/oauth/authorize?scope=bot&client_id=..., with a new app's client ID. Slack still showed a consent screen. After we clicked Allow, exchanging the code with the old oauth.access method returned {"ok": false, "error": "internal_error"}, and a fresh code exchanged with oauth.v2.access returned {"ok": false, "error": "oauth_authorization_url_mismatch"}. That path gives no token at all.
Never appear "away" on Slack again
Cloud-based. No downloads. Works 24/7 even when your laptop is off.
Classic apps can no longer be created
The old creation link, https://api.slack.com/apps?new_classic_app=1, now opens this dialog. Create App is greyed out:
If you still run an RTM bot, it is a classic app with a classic token. This dialog means you cannot create another one, for a new workspace, a staging copy or a fork. Plan the move before you need one.
The replacement: Socket Mode
Socket Mode keeps the part people liked about RTM: no public URL, events over a WebSocket. Turn it on under Settings, Socket Mode (or "socket_mode_enabled": true in the manifest), subscribe to the events you want, and create an app-level token with the connections:write scope on Basic Information. That xapp- token opens the connection:
{"ok": true, "url": "wss://wss-primary.slack.com/link/?ticket=<cut>"}
That is apps.connections.open. With the bot token instead, it returned not_allowed_token_type, the mirror of the RTM error. You almost never call it yourself; Bolt does. In Bolt for JavaScript 5 that connection no longer takes an agent option; our v5 upgrade log shows the replacement. This is the "reply to hello" bot an RTM tutorial would build, as a Bolt app:
import os, json, logging
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)s %(message)s")
app = App(token=os.environ["SLACK_BOT_TOKEN"])
@app.middleware
def log_payload(body, next):
with open("events.jsonl", "a") as f:
f.write(json.dumps(body) + "\n")
next()
@app.message("hello")
def reply_hello(message, say):
say(f"Hi <@{message['user']}>, this reply came over Socket Mode.")
@app.event("app_mention")
def on_mention(event, logger):
logger.info("app_mention from %s in %s", event["user"], event["channel"])
@app.event("message")
def other_messages(logger):
pass
if __name__ == "__main__":
SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()
Our app had the bot scopes chat:write, channels:history and app_mentions:read, the bot events message.channels and app_mention, and the bot was a member of the channel. The log from our run:
2026-10-02 10:23:34,521 slack_bolt.App A new session has been established (session id: 47c23c75-f6a0-470a-84aa-60c8b512d609)
2026-10-02 10:23:34,521 slack_bolt.App ⚡️ Bolt app is running!
2026-10-02 10:23:34,568 slack_bolt.App Starting to receive messages from a new connection (session id: 47c23c75-f6a0-470a-84aa-60c8b512d609)
2026-10-02 10:23:45,204 socket_bot.py:on_mention app_mention from U0B7L4YK420 in C0C6ZRH1Z8Q
We typed hello in a test channel. The reply's timestamp was 0.61 seconds after ours:
The bot did not answer its own reply, so there was no loop. Bolt skips events from the app's own bot user by default.
RTM vs Socket Mode
| RTM | Socket Mode | |
|---|---|---|
| Token that opens the socket | classic token with rtm:stream | xapp- with connections:write |
| Method | rtm.connect (rtm.start is the older one) | apps.connections.open |
| What arrives | the RTM event stream | only the events you subscribe to in app settings |
| Can a new app use it | no: not_allowed_token_type, and rtm:stream is an illegal scope | yes |
For the full setup with the token errors you can hit along the way, see Slack Socket Mode in Python. Token prefixes are explained in Slack bot tokens.
Stop Jiggling Your Mouse.
Join hundreds of remote workers who never worry about their Slack status. Set it up once, stay green forever.
Related Articles
Slack Bot Scopes: The Scope Each API Method Needs, Measured on 44 Methods
We gave a Slack bot one scope, called 44 common Web API methods, and read the needed field of every missing_scope error. Then we added the scopes and called them again. The table shows which scope clears each method.
Slack File Size Limit: 1 GB Is Exactly 1,073,741,824 Bytes, Tested
We uploaded files of 50 MB, exactly 1 GiB and 1 GiB plus one byte to Slack through its upload API. The limit is 1,073,741,824 bytes, and a failed upload can still leave a broken file behind.
Slack Dark Mode: Where the Setting Is, and Which Custom Emoji Disappear
Slack's dark mode is under Preferences > Appearance > Color Mode, with Light, Dark and System. We switched modes in Slack web with three test emoji and measured which ones vanish.