Below is a general guide on how to use and run these two scripts, ExportThreadWithoutReplies.py and ExportReplies.py. Both scripts interact with the Slack API to retrieve data from a specific Slack channel, but each focuses on different parts of the conversation.
Create a config.json file in the same directory as the scripts with the following format:
{
"SLACK_TOKEN": "xoxb-1234-...",
"SLACK_COOKIE": "YourCookieStringHere",
"CHANNEL_ID": "CXXXXXX"
}-
Channel ID
- Open Slack (the web version) and navigate to the channel you’re interested in.
- Look at the URL in your browser, for example:
The part after
https://app.slack.com/client/TXXXXXX/CYYYYYYY/client/andTXXXXXX/isCYYYYYYY. That’s the Channel ID. - Alternatively, if you see a link in the form
https://slack.com/app_redirect?channel=CYYYYYYY, thenCYYYYYYYis the Channel ID.
-
Slack Token and Cookie
- Open your browser’s Developer Tools → Network tab.
- Navigate (or refresh) the Slack channel to see all network requests.
- Look for a request containing
conversations.historyor any Slack API endpoint. - Right-click on the request → Copy as cURL.
- Paste the cURL command into Postman or a text editor to inspect its headers.
- In the headers, find
Authorization: Bearer xoxb-...(this is your Slack Token). - Find the
Cookie: ...header value (this is your Slack Cookie). - Copy both into your
config.jsonas shown above.

-
What does it do?
- This script fetches main thread messages (messages with
reply_count > 0, meaning they have replies) from the given Slack channel. - It saves the results in a file named
threads.json.
- This script fetches main thread messages (messages with
-
How to run it:
- Make sure your
config.jsonfile is properly filled in (Token, Cookie, Channel ID). - Open a terminal/command prompt in the same directory as
ExportThreadWithoutReplies.pyand run:python ExportThreadWithoutReplies.py
- The script will connect to Slack and gather all thread-starting messages.
- When finished, you should see a new file called
threads.jsonin your directory.
- Make sure your
-
Output Files:
- threads.json: Contains a list of JSON objects, each representing a main thread message (including
ts,text,reply_count, etc.).
- threads.json: Contains a list of JSON objects, each representing a main thread message (including
-
What does it do?
- This script uses the
threads.jsonfile created by ExportThreadWithoutReplies.py to find each thread’sts(timestamp). - Then, for each thread, it retrieves all replies (the messages inside that thread).
- It stores those replies in
replies.jsonand also keeps track of progress in a file calledprogress.json(so it can resume if interrupted).
- This script uses the
-
How to run it:
- Run it only after you have successfully run
ExportThreadWithoutReplies.py(so you havethreads.json). - In a terminal/command prompt, run:
python ExportReplies.py
- The script loads
threads.json, iterates over each thread, and fetches replies from Slack. - Replies are saved to
replies.json. Progress is logged inprogress.json.
- Run it only after you have successfully run
-
Output Files:
- replies.json: Contains all fetched replies from all threads in the channel.
- progress.json: Tracks the last processed thread index.
- If you re-run the script, it checks
progress.jsonto skip re-fetching. - At the end of a successful run, it may reset to 0 (depending on the version of the script you have) so you can safely export another channel if needed.
- If you re-run the script, it checks
- Configure: Ensure
config.jsonis filled out correctly with your Slack Token, Cookie, and Channel ID. - Run ExportThreadWithoutReplies:
python ExportThreadWithoutReplies.py
- Wait for it to finish.
- Check that
threads.jsonhas been created and contains your thread data.
- Run ExportReplies:
python ExportReplies.py
- This will read
threads.jsonand fetch all replies (per thread). - Check
replies.jsonfor the collected reply data. - If you stop it halfway through, re-run to resume from where it left off.
- This will read
- Check your files:
- threads.json contains the main threads.
- replies.json contains all the replies for those threads.
- Authentication Errors:
- If you receive 401/403 errors or Slack says “invalid_auth”, re-check your Slack Token and Cookie in
config.json.
- If you receive 401/403 errors or Slack says “invalid_auth”, re-check your Slack Token and Cookie in
- Rate Limits (429):
- The script automatically handles Slack’s rate limiting by waiting when it detects a 429 error. If Slack does not send a
Retry-Afterheader, the script will print a message so you can wait manually.
- The script automatically handles Slack’s rate limiting by waiting when it detects a 429 error. If Slack does not send a
- Missing Data:
- Make sure your Slack user account has the necessary permissions for reading conversation history in that channel.
By following these steps, you’ll export Slack threads (main messages) and all of their replies into JSON files.
- Reads the last processed message’s
tsvalue fromsince_ts.txt. - If the file is missing or empty, pulls the entire history on first run.
- After fetching, writes the highest
tsback tosince_ts.txt. - Ensures each subsequent run only processes newer messages.
- Uses
concurrent.futures.ThreadPoolExecutorto fire up to 10 concurrentchat.getPermalinkcalls for thread-starter messages. - Replies fetching script uses up to 5 parallel workers against
conversations.replies. - Results are sorted by
tsto preserve chronological order.
- On HTTP 429 (rate-limit), reads
Retry-Afterheader and sleeps before retrying. - Applies this logic uniformly across
conversations.history,chat.getPermalinkandconversations.repliesendpoints. - Prevents hard failures on large channels or big threads.
- Replies script records “last processed index” in
progress.jsonafter each thread. - On restart, resumes from that index—no need to re-fetch already handled threads.
- Once all threads are done,
progress.jsonresets to zero for the next full export.
- Threads:
threads.json(full JSON dump)- Optional:
threads.csvfor spreadsheet-friendly output
- Replies:
replies.json(accumulated thread replies)
- Tracker Files:
since_ts.txt(lasttscheckpoint)progress.json(reply-fetch index)
-
First Run:
since_ts.txtis empty or missing → fetch all threads viaconversations.history.- Write the newest
tsintosince_ts.txt.
-
Subsequent Runs:
- Read
since_ts→ fetch only threads newer than that value. - Replies script picks up from its
progress.jsoncheckpoint.
- Read
-
Inspecting Results:
- Use
threads.json&replies.jsonto see a fully chronological export of all threads and their replies.
- Use