| name | searching-slack-history |
| description | Use when needing to search Slack message history, find past conversations, or retrieve channel messages - provides Slack Web API patterns for search.messages and conversations.history endpoints using WebFetch or curl |
Searching Slack History
Overview
Search Slack message history using the Slack Web API.
Core principle: Use Slack's REST API endpoints with WebFetch or curl to search messages, retrieve channel history, and find past conversations.
Prerequisites: Slack Bot token with appropriate scopes (setup guide below)
Setup Guide (One-Time)
Creating a Slack Bot Token
- Visit https://api.slack.com/apps → Click "Create New App"
- Choose "From scratch"
- Name it (e.g., "Claude Search Bot")
- Select your workspace
- Navigate to "OAuth & Permissions" in sidebar
- Scroll to "Scopes" → "Bot Token Scopes"
- Add these scopes:
search:read- Search messages across workspacechannels:history- Read public channel historychannels:read- List public channelsgroups:history- Read private channel history (if needed)groups:read- List private channels (if needed)
- Click "Install to Workspace" at top of page
- Authorize the app
- Copy the "Bot User OAuth Token" (starts with
xoxb-) - Store securely as environment variable:
export SLACK_TOKEN="xoxb-your-token-here"
Security: Never commit tokens to git. Use environment variables or secure credential storage.
Private channels: Bot must be invited to private channels before it can search them (/invite @YourBotName).
Quick Reference
| Task | Endpoint | Key Parameters |
|---|---|---|
| Search all messages | search.messages |
query, sort, count |
| Get channel history | conversations.history |
channel, limit, oldest |
| Find channel ID | conversations.list |
types, exclude_archived |
| Search by date range | search.messages |
query with date operators |
API Patterns
Security Note: Never echo commands containing tokens. Use silent execution to prevent token exposure in terminal output.
Search Messages Globally
Endpoint: POST https://slack.com/api/search.messages
Use case: Find messages across all channels the bot has access to.
Secure pattern (use this):
# Create curl command without echoing it
cat > /tmp/slack_search.sh << 'SCRIPT'
curl -s -X POST https://slack.com/api/search.messages \
-H "Authorization: Bearer $SLACK_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "your search terms",
"count": 20,
"sort": "timestamp"
}'
SCRIPT
# Execute without showing token in terminal
bash /tmp/slack_search.sh
rm /tmp/slack_search.sh
Alternative secure pattern:
# Use curl config file (doesn't appear in terminal/history)
cat > /tmp/slack.curl << EOF
header = "Authorization: Bearer $SLACK_TOKEN"
header = "Content-Type: application/json"
EOF
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/search.messages \
-d '{"query": "your search terms", "count": 20, "sort": "timestamp"}'
rm /tmp/slack.curl
Query operators:
"exact phrase"- Match exact phrasefrom:@username- Messages from specific userin:#channel- Messages in specific channelafter:YYYY-MM-DD- Messages after datebefore:YYYY-MM-DD- Messages before date
Example with operators:
{
"query": "deployment after:2025-01-01 in:#engineering",
"count": 50
}
Rate limit: Tier 3 (20 requests/minute)
Get Channel History
Endpoint: POST https://slack.com/api/conversations.history
Use case: Retrieve recent messages from a specific channel.
Important: Requires channel ID, not channel name. Use conversations.list first if you only have the name.
Secure pattern:
# Use config file to hide token
cat > /tmp/slack.curl << EOF
header = "Authorization: Bearer $SLACK_TOKEN"
header = "Content-Type: application/json"
EOF
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/conversations.history \
-d '{"channel": "C1234567890", "limit": 100}'
rm /tmp/slack.curl
Time filtering:
{
"channel": "C1234567890",
"oldest": "1609459200.000000",
"latest": "1640995200.000000",
"limit": 100
}
Timestamps are Unix epoch time with microseconds (e.g., 1609459200.000000 = 2021-01-01).
Find Channel ID from Name
Endpoint: POST https://slack.com/api/conversations.list
Use case: Get channel ID when you only know the channel name.
Secure pattern:
cat > /tmp/slack.curl << EOF
header = "Authorization: Bearer $SLACK_TOKEN"
header = "Content-Type: application/json"
EOF
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/conversations.list \
-d '{"types": "public_channel,private_channel", "exclude_archived": true}'
rm /tmp/slack.curl
Filter response: Look for channel with matching name field, extract id.
Handling Pagination
All endpoints return paginated results. Check for response_metadata.next_cursor:
# Create reusable config (do this once)
cat > /tmp/slack.curl << EOF
header = "Authorization: Bearer $SLACK_TOKEN"
header = "Content-Type: application/json"
EOF
# First request
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/search.messages \
-d '{"query": "search", "cursor": ""}'
# If response contains "next_cursor": "dXNlcjpVMDYxTkZUVDI="
# Second request with cursor
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/search.messages \
-d '{"query": "search", "cursor": "dXNlcjpVMDYxTkZUVDI="}'
# Clean up when done
rm /tmp/slack.curl
Continue until next_cursor is empty or not present.
Common Mistakes
1. Missing Token Scopes
Symptom: {"ok": false, "error": "missing_scope"}
Fix: Add required scopes in Slack App OAuth settings, then reinstall app to workspace.
2. Using Channel Names Instead of IDs
Symptom: {"ok": false, "error": "channel_not_found"}
Fix: Call conversations.list first to map channel name → ID.
3. Ignoring Pagination
Symptom: Only getting first 20-100 results, missing older messages.
Fix: Check for response_metadata.next_cursor and make subsequent requests with cursor parameter.
4. Rate Limit Errors
Symptom: {"ok": false, "error": "rate_limited"} or HTTP 429
Fix: Implement exponential backoff. Wait time often provided in Retry-After header.
5. Private Channel Access
Symptom: Empty results or permission errors for private channels.
Fix:
- Add
groups:historyandgroups:readscopes - Invite bot to private channel:
/invite @YourBotName
6. Token Exposure in Terminal
Risk: Running curl with -H "Authorization: Bearer $SLACK_TOKEN" displays token in terminal output and shell history.
Fix:
- ALWAYS use curl config files (
-K /tmp/slack.curl) to hide token - Create config file with headers, run curl referencing it, delete config after
- Never echo commands containing
$SLACK_TOKEN - Add
.envto.gitignoreif storing tokens in files - Rotate token immediately if exposed in logs or history
Response Format
Successful responses have "ok": true:
{
"ok": true,
"messages": {
"matches": [
{
"type": "message",
"user": "U1234567890",
"text": "Message content",
"ts": "1234567890.123456",
"permalink": "https://workspace.slack.com/archives/...",
"channel": {
"id": "C1234567890",
"name": "general"
}
}
],
"total": 150
},
"response_metadata": {
"next_cursor": "dXNlcjpVMDYxTkZUVDI="
}
}
Error responses have "ok": false:
{
"ok": false,
"error": "invalid_auth"
}
Real-World Workflow
Scenario: Find all messages about "deployment" in #engineering from last week.
# 1. Create secure config file
cat > /tmp/slack.curl << EOF
header = "Authorization: Bearer $SLACK_TOKEN"
header = "Content-Type: application/json"
EOF
# 2. Get channel ID (pipe to jq to extract)
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/conversations.list \
-d '{"types": "public_channel"}' \
| jq -r '.channels[] | select(.name=="engineering") | .id'
# Returns: C1234567890
# 3. Search messages with date filter
curl -s -K /tmp/slack.curl -X POST https://slack.com/api/search.messages \
-d '{
"query": "deployment in:#engineering after:2025-10-24",
"count": 100,
"sort": "timestamp"
}'
# 4. Clean up config file
rm /tmp/slack.curl
Further Reading
- Slack Web API Documentation: https://api.slack.com/web
- search.messages: https://api.slack.com/methods/search.messages
- conversations.history: https://api.slack.com/methods/conversations.history
- OAuth Scopes Reference: https://api.slack.com/scopes