Back to Blog
Guide

Set a Slack Status With the API: users.profile.set, With Code

To set a Slack status through the API, call users.profile.set with a user token that has users.profile:write and a profile containing status_text, status_emoji and status_expiration. Curl and Python examples, how to read and clear a status, and why a bot token cannot set yours.

Slack Green Team
September 23, 2026
October 7, 2026
3 min read
Share:
slack api
slack status
developers

To set a Slack status with the API, call users.profile.set with a user token that has the users.profile:write scope, and send a profile object with status_text, status_emoji and, optionally, status_expiration as a Unix timestamp. Slack's developer docs say status text holds up to 100 characters without formatting (a URL in it stays plain text, as our link in Slack status test shows), the emoji must be installed in the workspace, and an expiration of 0 means the status never clears. To clear a status, set both text and emoji to empty strings. Bot users have no profile, so a bot token cannot set your status; admins on paid plans can set another user's status by passing user.

Status is the emoji and text. Your green or grey dot is presence, a separate API with different rules: users.setPresence takes only auto or away.

Slack status fields

FieldTypeRules
status_textstringUp to 100 characters, no formatting or mentions. 101 returns too_long
status_emojistringAn emoji code in the workspace, such as :palm_tree:
status_expirationintegerUnix time when it clears; 0 means never

Set your status with curl

Use a user token (xoxp-) with users.profile:write:

curl -s -X POST https://slack.com/api/users.profile.set \
  -H "Authorization: Bearer $SLACK_USER_TOKEN" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{"profile": {"status_text": "Focus time", "status_emoji": ":headphones:", "status_expiration": 0}}'

Slack recommends JSON; with a form-encoded POST, profile must be a URL-encoded JSON string.

We checked the length rule on 7 October 2026 in our test workspace. A 100-character status_text was saved in full; 101 characters came back as an error:

{"ok": false, "error": "too_long"}

The status that Slack's own Set a status dialog saves with Duration: Today read back through users.profile.get with "status_expiration": 1791385199, which is 23:59:59 on that day in the profile's time zone (Asia/Seoul). To copy that from code, compute the end of the day in the user's tz from users.info, not in UTC.

To clear it:

curl -s -X POST https://slack.com/api/users.profile.set \
  -H "Authorization: Bearer $SLACK_USER_TOKEN" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{"profile": {"status_text": "", "status_emoji": ""}}'

Set a status that expires, in Python

import os, time
from slack_sdk import WebClient

client = WebClient(token=os.environ["SLACK_USER_TOKEN"])

# "In a meeting" for the next 45 minutes
client.users_profile_set(profile={
    "status_text": "In a meeting",
    "status_emoji": ":calendar:",
    "status_expiration": int(time.time()) + 45 * 60,
})

Wire this to a calendar or a cron job to build your own status automation; our automatic Slack status guide times three macOS triggers, and Apple Shortcuts can send the same request. Slack's Google Calendar and Outlook apps already do it for meetings; see sync Slack status with Google Calendar. To copy your Microsoft Teams presence into your Slack status, see how to connect Slack and Teams.

Never appear "away" on Slack again

Cloud-based. No downloads. Works 24/7 even when your laptop is off.

Read a user's status

profile = client.users_profile_get(user="U0123ABCD")["profile"]
print(profile["status_emoji"], profile["status_text"], profile["status_expiration"])

users.profile.get needs users.profile:read. Profiles returned by users.list and users.info also include status, with users:read. To be told when a status changes, subscribe to user_change in the Events API.

To hear about a change instead of polling, an app can subscribe to user_status_changed, which reached our test app in under a second on Slack status change notification.

Which method and scope to use

TaskMethodScope
Set your own statususers.profile.setusers.profile:write (user token)
Set another user's statususers.profile.set with userAdmin on a paid team
Read one statususers.profile.getusers.profile:read
Read everyone'susers.listusers:read
Status changesuser_change eventEvents API
Set away or autousers.setPresenceusers:write

Getting a user token is covered in Slack bot token: xoxb vs xoxp. Presence methods, fields and rate limits are in our Slack presence API guide.

Set a Slack status from the terminal

Put the curl command in a shell alias or script:

slack_status() {
  curl -s -X POST https://slack.com/api/users.profile.set \
    -H "Authorization: Bearer $SLACK_USER_TOKEN" \
    -H "Content-Type: application/json; charset=utf-8" \
    -d "{\"profile\": {\"status_text\": \"$1\", \"status_emoji\": \"$2\"}}"
}
slack_status "Deploying" ":rocket:"

Keep the token in your keychain or an environment variable, never in the script file. If you installed Slack's own slack command with Homebrew, note that it builds apps and has no status command; what it does is in Slack CLI on Homebrew.

FAQ

How do I set my Slack status with the API?

Call users.profile.set with a user token that has users.profile:write, sending status_text and status_emoji inside profile.

Can a bot set my Slack status?

No. Bots have no profile. Use a user token; admins on paid plans can set other users' statuses.

How do I make an API status expire?

Set status_expiration to a Unix timestamp. 0 means it never clears.

How do I get a user's status with the API?

users.profile.get with users.profile:read, or read profile from users.info.

Can the API set me to active?

No. users.setPresence accepts only auto or away; see script to keep Slack active.

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

Developers

Send a Slack Message From a Cron Job: 4 Failures We Hit and the Fix

A Slack webhook call that works in your terminal often fails from cron. We ran six crontab entries and a launchd agent on a Mac for 10 minutes, logged each failure (empty env var, % in crontab, JSON quoting, macOS privacy block) and the script that posted every minute.

Slack Green Team
Developers

Slack Outgoing Webhooks: Payload, Trigger Words and Timeout, Tested

Slack's legacy Outgoing WebHooks still install on a Free workspace in November 2026. We set one up, sent 15 trigger messages through a tunnel, and logged the exact payload, how trigger words match, which replies Slack posts and when it gives up.

Slack Green Team
Developers

Slack API link_names: What It Still Links, Tested on 20 Messages

Slack's docs say link_names now links only user groups. On November 2, 2026 a bot token with link_names=true still turned @name, #channel and @here into real mentions, in plain text, section blocks and incoming webhooks.

Slack Green Team