Introduction
meetupr is an R package that provides a client for the Meetup.com GraphQL API. It allows you to search for groups, retrieve event information, get member lists, and access other Meetup data directly from R. This vignette will guide you through setup, authentication, and common use cases.
Quick Setup Check
Start by running meetup_sitrep() to check your
authentication status or set up authentication:
meetup_sitrep()
#>
#> ── meetupr Situation Report ────────────────────────────────────────────────────
#>
#> ── Active Authentication Method ──
#>
#> ✔ OAuth (CI Mode) - "Active"
#> ℹ Cached Token: None - run `get_self()`
#> ℹ CI environment detected
#>
#> ── Package Settings ──
#>
#> ℹ Debug Mode: Disabled
#> ℹ API endpoint: <https://api.meetup.com/gql-ext>
#>
#> ── API Connectivity Test ──
#>
#> ✔ API Connection: Working
#> ℹ Authenticated as: R-Ladies Global (ID: 251470805)This function shows you:
- Which authentication method is currently active
- Whether your credentials are properly configured
- API connectivity status
- Setup instructions if authentication is missing
The function provides actionable feedback, telling you exactly what to do if authentication isn’t working.
Authentication
Authentication is required to access the Meetup API. meetupr supports two authentication methods: interactive OAuth (for local development) and CI/CD authentication (for automated workflows).
Interactive Authentication
For interactive use (exploring data, one-off analyses), simply authenticate when prompted:
# Authenticate interactively (opens browser)
meetup_auth()
# Check authentication status
meetup_auth_status()When you run meetup_auth():
- A browser window opens to Meetup’s authorization page
- You log in with your Meetup credentials
- You grant permission to the meetupr app
- The OAuth token is securely cached on your system
The OAuth token is stored locally in your httr2 cache directory.
Token files follow the naming pattern:
{hash}-token.rds.enc. These files are encrypted and
specific to your system.
You only need to authenticate once. The token will be reused in future R sessions until it expires (typically after 90 days).
CI/CD Authentication
For automated workflows (GitHub Actions, scheduled scripts, etc.), you need token-based authentication that doesn’t require browser interaction.
Step 1: Set up CI credentials locally
# First authenticate interactively
meetup_auth()
# Then set up CI credentials
meetup_ci_setup()The meetup_ci_setup() function will:
- Encode your existing OAuth token as base64
- Store the encoded token in your system keyring
- Display the token and filename for setting CI secrets
- Provide instructions for your CI platform
Step 2: Set environment variables in your CI
In your CI platform (GitHub Actions, GitLab CI, etc.), set these secrets:
-
meetupr:token: Base64-encoded token (from step 1)
-
meetupr:token_file: Token filename (e.g.,ae743e0-token.rds.enc)
For GitHub Actions, your workflow YAML should include:
env:
"meetupr:token": ${{ secrets.MEETUPR_TOKEN }}
"meetupr:token_file": ${{ secrets.MEETUPR_TOKEN_FILE }}Important: Quote the environment variable names in YAML because they contain colons.
Deauthentication
To remove cached credentials:
# Clear authentication completely
meetup_deauth()The meetup_deauth() function removes all cached tokens
and clears authentication state. You’ll need to re-authenticate the next
time you make an API call.
Verification
After authenticating, verify the setup:
meetup_sitrep()
#>
#> ── meetupr Situation Report ────────────────────────────────────────────────────
#>
#> ── Active Authentication Method ──
#>
#> ✔ OAuth (CI Mode) - "Active"
#> ℹ Cached Token: None - run `get_self()`
#> ℹ CI environment detected
#>
#> ── Package Settings ──
#>
#> ℹ Debug Mode: Disabled
#> ℹ API endpoint: <https://api.meetup.com/gql-ext>
#>
#> ── API Connectivity Test ──
#>
#> ✔ API Connection: Working
#> ℹ Authenticated as: R-Ladies Global (ID: 251470805)The output shows:
- Whether an OAuth token exists and is valid
- Whether you’re in CI mode (token loaded from environment
variables)
- API connectivity status
Basic Usage Examples
Once authenticated, you can start querying the Meetup API. All functions return tibbles (data frames) for easy manipulation with dplyr and other tidyverse packages.
Get Group Information
Retrieve detailed information about a specific group using its URL
name (the part after meetup.com/ in the URL):
group_info <- get_group("rladies-lagos")
str(group_info)
#> List of 13
#> $ id : chr "32612004"
#> $ name : chr "R-Ladies Lagos"
#> $ description : chr "R-Ladies is a world-wide organization to promote gender diversity in the R community.\nR-Ladies welcomes member"| __truncated__
#> $ urlname : chr "rladies-lagos"
#> $ link : chr "https://www.meetup.com/rladies-lagos"
#> $ location :List of 2
#> ..$ city : chr "Lagos"
#> ..$ country: chr "ng"
#> $ timezone : chr "Africa/Lagos"
#> $ created : POSIXct[1:1], format: "2019-08-16 08:45:21"
#> $ members : int 880
#> $ total_events: int 13
#> $ organizer :List of 2
#> ..$ id : chr "251470805"
#> ..$ name: chr "R-Ladies Global"
#> $ category :List of 2
#> ..$ id : chr "546"
#> ..$ name: chr "Technology"
#> $ photo_url : chr "https://secure-content.meetupstatic.com/images/classic-events/"
#> - attr(*, "class")= chr [1:2] "meetup_group" "list"The result includes:
- Group name, description, and URL
- Location (city, state, country)
- Member count
- Organizer information
- Group creation date
List Group Events
Get events for a specific group. By default, this returns upcoming events:
events <- get_group_events("rladies-lagos")
head(events)
#> # A tibble: 6 × 23
#> id title event_url created_time status date_time duration
#> <chr> <chr> <chr> <dttm> <chr> <dttm> <chr>
#> 1 26415… satR… https://… 2019-08-20 11:54:50 PAST 2019-09-21 08:00:00 PT7H
#> 2 26675… Data… https://… 2019-11-26 17:00:29 PAST 2019-12-07 08:00:00 PT7H
#> 3 26780… Gett… https://… 2020-01-10 12:56:39 PAST 2020-02-22 08:00:00 PT7H
#> 4 28432… Data… https://… 2022-03-01 00:27:32 PAST 2022-03-26 13:00:00 PT2H
#> 5 28461… R La… https://… 2022-03-14 16:37:46 PAST 2022-05-07 15:00:00 PT1H
#> 6 29226… Wome… https://… 2023-03-15 19:29:08 PAST 2023-03-24 09:00:00 PT2H
#> # ℹ 16 more variables: description <chr>, group_id <chr>, group_name <chr>,
#> # group_urlname <chr>, venues_id <list>, venues_name <list>,
#> # venues_address <list>, venues_city <list>, venues_state <list>,
#> # venues_postal_code <list>, venues_country <list>, venues_lat <list>,
#> # venues_lon <list>, venues_venue_type <list>, rsvps_count <int>,
#> # featured_event_photo_url <chr>Each row represents an event with:
- Event ID, title, and description
- Date and time (as POSIXct objects)
- Duration
- RSVP counts (yes, waitlist, total)
- Venue information (if available)
Get Past Events
To retrieve historical events, use the status
parameter:
past_events <- get_group_events(
"rladies-lagos",
status = "past",
max_results = 10
)
head(past_events)
#> # A tibble: 6 × 23
#> id title event_url created_time status date_time duration
#> <chr> <chr> <chr> <dttm> <chr> <dttm> <chr>
#> 1 26415… satR… https://… 2019-08-20 11:54:50 PAST 2019-09-21 08:00:00 PT7H
#> 2 26675… Data… https://… 2019-11-26 17:00:29 PAST 2019-12-07 08:00:00 PT7H
#> 3 26780… Gett… https://… 2020-01-10 12:56:39 PAST 2020-02-22 08:00:00 PT7H
#> 4 28432… Data… https://… 2022-03-01 00:27:32 PAST 2022-03-26 13:00:00 PT2H
#> 5 28461… R La… https://… 2022-03-14 16:37:46 PAST 2022-05-07 15:00:00 PT1H
#> 6 29226… Wome… https://… 2023-03-15 19:29:08 PAST 2023-03-24 09:00:00 PT2H
#> # ℹ 16 more variables: description <chr>, group_id <chr>, group_name <chr>,
#> # group_urlname <chr>, venues_id <chr>, venues_name <chr>,
#> # venues_address <chr>, venues_city <chr>, venues_state <chr>,
#> # venues_postal_code <chr>, venues_country <chr>, venues_lat <dbl>,
#> # venues_lon <dbl>, venues_venue_type <chr>, rsvps_count <int>,
#> # featured_event_photo_url <chr>Valid status values are:
-
upcoming: Future events (default)
-
past: Historical events
-
cancelled: Cancelled events
-
draft: Draft events (if you’re a group organizer)
Filter Events by Date
You can filter events within a specific date range:
# Events from 2024 onwards
recent_events <- get_group_events(
"rladies-lagos",
status = "past",
date_after = "2024-01-01T00:00:00Z"
)
head(recent_events)
#> # A tibble: 3 × 23
#> id title event_url created_time status date_time duration
#> <chr> <chr> <chr> <dttm> <chr> <dttm> <chr>
#> 1 30002… Buil… https://… 2024-03-26 12:37:08 PAST 2024-04-06 16:00:00 PT3H
#> 2 30035… Inte… https://… 2024-04-11 19:14:08 PAST 2024-04-25 10:00:00 PT5H
#> 3 30002… Inte… https://… 2024-03-26 13:08:58 PAST 2024-04-27 16:00:00 PT3H
#> # ℹ 16 more variables: description <chr>, group_id <chr>, group_name <chr>,
#> # group_urlname <chr>, venues_id <list>, venues_name <list>,
#> # venues_address <list>, venues_city <list>, venues_state <list>,
#> # venues_postal_code <list>, venues_country <list>, venues_lat <list>,
#> # venues_lon <list>, venues_venue_type <list>, rsvps_count <int>,
#> # featured_event_photo_url <chr>Dates must be in ISO 8601 format with timezone (typically UTC:
YYYY-MM-DDTHH:MM:SSZ).
Get Event Details
Retrieve detailed information about a specific event using its ID:
event <- get_event(id = "103349942")
event
#>
#> ── Meetup Event ──
#>
#> • ID: "103349942"
#> • Title: Ecosystem GIS & Community Building
#> • Status: "PAST"
#> • Date/Time: 2013-02-18T18:30:00-05:00
#> • Duration: PT2H
#> • RSVPs: 97
#>
#> ── Group:
#> • Data Visualization DC ("data-visualization-dc")
#>
#> ── Venue:
#> • Name: Browsermedia/NClud
#> • Location: Washington, DC, us
#>
#> <https://www.meetup.com/data-visualization-dc/events/103349942/>The print() method displays a formatted summary. Access
individual fields with $ notation:
event$title
event$dateTime
event$goingGet Event RSVPs
See who has RSVP’d to an event:
rsvps <- get_event_rsvps(id = "103349942")
head(rsvps)
#> # A tibble: 6 × 9
#> id member_id member_name member_bio member_url member_photo_url
#> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 683104152 12251810 Sean Moore Gonzalez "Backgrou… https://w… https://secure-…
#> 2 683108312 482161 Harlan Harris "" https://w… https://secure-…
#> 3 683109202 6382386 Harnam Rai "" https://w… https://secure-…
#> 4 683114012 70383262 Dario Rivera "" https://w… https://secure-…
#> 5 683114892 8783792 Aaron M "" https://w… https://secure-…
#> 6 683118132 10948775 Sam "" https://w… https://secure-…
#> # ℹ 3 more variables: member_organized_group_count <int>, guests_count <int>,
#> # status <chr>Each row represents one RSVP with:
- Member ID and name
- RSVP response (yes, no, waitlist)
- Number of guests
- RSVP creation time
This is useful for analyzing attendance patterns or contacting attendees (with appropriate permissions).
Get Group Members
List members of a group:
members <- get_group_members("rladies-lagos", max_results = 10)
head(members)
#> # A tibble: 6 × 4
#> id name member_url member_photo_url
#> <chr> <chr> <chr> <chr>
#> 1 251470805 R-Ladies Global https://www.meetup.com/member… https://secure-…
#> 2 225839690 EYITAYO ALIMI https://www.meetup.com/member… https://secure-…
#> 3 236466773 Adedamilola Adekanye https://www.meetup.com/member… https://secure-…
#> 4 255806325 Helen https://www.meetup.com/member… https://secure-…
#> 5 287781170 Alvin https://www.meetup.com/member… https://secure-…
#> 6 266271010 ijeoma benson https://www.meetup.com/member… NAMember data includes:
- Member ID and name
- Join date
- Member status (active, organizer, etc.)
- Bio and profile URL
Note: Due to privacy settings, some member information may be limited.
Search for Groups
Find groups matching a search term:
r_groups <- find_groups("R programming")
head(r_groups)
#> # A tibble: 6 × 14
#> id name urlname city state country lat lon memberships_count
#> <chr> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <int>
#> 1 38207702 Birmingh… bham-r… Birm… "AL" us 33.5 -86.8 5
#> 2 24890872 Warwick … warwic… Cove… "43" gb 52.4 -1.56 919
#> 3 18574545 Johannes… joburg… Joha… "" za -26.2 28.0 1557
#> 4 2906882 Birmingh… Birmin… Birm… "43" gb 52.5 -1.9 808
#> 5 23174619 R-Ladies… rladie… Sant… "" ar -36.6 -64.3 185
#> 6 26517118 Salt Lak… slc-rug Salt… "UT" us 40.8 -112. 3050
#> # ℹ 5 more variables: founded_date <dttm>, timezone <chr>, join_mode <chr>,
#> # is_private <lgl>, membership_status <chr>Search results include:
- Group name and URL name
- Location
- Member count
- Description snippet
This is useful for discovering groups in your area or analyzing group networks.
Pagination and Rate Limits
The Meetup API limits how many results can be returned in a single
request. The max_results parameter controls pagination:
# Get up to 50 events (may require multiple API calls)
many_events <- get_group_events(
"rladies-san-francisco",
status = "past",
max_results = 50
)
cli::cli_alert_info("Retrieved {nrow(many_events)} events")
#> ℹ Retrieved 50 eventsmeetupr automatically handles pagination behind the scenes. It makes multiple API requests if needed and combines the results into a single tibble.
The Meetup API rate limit is 500 requests per 60 seconds. meetupr automatically throttles requests to stay under this limit. For large batch operations, consider adding explicit delays:
# Process multiple groups with delays
groups <- c("rladies-nyc", "rladies-sf", "rladies-london")
events <- purrr::map_dfr(groups, \(x) {
result <- get_group_events(x, max_results = 20)
Sys.sleep(0.5) # 500ms delay between requests
result
})Pro Account Features
If you have a Meetup Pro account, you can access network-wide data using the Pro functions. These functions require appropriate permissions and will error if you don’t have Pro access.
List All Pro Groups
# Get all groups in the R-Ladies network
pro_groups <- get_pro_groups("rladies")
head(pro_groups)Network-Wide Events
# Get upcoming events across all groups in network
upcoming <- get_pro_events("rladies", status = "upcoming")
head(upcoming)
# Get cancelled events
cancelled <- get_pro_events("rladies", status = "cancelled")
head(cancelled)Pro functions return data for all groups in your network with a single API call, which is more efficient than querying each group individually.
Debug Mode
Sometimes issues arise due to misconfiguration or unexpected API behavior. Enabling debug mode shows the exact GraphQL queries being sent to the API.
Enable debugging by setting the MEETUPR_DEBUG
environment variable to 1:
local_meetupr_debug(1)
meetup_sitrep()
#>
#> ── meetupr Situation Report ────────────────────────────────────────────────────
#>
#> ── Active Authentication Method ──
#>
#> ✔ OAuth (CI Mode) - "Active"
#> ℹ Cached Token: None - run `get_self()`
#> ℹ CI environment detected
#>
#> ── Package Settings ──
#>
#> ℹ Debug Mode: Enabled
#> ℹ API endpoint: <https://api.meetup.com/gql-ext>
#>
#> ── API Connectivity Test ──
#>
#> ℹ DEBUG: JSON to be sent:
#> {
#> "query": "query GetSelf{
#> self {
#> id
#> name
#> email
#> isOrganizer
#> isLeader
#> isMemberPlusSubscriber
#> isProOrganizer
#> adminProNetworks {
#> id
#> name
#> }
#> bio
#> city
#> country
#> state
#> lat
#> lon
#> startDate
#> preferredLocale
#> memberUrl
#>
#> }
#> }",
#> "variables": {}
#> }
#> ✔ API Connection: Working
#> ℹ Authenticated as: R-Ladies Global (ID: 251470805)
find_groups("R programming")
#> ℹ DEBUG: JSON to be sent:
#> {
#> "query": "query findGroups(
#> $query: String!
#> $cursor: String
#> $first: Int = 1000
#> $lat: Float = 0.0
#> $lon: Float = 0.0
#> $radius: Float = 100000000.0
#> $categoryId: ID
#> $topicCategoryId: ID
#> ) {
#> groupSearch(
#> after: $cursor
#> first: $first
#> filter: {
#> query: $query
#> lat: $lat
#> lon: $lon
#> radius: $radius
#> categoryId: $categoryId
#> topicCategoryId: $topicCategoryId
#> }
#> ) {
#> pageInfo {
#> hasNextPage
#> endCursor
#> }
#> totalCount
#> edges {
#> node {
#> id
#> name
#> urlname
#> city
#> state
#> country
#> lat
#> lon
#> memberships {
#> totalCount
#> }
#> foundedDate
#> timezone
#> joinMode
#> isPrivate
#> membershipMetadata {
#> status
#> }
#> }
#> }
#>
#> }
#> }",
#> "variables": {
#> "query": "R programming",
#> "first": 200
#> }
#> }
#> # A tibble: 200 × 14
#> id name urlname city state country lat lon memberships_count
#> <chr> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <int>
#> 1 38207702 Birming… bham-r… Birm… "AL" us 33.5 -86.8 5
#> 2 24890872 Warwick… warwic… Cove… "43" gb 52.4 -1.56 919
#> 3 18574545 Johanne… joburg… Joha… "" za -26.2 28.0 1557
#> 4 2906882 Birming… Birmin… Birm… "43" gb 52.5 -1.9 808
#> 5 23174619 R-Ladie… rladie… Sant… "" ar -36.6 -64.3 185
#> 6 26517118 Salt La… slc-rug Salt… "UT" us 40.8 -112. 3050
#> 7 20443056 R-Ladie… rladie… Paris "" fr 48.9 2.34 1143
#> 8 21760043 R-Ladie… rladie… Buen… "" ar -34.6 -58.4 1966
#> 9 37281989 Cape To… cape-t… Cape… "" za -33.9 18.5 110
#> 10 17428672 R Users… spotka… Wars… "" pl 52.3 21.0 2975
#> # ℹ 190 more rows
#> # ℹ 5 more variables: founded_date <dttm>, timezone <chr>, join_mode <chr>,
#> # is_private <lgl>, membership_status <chr>Debug output includes:
- The complete GraphQL query sent to the API
- Variable values being passed
- The raw JSON response
This is invaluable when queries fail unexpectedly or you’re unsure what data is being returned.
To turn it off again, set it to 0:
local_meetupr_debug(0)
meetup_sitrep()
#>
#> ── meetupr Situation Report ────────────────────────────────────────────────────
#>
#> ── Active Authentication Method ──
#>
#> ✔ OAuth (CI Mode) - "Active"
#> ℹ Cached Token: None - run `get_self()`
#> ℹ CI environment detected
#>
#> ── Package Settings ──
#>
#> ℹ Debug Mode: Disabled
#> ℹ API endpoint: <https://api.meetup.com/gql-ext>
#>
#> ── API Connectivity Test ──
#>
#> ✔ API Connection: Working
#> ℹ Authenticated as: R-Ladies Global (ID: 251470805)
find_groups("R programming")
#> # A tibble: 200 × 14
#> id name urlname city state country lat lon memberships_count
#> <chr> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <int>
#> 1 38207702 Birming… bham-r… Birm… "AL" us 33.5 -86.8 5
#> 2 24890872 Warwick… warwic… Cove… "43" gb 52.4 -1.56 919
#> 3 18574545 Johanne… joburg… Joha… "" za -26.2 28.0 1557
#> 4 2906882 Birming… Birmin… Birm… "43" gb 52.5 -1.9 808
#> 5 23174619 R-Ladie… rladie… Sant… "" ar -36.6 -64.3 185
#> 6 26517118 Salt La… slc-rug Salt… "UT" us 40.8 -112. 3050
#> 7 20443056 R-Ladie… rladie… Paris "" fr 48.9 2.34 1143
#> 8 21760043 R-Ladie… rladie… Buen… "" ar -34.6 -58.4 1966
#> 9 37281989 Cape To… cape-t… Cape… "" za -33.9 18.5 110
#> 10 17428672 R Users… spotka… Wars… "" pl 52.3 21.0 2975
#> # ℹ 190 more rows
#> # ℹ 5 more variables: founded_date <dttm>, timezone <chr>, join_mode <chr>,
#> # is_private <lgl>, membership_status <chr>For persistent debugging across R sessions, set the environment
variable in your .Renviron file:
MEETUPR_DEBUG=1
Common Issues
Authentication Errors
Error: Authentication required
Solution: Run meetup_sitrep() to
diagnose the issue. Common causes include:
- No OAuth token cached (run
meetup_auth())
- Expired token (re-authenticate with
meetup_auth())
- Missing CI environment variables (check
meetupr:tokenandmeetupr:token_file)
Multiple Token Warning
Warning: Multiple tokens found in cache
Solution: Clear old tokens and re-authenticate:
This happens when tokens from different OAuth applications accumulate in your cache directory.
Rate Limiting
Error: Rate limit exceeded
Solution: The Meetup API limits you to 500 requests per 60 seconds. If you hit this limit:
- Add delays between requests (
Sys.sleep(0.5))
- Reduce
max_resultsto minimize pagination
- Cache results locally to avoid repeated queries
meetupr automatically throttles requests, but aggressive batch operations may still hit limits.
Group Not Found
Error: Group not found
Solution: Verify the group URL name. The URL name is
the part after meetup.com/ in the group’s URL. For example,
for https://www.meetup.com/rladies-san-francisco/, the URL
name is rladies-san-francisco.
CI Token Expired
If CI authentication fails with “token expired”:
# Locally, refresh token
meetup_auth()
meetup_ci_setup()
# Update CI secrets with new values shown by meetup_ci_setup()You’ll need to refresh CI secrets periodically.
Next Steps
Now that you’re set up, explore more advanced features:
-
Custom GraphQL Queries: See the GraphQL vignette to write custom queries and
access fields not available through wrapper functions
-
Custom OAuth Application: See the Advanced Authentication vignette for
setting up your own OAuth app for higher rate limits
- API Schema Exploration: See the Inspecting the API vignette for exploring the Meetup GraphQL schema
- Data Analysis: Combine meetupr with dplyr, ggplot2, and other tidyverse packages for analysis and visualization
For package updates and issues, visit the GitHub repository.
Getting Help
If you encounter issues:
-
Check
meetup_sitrep()for authentication diagnostics
-
Enable debug mode
(
local_meetupr_debug(1)) to see API queries
-
Search existing issues on GitHub
-
File a bug report with a reproducible example (use
reprex::reprex())
When reporting issues, include:
- Output from
meetup_sitrep()
- Debug output (if relevant)
- A minimal reproducible example
- Your R and package versions (
sessionInfo())
This helps maintainers diagnose and fix problems quickly.
