Scrape and analyze replies from any public Threads post — right from your AI coding agent.
An MCP server that lets your AI assistant scrape a Threads post URL, then query and analyze the replies — all through natural conversation.
Instead of:
1. Manually open browser
2. Scroll through hundreds of replies
3. Copy-paste into spreadsheet
4. Manually look for patterns
Just say:
"Analyze the replies on this Threads post: https://www.threads.com/@zuck/post/ABC123"
Your AI agent handles the rest.
- Network interception — Captures GraphQL API responses, not fragile CSS selectors that Meta randomizes
- Anti-detection — Randomized scroll delays, stealth browser flags, custom User-Agent
- 4 MCP tools — Scrape, list, search, and get statistics on replies
- Works with any MCP client — Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, and more
| Tool | Description |
|---|---|
scrape_thread(url) |
Scrape all replies from a public Threads post |
get_all_replies() |
Return all scraped replies with username and timestamp |
search_replies(keyword) |
Case-insensitive keyword search across replies |
get_reply_stats() |
Reply count, top commenters, avg length, time range |
- Python 3.13+
- uv package manager
git clone https://github.com/ethan-tsai-tsai/thread-analyzer.git
cd thread-analyzer
uv sync
uv run playwright install chromiumAdd the server to your MCP client config:
{
"mcpServers": {
"thread-analyzer": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/thread-analyzer", "python", "server.py"]
}
}
}Claude Code
Add to your project's .mcp.json:
{
"mcpServers": {
"thread-analyzer": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/thread-analyzer", "python", "server.py"]
}
}
}Or run: claude mcp add thread-analyzer -- uv run --directory /absolute/path/to/thread-analyzer python server.py
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"thread-analyzer": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/thread-analyzer", "python", "server.py"]
}
}
}Cursor
Go to Cursor Settings > MCP > Add new MCP Server, then add:
{
"mcpServers": {
"thread-analyzer": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/thread-analyzer", "python", "server.py"]
}
}
}VS Code (Copilot)
Add to .vscode/mcp.json in your workspace:
{
"servers": {
"thread-analyzer": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/thread-analyzer", "python", "server.py"]
}
}
}Windsurf
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"thread-analyzer": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/thread-analyzer", "python", "server.py"]
}
}
}You can also use the scraper directly without MCP:
uv run python scraper.py "https://www.threads.com/@user/post/XXXXX"
# Options
uv run python scraper.py "URL" --output custom.csv --max-scrolls 50┌─────────────┐ MCP (stdio) ┌──────────────┐ Playwright ┌─────────────┐
│ AI Client │ ◄──────────────────► │ server.py │ ◄──────────────► │ Threads.com │
│ (Claude, │ scrape_thread() │ (FastMCP) │ GraphQL API │ (Meta) │
│ Cursor...) │ get_all_replies() │ │ interception │ │
│ │ search_replies() │ replies.csv │ │ │
│ │ get_reply_stats() │ │ │ │
└─────────────┘ └──────────────┘ └─────────────┘
- You give your AI assistant a Threads post URL
- AI calls
scrape_thread(url)via MCP - Server launches headless Chromium, navigates to the post
- Playwright intercepts GraphQL network responses containing reply data
- Server parses replies (username, text, timestamp), saves to CSV
- AI uses
get_all_replies(),search_replies(),get_reply_stats()to analyze
| Technique | Purpose |
|---|---|
| Custom User-Agent | Mimics real Chrome browser |
navigator.webdriver removal |
Hides automation flag |
AutomationControlled disabled |
Prevents Chromium detection |
| Randomized scroll delays (1.5-4.5s) | Avoids behavioral fingerprinting |
| Early stop on idle scrolls | Mimics natural browsing patterns |
- Public posts only — Cannot access private or restricted posts
- Meta's anti-bot measures — Meta may block headless browsers; if scraping fails, try the standalone CLI in non-headless mode
- GraphQL schema changes — Meta periodically changes their API structure; the parser in
scraper.pymay need updating
Contributions are welcome! Please open an issue or submit a pull request.