A TypeScript CLI tool to archive all events from a Meetup.com group using the Meetup GraphQL API. Exports comprehensive event data including venue information, RSVPs, hosts, photos, and more to a well-formatted JSON file.
- ✅ Fetches all historic events (past & upcoming) from any Meetup group
- ✅ Uses Meetup's official GraphQL API
- ✅ Automatic pagination to retrieve complete event history
- ✅ Comprehensive event data extraction:
- Event details (title, description, date, duration, URL)
- Venue information (name, address, coordinates)
- RSVP counts and attendee lists
- Event hosts
- Featured photos
- Event type (in-person, online, hybrid)
- ✅ Clean JSON output with metadata
- ✅ HTML rendering of archived events with formatted descriptions
- ✅ Rate limiting protection
- ✅ Progress indicators
- Node.js (v18 or higher)
- npm
- A Meetup.com account
- Access token from Meetup.com
-
Clone or navigate to this directory:
cd meetup-archiver -
Install dependencies:
npm install
-
Set up environment variables:
cp .env.example .env
You need an access token from Meetup.com to use this tool. Here's the easiest way to get it:
-
Log in to Meetup.com:
- Visit https://www.meetup.com and log in to your account
-
Open Browser DevTools:
- Press
F12(Windows/Linux) orCmd+Option+I(Mac)
- Press
-
Find the Cookie:
- Go to the Application tab (Chrome) or Storage tab (Firefox)
- Navigate to Cookies →
https://www.meetup.com - Look for a cookie named:
__meetup_auth_access_token - Copy the Value of this cookie
-
Add to .env file:
- Open the
.envfile in your text editor - Replace
your_token_herewith your copied token:
MEETUP_ACCESS_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... - Open the
-
Log in to Meetup.com:
- Visit https://www.meetup.com and log in
-
Open DevTools and go to Network tab:
- Press
F12and click the Network tab
- Press
-
Visit the API Playground:
-
Run any test query:
- Execute a simple query in the playground
-
Find the API request:
- In the Network tab, find a request to
api.meetup.com/gql-ext - Click on it and look at the Request Headers
- Find the
Authorizationheader - Copy the token after
Bearer(everything after "Bearer ")
- In the Network tab, find a request to
-
Add to .env file:
MEETUP_ACCESS_TOKEN=your_copied_token
Test your token with this PowerShell command:
$token = "YOUR_TOKEN_HERE"
$body = '{"query": "query { self { id name } }"}'
Invoke-RestMethod -Uri "https://api.meetup.com/gql-ext" -Method Post -Headers @{"Authorization"="Bearer $token"; "Content-Type"="application/json"} -Body $bodyIf it works, you'll see your user ID and name. If it fails, you'll get an authentication error.
Archive all events from a Meetup group:
npm run dev -- <group-urlname>Or after building:
npm run build
npm start <group-urlname>Convert a generated archive JSON into a nicely formatted HTML report (most recent first):
# Example: render the OWASP Israel archive you just created
npm run render -- output/owasp-israel-2026-01-14T07-02-25-976Z.json
# Optional: specify a custom output path
npm run render -- output/owasp-israel-2026-01-14T07-02-25-976Z.json ./output-html/owasp-israel.htmlThe HTML will be written to output-html/<archive-name>.html by default.
The group URL name is the identifier in the Meetup.com URL. For example:
-
URL:
https://www.meetup.com/typescript-oslo/ -
Group URL name:
typescript-oslo -
URL:
https://www.meetup.com/london-javascript-community/ -
Group URL name:
london-javascript-community
npm run dev -- typescript-osloThis will:
- Authenticate with Meetup.com
- Fetch all past events for the group
- Fetch all upcoming events for the group
- Combine and sort them chronologically
- Save to
output/typescript-oslo-2026-01-14T12-30-45-123Z.json
The tool creates a JSON file in the output/ directory with this structure:
{
"metadata": {
"archivedAt": "2026-01-14T12:30:45.123Z",
"groupUrlname": "typescript-oslo",
"groupId": "12345678",
"groupName": "TypeScript Oslo",
"totalEvents": 150,
"pastEvents": 145,
"upcomingEvents": 5
},
"events": [
{
"id": "276754274",
"title": "TypeScript Workshop",
"description": "Learn TypeScript basics...",
"dateTime": "2025-03-15T18:00:00+01:00",
"duration": "PT2H",
"eventUrl": "https://www.meetup.com/typescript-oslo/events/276754274/",
"eventType": "IN_PERSON",
"going": 45,
"maxTickets": 50,
"venue": {
"name": "Tech Hub Oslo",
"address": "123 Main St",
"city": "Oslo",
"state": "Oslo",
"country": "NO",
"lat": 59.9139,
"lng": 10.7522
},
"featuredEventPhoto": {
"id": "495693322",
"baseUrl": "https://secure-content.meetupstatic.com/images/classic-events/"
},
"eventHosts": [
{
"memberId": "123456",
"name": "John Doe"
}
],
"rsvps": {
"totalCount": 45,
"edges": [
{
"node": {
"id": "rsvp_123",
"member": {
"id": "789012",
"name": "Jane Smith"
}
}
}
]
}
}
]
}meetup-archiver/
├── src/
│ ├── index.ts # Main CLI entry point
│ ├── meetupClient.ts # GraphQL API client with pagination
│ ├── queries.ts # GraphQL query definitions
│ ├── renderHtml.ts # HTML rendering for archived events
│ ├── types.ts # TypeScript type definitions
│ ├── utils.ts # File operations and utilities
│ └── __tests__/ # Unit and integration tests
│ ├── meetupClient.test.ts
│ ├── renderHtml.test.ts
│ └── utils.test.ts
├── output/ # Generated JSON files (created automatically)
├── output-html/ # Generated HTML files (created automatically)
├── .env # Your access token (DO NOT COMMIT)
├── .env.example # Template for .env
├── .gitignore # Git ignore rules
├── jest.config.js # Jest configuration
├── package.json # Project dependencies
├── tsconfig.json # TypeScript configuration
└── README.md # This file
The Meetup API has rate limits:
- 500 points per 60 seconds
- The tool includes basic rate limit protection and will wait if approaching limits
- Check that your
MEETUP_ACCESS_TOKENin.envis correct - Try getting a fresh token from your browser
- Make sure you're logged into Meetup.com in your browser
- Verify the group URL name is correct
- Check that the group is public (private groups may not be accessible)
- Ensure you have permission to view the group
- Access tokens from cookies may expire
- If you get authentication errors, get a fresh token from your browser
- Some tokens expire after a few hours, others last longer
npm run buildnpm run dev -- <group-urlname>npm start <group-urlname>This project includes comprehensive unit tests to ensure functionality works correctly.
Run all tests:
npm testRun tests in watch mode (for development):
npm run test:watchThe test suite includes:
- Unit tests for utility functions (file operations, formatting, metadata)
- Integration tests for the Meetup API client (with mocked requests)
- Tests for HTML rendering and sanitization
The project uses GitHub Actions to automatically run tests on:
- Every push to
mainordevelopbranches - Every pull request targeting
mainordevelopbranches
Tests run on multiple Node.js versions (18.x and 20.x) to ensure compatibility.
- TypeScript - Type-safe JavaScript
- Node.js - Runtime environment
- Axios - HTTP client for GraphQL requests
- Meetup GraphQL API - Official Meetup API
- dotenv - Environment variable management
- marked - Markdown parser for rendering event descriptions
- sanitize-html - HTML sanitization for secure rendering
- Jest - Testing framework
- ts-jest - TypeScript support for Jest
- ts-jest - TypeScript support for Jest
MIT
Feel free to open issues or submit pull requests!
- The tool fetches all available event data from the Meetup API
- Events are sorted chronologically in the output
- RSVP lists may be truncated for very large events (API limitation)
- The tool respects Meetup's API rate limits
For issues with:
- This tool: Open an issue in this repository
- Meetup API: Visit https://www.meetup.com/api/support/
- Getting your token: See "Getting Your Access Token" section above