Back to Blog
Guide

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.

Slack Green Team
October 2, 2026
October 2, 2026
3 min read
Share:
slack api
developers
tokens

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

Tokenas_userResultPosted as
bot (xoxb-)not sentokthe bot
bottrue, 1, yes or Trueokthe bot, same as not sent
botfalse, 0 or Falseinvalid_arguments, deprecated_argument: as_usernothing posted
botJSON body "as_user": falseinvalid_argumentsnothing posted
user (xoxp-)not sentokthe person
usertrueokthe person, same as not sent
userfalseinvalid_argumentsnothing 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:

Slack web: two messages from

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:write under User Token Scopes in the app's OAuth settings (or under oauth_config.scopes.user in 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.postMessage with that xoxp- token and no as_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.

Always Active

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

Guide

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 Green Team
Guide

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 Green Team
Guide

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.

Slack Green Team