channel/getMembers
Returns the list of Slack user IDs who are members of a given channel. Supports full pagination for large channels. Useful for membership audits, bulk notifications, and HR system synchronization. Requires channels:read scope.
When to Use
- Pre-action membership check: Verify that a specific user is already in a channel before attempting to DM them via a channel-based action — avoids redundant invites.
- Bulk notification targeting: Enumerate all members of a project channel to send personalized direct messages (e.g., sprint reminders or survey invitations).
- HR system synchronization: Compare channel membership against an HR directory to detect employees who have left but still have channel access.
- Sensitive channel audit: Report who has access to channels containing confidential information as part of periodic access reviews.
- Attendance reporting: Generate a list of channel members and cross-reference with event participation records for compliance documentation.
Configuration
Connection
| Field | Type | Required | Description |
|---|---|---|---|
botToken | string | Required | Bot Token starting with xoxb-. Requires channels:read (public) or groups:read (private) scopes. |
Operation Fields
| Field | Type | Required | Description |
|---|---|---|---|
channelId | string | Required | The Slack channel ID (starts with C for public, G for private). |
returnAll | boolean | Optional | When true, paginates through all members. Default: true. |
limit | integer | Optional | Maximum members to return when returnAll is false. Default: 200. |
User IDs only: This operation returns Slack user IDs (e.g.,
U01USER12345), not names or emails. Use user/get or user/getProfile to resolve user details from the returned IDs.
Sample Configuration
{
"operation": "channel/getMembers",
"connection": {
"botToken": "{{credentials.slackBotToken}}"
},
"fields": {
"channelId": "{{$json.channelId}}",
"returnAll": true
}
}
Validation Errors
| Error Code | Cause | Resolution |
|---|---|---|
channel_not_found | The channel ID is invalid or the bot is not a member of the private channel. | Verify the channel ID. For private channels, the bot must be a member. Use channel/join if needed. |
missing_scope | Bot token lacks channels:read or groups:read scope. | Re-authorize the Slack app with the required scopes. |
Output
Success Port
| Field | Type | Description |
|---|---|---|
memberCount | number | Total number of user IDs returned. |
members | array | Array of Slack user ID strings. Example: ["U01USER12345", "U01USER67890"]. |
nextCursor | string | Pagination cursor. Empty when all members have been returned. |
status | string | success or error. |
errorCode | string | Slack error code when status is error. |
payload | object | Full raw Slack API response. |
Error Port
On failure with Continue on Error enabled, routes to the error port with status: "error" and populated errorCode.
Sample Output
{
"memberCount": 4,
"members": [
"U01USER12345",
"U01USER67890",
"U01BOT99999",
"U01USER11111"
],
"nextCursor": "",
"status": "success",
"errorCode": "",
"payload": {
"ok": true,
"members": ["U01USER12345", "U01USER67890", "U01BOT99999", "U01USER11111"],
"response_metadata": { "next_cursor": "" }
}
}
Expression Reference
| Expression | Result |
|---|---|
{{$node["channel-getmembers"].json.memberCount}} | Total members — use in report summaries or capacity calculations. |
{{$node["channel-getmembers"].json.members}} | Full user ID array — iterate with a loop node to process each member. |
{{$node["channel-getmembers"].json.members.includes($json.userId)}} | Boolean — check if a specific user is in the channel. |
{{$node["channel-getmembers"].json.members.filter(id => id !== "U01BOT99999")}} | Exclude the bot's own user ID from the member list before sending DMs. |
{{$node["channel-getmembers"].json.members.length}} | Count of members — equivalent to memberCount. |
Node Policies & GuardRails
| Policy Area | Recommendation |
|---|---|
| Scope requirements | Requires channels:read for public channels and groups:read for private channels. The bot must be a member of private channels. |
| Rate limiting | Tier 2 (20+ req/min). Large channels with 1000+ members will generate multiple paginated requests. Add delays between bulk member processing operations. |
| No hard-coded IDs | Always pass channelId via expressions. Never hard-code channel IDs in node configuration. |
| Bot user filtering | The member list includes the bot's own user ID. Filter it out before sending DMs or notifications to avoid the bot messaging itself. |
| Privacy compliance | Member lists are PII-adjacent data. Log access and restrict downstream processing to authorized workflows. Do not store member lists in public data stores. |
| Rate limit for DM loops | If iterating through members to send DMs, rate-limit to avoid hitting Slack's DM rate limits. Use a Wait node with at least 1-second delays per DM. |
Examples
Example 1 — Check User Membership Before Invite
Before calling channel/invite, verify the user is not already a member to avoid the already_in_channel error.
// Node 1: channel/getMembers
{ "channelId": "{{$json.channelId}}", "returnAll": true }
// IF node:
// {{!$node["channel-getmembers"].json.members.includes($json.userId)}}
// True → channel/invite
// False → skip (user already in channel)
Example 2 — HR Offboarding Access Audit
Compares channel members against an HR "terminated employees" list and flags unauthorized access.
// Node 1: channel/getMembers (sensitive channel)
{ "channelId": "C08CONFIDENTIAL", "returnAll": true }
// Code node:
const members = $node["channel-getmembers"].json.members;
const terminated = $node["hr-terminated"].json.userIds; // from HR system
const unauthorized = members.filter(id => terminated.includes(id));
return { unauthorized, count: unauthorized.length };
// IF: count > 0 → channel/kick for each + alert to security team
Example 3 — Sprint Reminder Broadcast
Gets all project channel members and sends a personalized DM reminder to each (excluding the bot).
// Node 1: channel/getMembers
{ "channelId": "C08SPRINT01", "returnAll": true }
// Code node: filter out bot
const botId = "U01BOT99999";
return $node["channel-getmembers"].json.members
.filter(id => id !== botId)
.map(userId => ({ userId }));
// SplitInBatches → channel/open (DM) → message/send per user