Slack as_user: What It Does Now, Tested With Bot and User Tokens
We sent chat.postMessage with as_user=true, as_user=false and no as_user, with a bot token and a user token. as_user=true changed nothing, as_user=false was rejected, and only the user token posted under the person's name.
On this page
as_user is a chat.postMessage argument from Slack's older bot model. With today's tokens it no longer decides who posts: the token does. On 2 October 2026 we sent messages with as_user=true, as_user=false and no as_user from a bot token and from a user token in our own test workspace. as_user=true was accepted and changed nothing. as_user=false was rejected with invalid_arguments. A bot token always posted as the bot, and a user token always posted as the person.
The test
We ran this with slack_sdk 3.45.0. The app had chat:write as a bot scope and as a user scope, so the install gave us both tokens:
import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
CHANNEL = os.environ["CHANNEL_ID"]
tokens = {"bot": os.environ["SLACK_BOT_TOKEN"], "user": os.environ["SLACK_USER_TOKEN"]}
for name, token in tokens.items():
client = WebClient(token=token)
for as_user in (None, True, False):
kwargs = {} if as_user is None else {"as_user": as_user}
try:
r = client.chat_postMessage(channel=CHANNEL, text=f"{name} token, as_user={as_user}", **kwargs)
m = r["message"]
print(f"{name:4} as_user={str(as_user):5} ok user={m['user']} bot_id={m.get('bot_id')} ts={r['ts']}")
except SlackApiError as e:
d = e.response.data
print(f"{name:4} as_user={str(as_user):5} {d['error']} deprecated_argument={d.get('deprecated_argument')}")
Output:
bot as_user=None ok user=U0C695L6YVA bot_id=B0C5Q3X48EB ts=1790905019.690349
bot as_user=True ok user=U0C695L6YVA bot_id=B0C5Q3X48EB ts=1790905020.016449
bot as_user=False invalid_arguments deprecated_argument=as_user
user as_user=None ok user=U0B7L4YK420 bot_id=B0C695KUBJ8 ts=1790905020.654209
user as_user=True ok user=U0B7L4YK420 bot_id=B0C695KUBJ8 ts=1790905021.996629
user as_user=False invalid_arguments deprecated_argument=as_user
The full response for as_user=false was:
{"ok": false, "error": "invalid_arguments", "deprecated_argument": "as_user"}
What each combination did
| Token | as_user | Result | Posted as |
|---|---|---|---|
bot (xoxb-) | not sent | ok | the bot |
| bot | true, 1, yes or True | ok | the bot, same as not sent |
| bot | false, 0 or False | invalid_arguments, deprecated_argument: as_user | nothing posted |
| bot | JSON body "as_user": false | invalid_arguments | nothing posted |
user (xoxp-) | not sent | ok | the person |
| user | true | ok | the person, same as not sent |
| user | false | invalid_arguments | nothing posted |
The other methods we tried with a bot token behaved the same way: chat.update and chat.postEphemeral accepted as_user=true and rejected as_user=false with the same error, chat.scheduleMessage accepted as_user=true, and chat.delete rejected as_user=false. If old code passes as_user=False to be explicit, delete the argument.
This is how Slack web showed the messages:
Both bot messages look the same, with the bot's display name and the APP label. The user-token message shows the person's name and avatar with no label. In the API it is not anonymous, though: the message carries bot_id B0C695KUBJ8 and the app's app_id, so anyone reading the raw message can tell an app sent it. The bot's own messages carry a different bot_id, B0C5Q3X48EB.
Never appear "away" on Slack again
Cloud-based. No downloads. Works 24/7 even when your laptop is off.
Posting as a user
To post as a person, use that person's user token:
- Add
chat:writeunder User Token Scopes in the app's OAuth settings (or underoauth_config.scopes.userin the app manifest). - The person installs or reinstalls the app. Each person who should post through the app has to authorize it themselves; the install response puts their token in
authed_user.access_token. Our oauth.v2.access walkthrough shows that response. - Call
chat.postMessagewith thatxoxp-token and noas_user.
A bot token cannot post as a person, with or without as_user. The bot token page explains which token types exist.
About as_user_not_supported
Slack's docs list as_user_not_supported for chat.postMessage and describe it as the as_user parameter not working with workspace apps, an app type Slack retired. We did not get it with a bot token or a user token: every as_user=false returned invalid_arguments with deprecated_argument, and every as_user=true was ignored. If you see as_user_not_supported from an old integration, remove as_user from the call and check which kind of token it sends.
FAQ
Does as_user=true make a bot message look like it came from me?
No. In our test it posted under the bot's name with the APP label, exactly like a call without as_user.
Can an admin see that a message was sent through the API with a user token?
The message object shows bot_id and app_id, so anything that reads the raw message can. Slack web showed no label on it in our test.
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 API Pagination: next_cursor, the Last Page and invalid_cursor, Tested
Slack paginates list methods with a cursor: pass response_metadata.next_cursor back as cursor until it is empty. We paged 27 real messages on 2 October 2026 and broke the cursor five ways to see which ones fail.
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.
Slack Bot Icon and Name Per Message: icon_emoji, icon_url and username, Tested
icon_emoji, icon_url and username only work with the chat:write.customize scope, and Slack ignores them silently without it. We tested every case on 2 October 2026, plus webhooks and the app icon upload limits.