Export Discord Server Members + Social Links to Google Sheets
Scrape all active members from any Discord server and their public social links (Twitter, GitHub, LinkedIn, etc.). Paste a fetch() from DevTools — the workflow scans all channels for active users, enriches each profile, and saves to Google Sheets.
Last updated
March 1, 2026
Connectors used
Tags
Key Takeaways
- Active member discovery — Scans all text channels and collects every user who has sent a message (bots excluded, deduplication built-in)
- Social link enrichment — Fetches each member's public Discord profile to extract Twitter/X, GitHub, LinkedIn, Bluesky, Twitch, Reddit, YouTube, Instagram, Spotify, and Steam
- Two-phase, two-loop workflow — Phase 1 collects users across channels; Phase 2 enriches profiles and writes to Google Sheets
- No Discord API key required — Uses your browser session via a copied fetch() request
- Upsert-safe — Writes each member with deduplication so re-runs never create duplicate rows
What This Workflow Does
This workflow scrapes all active members from any Discord server you are a member of, enriches each profile with their publicly linked social accounts, and exports everything to Google Sheets — automatically.
You copy one fetch() request from your browser's DevTools. The workflow then:
- Discovers all text channels in the server
- Reads the last 100 messages from each channel to collect unique user IDs
- Fetches each user's Discord profile to extract connected social accounts
- Saves every member as a row in Google Sheets, with upsert to avoid duplicates
Use cases:
- Build a lead list from a niche community (devs, founders, crypto, AI)
- Find GitHub and LinkedIn profiles for developer outreach
- Identify Twitter/X influencers active in your target community
- Research community members before reaching out
- Map the social graph of a Discord server for partnership or growth work
How It Works
| Step | What Happens |
|---|---|
| 1. Manual trigger | Paste a fetch() request from Discord DevTools |
| 2. Parse authentication | Extracts authorization token, guild ID from Referer, and cookies |
| 3. Get channels | Calls Discord API to list all text channels in the server |
| 4. Filter channels | Keeps only text (type 0) and announcement (type 5) channels |
| 5. Channel loop | Iterates through each channel, fetches 100 messages, accumulates unique user IDs |
| 6. Extract user array | Reads the final deduplicated user list from the channel loop output |
| 7. Profile loop | For each user, calls the Discord profile API to get connected social accounts |
| 8. Extract connections | Maps connected_accounts to Twitter, GitHub, LinkedIn, Bluesky, etc. |
| 9. AI save to Sheets | Writes each enriched member row to Google Sheets using upsert |
Setup Instructions
Step 1: Get a Discord fetch() Request
- Open Discord in your browser (not the desktop app)
- Navigate to any channel in the server you want to scrape
- Press F12 to open DevTools
- Go to the Network tab
- Perform any action — click a channel, scroll, send a reaction
- Find any request to
discord.com/api/v9/... - Right-click the request → Copy → Copy as fetch()
The workflow only needs the authorization token and Referer header from the fetch. The Referer must contain /channels/{guildId}/{channelId} so the workflow knows which server to scrape.
Step 2: Set Up the Workflow
- Click Use template on this page
- Click the Manual Trigger node and paste your copied fetch()
- Click the AI Save node (needle_ai_v1)
- Replace the Google Sheets URL placeholder with your actual sheet URL
- Connect a Google Sheets connector via the Pipedream integration
Step 3: Run
- Click Run at the top
- The workflow runs in two phases automatically:
- Phase 1 (~10–30 seconds): scans all channels, collects user IDs
- Phase 2 (~5s per user): enriches each profile, saves to Sheets
- Check your Google Sheet for results as they stream in
Data Extracted Per Member
| Column | Field | Description |
|---|---|---|
| A | user_id | Discord snowflake user ID |
| B | username | The unique @handle |
| C | global_name | Display name set by the user |
| D | nickname | Server-specific nickname (if set) |
| E | bio | Public bio text (up to 500 chars) |
| F | joined_at | When they joined this server |
| G | premium_since | When they started Nitro boosting (if applicable) |
| H | Twitter/X username (if public) | |
| I | github | GitHub username (if public) |
| J | twitch | Twitch username (if public) |
| K | Reddit username (if public) | |
| L | bluesky | Bluesky handle (if public) |
| M | youtube | YouTube channel (if public) |
| N | Instagram username (if public) | |
| O | spotify | Spotify username (if public) |
| P | steam | Steam username (if public) |
| Q | LinkedIn profile (if public) | |
| R | website | Personal domain (if public) |
Important Notes
Who gets captured: Only users who have sent at least one message in an accessible channel. Lurkers who never post are not included. This is because Discord's member list REST endpoint requires admin/Manage Members permission — reading messages does not.
Social links: Discord only returns connections the user has explicitly made public in their profile settings. Typically 5–15% of members will have at least one public social link, which is still extremely valuable for outreach.
Rate limiting: The workflow adds a 1-second delay between channel requests and a 5-second delay between profile requests. This is conservative and avoids rate-limit errors. For servers with many members, the workflow may take 15–30 minutes to complete.
Pagination Details
| Setting | Value |
|---|---|
| Messages per channel | 100 (last 100) |
| Max channels | 50 |
| Max users | 5,000 |
| Delay between channels | 1 second |
| Delay between profile requests | 5 seconds |
Customization
| What You Can Change | How |
|---|---|
| Fewer / more channels | Change index < 50 in the Channel Loop condition |
| More members | Change index < 5000 in the User Loop condition |
| Faster runs | Reduce the wait node duration (risk: rate limiting) |
| Output destination | Replace Google Sheets with Airtable, Notion, or a webhook |
| Filter by social presence | Add a conditional node after Extract Connections to skip users with no links |
Troubleshooting
Q: I get "Could not extract guild ID from Referer"
A: The fetch() must be copied from a Discord channel page (discord.com/channels/{guildId}/{channelId}). Make sure the Referer header contains a valid channel URL.
Q: Phase 1 returns 0 users A: Your account may not have permission to read messages in any channel, or the token has expired. Copy a fresh fetch() from DevTools.
Q: Some users have no social links A: Only publicly shared connections appear. Most Discord users keep their accounts private. 5–15% public connection rate is typical.
Q: The workflow is very slow A: The 5-second delay between profile requests is intentional. For 175 users that's ~15 minutes. You can reduce it to 2–3 seconds for faster runs, but risk hitting Discord's rate limits.
Q: I see "Terminal node result not found" on the User Loop
A: This means the channel loop's output wasn't properly connected to the user loop's input. Make sure there is an edge from the channel loop node (default output) to the "Get User Array" code node, and from there to the user loop's input handle.
FAQ
Q: Do I need admin permissions on the Discord server? A: No. Any member can read messages in public channels. The workflow works with regular member access.
Q: Is this against Discord's Terms of Service? A: This workflow uses the same API endpoints your browser uses when you view Discord. It does not use bots or bypass rate limits. However, be mindful of your server's community guidelines and applicable data protection laws.
Q: Can I run this for multiple servers? A: Yes — run the workflow separately for each server using a fetch() copied from a channel in that server.
Q: How do I get more than 100 messages per channel?
A: The workflow fetches the last 100 messages. To go further back, you would need to add pagination using the before query parameter in the messages API, but this significantly increases runtime.
Q: What if I want only members with a GitHub profile?
A: After the "Extract Connections" code node, add a Conditional node that checks input.github !== '' and only proceeds to the AI Save node when true.
Want to showcase your own workflows?
Become a Needle workflow partner and turn your expertise into recurring revenue.