search-events▌
meetup.com/search-events-8bdsvy · updated May 21, 2026
MDX-style export adds YAML metadata + attribution linking explainx.ai and this canonical listing URL.
Search Meetup for upcoming events by topic, location, group slug, or topic category. Returns structured JSON per event — id, title, group, venue + lat/lon (or online platform), start/end time, going/waitlist counts, capacity, price, photo, organizer/hosts, topic tags, canonical URL. Honors keywords/location/eventType/distance/dateRange/categoryId/sortField URL filters. Read-only.
| name | search-events |
| title | Meetup Search Events |
| description | >- Search Meetup for upcoming events by topic, location, group slug, or topic category. Returns structured JSON per event — id, title, group, venue + lat/lon (or online platform), start/end time, going/waitlist counts, capacity, price, photo, organizer/hosts, topic tags, canonical URL. Honors keywords/location/eventType/distance/dateRange/categoryId/sortField URL filters. Read-only. |
| website | meetup.com |
| category | social |
| tags | - meetup - events - search - groups - read-only |
| source | 'browserbase: agent-runtime 2026-05-18' |
| updated | '2026-05-18' |
| recommended_method | url-param |
| alternative_methods | [] |
| verified | true |
| proxies | true |
Meetup Search Events
Purpose
Search Meetup for upcoming events matching a topic, location, group, or topic-category and return them as structured JSON — event id, title, group, description, format (in-person/online), venue + lat/lon (or online platform), start/end time, going/waitlist counts, capacity, price + is-free flag, photo URL, organizer/hosts, topic tags, and the canonical event URL. Same shape for both ad-hoc text searches and group-scoped event listings. Read-only: never RSVP, join, save, or sign in.
When to Use
- "AI events in San Francisco this week", "book club Brooklyn", "climbing meetups near 94110".
- Pulling a single Meetup group's upcoming events from its slug or URL.
- Aggregating events by topic category (Tech, Social Activities, Sports & Fitness, etc.) in a region.
- Watch-lists / digests for a fixed query + location pair.
- Anywhere a public Meetup browse URL would work — including online-only events.
Workflow
The Meetup find page is a Next.js SSR app whose page HTML embeds the entire first-page GraphQL response (operation: eventSearchWithSeries, server-resolved as eventSearch) inside window.__NEXT_DATA__.props.pageProps.__APOLLO_STATE__. The same response is also mirrored as schema.org <script type="application/ld+json"> blocks (one per result). Fetch the HTML, parse the embedded state, and resolve the Apollo refs — no live browser session, no auth, no GraphQL POST required for page-1 reads. Pagination beyond page 1 does require a GraphQL POST (no URL surface for it); that is the only situation where a Browserbase remote session is needed.
Recommended path — SSR hydration via Browserbase Fetch
-
Build the find URL. Required:
source=EVENTS(without it the page falls into a different code path —recommendedEvents/ ML-popular — that won't honor your filters). Appendkeywords=...for text search,location=...for the geo lock, and any optional filter params from the table below.https://www.meetup.com/find/ ?keywords=<urlenc text> &location=<location-slug> &source=EVENTS &eventType=online|inPerson // optional &distance=fiveMiles|tenMiles|twentyFiveMiles|fiftyMiles|hundredMiles &dateRange=today // ONLY `today` is honored server-side &categoryId=<numeric> // see enum below; maps to topicCategoryId &sortField=RELEVANCE|DATETIME|DISTANCE // UPPERCASE requiredLocation slug grammar (critical, two distinct forms):
- US/Canada:
us--<state-lowercase>--<city-with-dashes>— e.g.us--ny--new-york,us--ca--san-francisco. Dashes between city words, never underscores. Underscore form silently falls back to the request IP's location. - International: REVERSED order:
<city>--<country-code>— e.g.berlin--de,london--gb,paris--fr. The US<country>--<region>--<city>form does not work for non-US cities.
- US/Canada:
-
Fetch with proxies on.
bb fetch "<find-url>" --proxies --allow-redirects --output page.htmlMeetup has Cloudflare in front. Across 30+ probes during skill construction,
--proxiesreturned 200 OK on every find/topic/group URL — no 403s, no captchas, no rate-limit.--proxiesis the safer default. -
Parse
__NEXT_DATA__.import re, json nd = json.loads(re.search( r'<script id="__NEXT_DATA__"[^>]*>(.*?)</script>', html, re.DOTALL).group(1)) pp = nd['props']['pageProps'] apollo = pp['__APOLLO_STATE__'] -
VERIFY the location lock before trusting results. Meetup silently re-resolves the location to the request IP when the
location=slug is malformed. Always confirm before emitting events:ul = pp['userLocation'] # what Meetup actually used # Compare ul.city / ul.state / ul.lat / ul.lon against the user's intent. # If they don't match, the slug was wrong — re-issue with corrected slug, # or emit { success: false, reason: "location_not_resolved", ... }. -
Read the eventSearch result. Locate the single ROOT_QUERY entry whose key starts with
eventSearch:(the rest of the key is a JSON-stringified{filter, sort}block — useful for debugging but not needed for extraction):rq = apollo['ROOT_QUERY'] es_key = next(k for k in rq if k.startswith('eventSearch:')) conn = rq[es_key] total = conn['totalCount'] # region-wide totals has_next = conn['pageInfo']['hasNextPage'] end_cursor = conn['pageInfo']['endCursor'] # base64 offset, e.g. "MTI=" = 12 edges = conn['edges'] # list of {node: {__ref}, metadata} -
Resolve each event by ref. The edges hold
Event:<id>pointers; the full entity is in the flat Apollo store at the same key:for edge in edges: ev = apollo[edge['node']['__ref']] # Event:<id> entity grp = apollo[ev['group']['__ref']] # Group:<id> venue = apollo[ev['venue']['__ref']] if ev.get('venue') else None photo = apollo[ev['featuredEventPhoto']['__ref']] if ev.get('featuredEventPhoto') else None topics = [apollo[t['node']['__ref']] for t in (ev.get('topics') or {}).get('edges', [])] hosts = [apollo[h['__ref']] for h in (ev.get('eventHosts') or [])] # ... assemble flat output (see Expected Output section)Note: on the find-page hydration, the Event entity has
dateTime(start) but noendTime, the Group hasstats.eventRatingsbut no member count, and theeventHostsarray is empty. To get those fields, follow with step 7. -
(Optional, for richer fields) For each event you want hydrated with end time + lat/lon + capacity + topics + hosts + group member count, fetch the canonical event URL:
bb fetch "<ev.eventUrl>" --proxies --output event.htmlThe detail page's
__APOLLO_STATE__has the full Event schema:endTime,topics{edges[]},eventHosts[],rsvps({"filter":{"rsvpStatus":["YES"]}}).totalCount(going count),rsvps({"filter":{"rsvpStatus":["WAITLIST"]}}).totalCount,maxTickets(capacity;0= unlimited),feeSettings(price when paid),venue{lat, lon}, andGroup{stats.memberCounts.all, city, state, country, link, activeTopics, topicCategory}. The same page also carries a clean JSON-LDEventblock withstartDate,endDate,image[],location.address,organizer— often the easiest path when you only need the basics. -
Group-scoped listings. When the input is a group slug (e.g.
/photography-sf/) or URL, fetchhttps://www.meetup.com/<slug>/events/— that page hydrates up to 30 upcoming events as aGroup.events({"filter":{"afterDateTime":"<now>","status":["ACTIVE","PAST","CANCELLED"]},"first":30,"sort":"ASC"})connection on theGroup:<id>entity. Same Event ref-resolution loop; no extra fetch needed. -
Topic / category landing.
https://www.meetup.com/topics/<topic-urlkey>/andhttps://www.meetup.com/topics/<topic-urlkey>/<country>--<region>/both hydrate ~30 events scoped to the topic. Useful when the user's intent is "all AI events near me" with no other text — set<topic-urlkey>=artificial-intelligence. Location for/topics/defaults to request IP unless the country/region subpath is provided. -
Pagination beyond page 1. None of
page=,offset=,after=,cursor=,endCursor=are honored by the SSR — every call returns the same first 12–30 events. To paginate, you must POST theeventSearchWithSeriesoperation to Meetup's GraphQL endpoint with{ after: <endCursor>, first: 30 }(see Site-Specific Gotchas for the endpoint situation), or narrow the query/location until the first page covers your need.
Browser fallback — Browserbase remote session
When (a) you need to paginate beyond page 1 and want to use the in-page Apollo client (which holds the GraphQL endpoint URL + persisted-query hash + auth cookies), or (b) the Fetch API is blocked/rate-limited:
SID=$(bb sessions create --keep-alive --advanced-stealth --proxies | jq -r .id)
browse --connect "$SID" open "https://www.meetup.com/find/?keywords=AI&location=us--ny--new-york&source=EVENTS"
browse --connect "$SID" wait load
browse --connect "$SID" wait timeout 2000
# Pull hydrated state directly
browse --connect "$SID" eval "JSON.stringify(window.__NEXT_DATA__.props.pageProps.__APOLLO_STATE__)" > apollo.json
# To paginate: click the "Show more" / "Load more" button at the bottom and re-eval
browse --connect "$SID" snapshot
# ... find @ref of the load-more button, click it, wait, re-eval __APOLLO_STATE__
bb sessions update "$SID" --status REQUEST_RELEASE
Same Apollo extraction logic as the Fetch path — the in-page state is the same shape, just kept fresh by the Apollo client as the user scrolls.
Site-Specific Gotchas
- Location slug uses dashes, not underscores.
us--ca--san_franciscosilently falls back to the request IP's location (verified: returned "La Canada Flintridge, CA" instead of SF in our sandbox).us--ca--san-franciscoworks. Always verify by reading backuserLocationfrompagePropsafter the fetch — if it doesn't match the user's intent, the slug was wrong; re-issue or fail loud. - International locations use reversed slug grammar.
de--be--berlin(US-style) fails and falls back to IP.berlin--de(city--country) works and resolves to Berlin (52.52, 13.38). Other examples:london--gb,paris--fr,tokyo--jp. The state/region middle segment doesn't exist for non-US cities. source=EVENTSis mandatory. Without it the find page rendersrecommendedEvents(ML-popular events near you) — a completely different ROOT_QUERY that ignoreskeywords=,eventType=,distance=, etc. Always includesource=EVENTS.categoryId=URL param maps totopicCategoryIdin the GraphQL filter. Don't passtopicCategoryId=on the URL — it's silently ignored. UsecategoryId=<numeric>. Verified enum (extracted from_next/static/chunks/73326...js):521=Art & Culture,593=Beliefs & Religion,405=Career & Business,604=Community & Environment,612=Dancing,436=Science & Education,535=Games,522=Health & Wellbeing,622=Identity & Language,395=Music,684=Travel & Outdoor,673=Parents & Family,701=Pets & Animals,652=Social Activities,482=Sports & Fitness,546=Technology,467=Writing.- "Synthetic" categories don't have a numeric ID. Movements & Politics, Photography, LGBTQ, Singles, Fashion & Beauty, Film, Fitness, Food & Drink, Hobbies & Passions, Book Clubs, Lifestyle, Women — these are surfaced by Meetup's category UI but resolve to keyword rewrites under the hood (e.g. Photography →
keywords=photography, LGBTQ →keywords=queer%20lgbtq). For these intents, usekeywords=...instead ofcategoryId=. eventTypeaccepts onlyonlineandinPerson.eventType=physical(the literal GraphQL enum value) is dropped silently. The URL paraminPersonis normalized toPHYSICALin the filter;onlinetoONLINE. To get both (the default), omit the param entirely.sortFieldis case-sensitive.sortField=DATETIMEworks;sortField=datetimesilently falls back toRELEVANCE. Same forRELEVANCE,DISTANCE.dateRange=is mostly UI-only. OnlydateRange=todayis honored at the SSR layer (setsfilter.startDateRangeto now andfilter.endDateRangeto end-of-day).this_week,this_weekend,next_week,tomorrowecho intofiltersbut don't reach the eventSearch filter — the find UI applies them client-side after hydration, so an SSR-only consumer sees the unfiltered page-1 results. Workaround: use the (broken)customStartDate/customEndDateif it ever gets fixed, or post-filter onEvent.dateTimeafter extraction.customStartDate=YYYY-MM-DD&customEndDate=...returns 500. The SSR resolver throws on this combination. Don't construct URLs that include these — the page won't render at all. Post-filter onEvent.dateTimeafter extraction.isHappeningNow,isStartingSoon,isFree, time-of-day buckets — all UI-only. These exist asBooleanvariables in theeventSearchWithSeriesoperation but the find-page SSR doesn't pass them through from the URL. Either (a) post-filter onEvent.dateTimeandEvent.feeSettings, or (b) use the Browser-fallback path and POST the GraphQL operation with these vars set.- No URL pagination.
page=2,after=<cursor>,offset=20,cursor=...,endCursor=...are all silently ignored.pageInfo.endCursoris a base64-encoded offset (e.g.MTI=decodes to "12"); it's only useful when POSTed to the GraphQL endpoint as theaftervariable. The endpoint POST URL ishttps://www.meetup.com/gql2(GETreturns 404 — endpoint is POST-only).bb fetchis GET-only, so to actually paginate you need a--connect-attached browser session. - Find-page Event entity is partial. It carries
id,title,dateTime,description,eventType,eventUrl,rsvpState,maxTickets,feeSettings,venue(name/address/city/state/country but no lat/lon), and refs togroup,featuredEventPhoto. It does not carryendTime,topics,eventHosts,rsvps.totalCount. Visit the canonical event URL (step 7 above) to get those. maxTickets: 0means unlimited, not zero. Map tocapacity: nullin your output, notcapacity: 0.- Two event ID formats. Numeric (
314579537) for standalone events; alphanumeric (rmcjwtyjckbtb,qltprtyjcjbwb) for individual instances of recurring event series. Both work in the canonical URL (/<group-slug>/events/<id>/). - Online platform is unstructured. When
eventType=ONLINE,venueis null and there is no structuredonline_platformfield — Meetup leaves the host to mention "Zoom / Google Meet / Hopin / Discord" in the free-text description. Best-effort: regex-scan the description for known platform names; treat asnullwhen none match. - Group page (
/<slug>/) ≠ group events page (/<slug>/events/). The bare slug hydrates 1–8 "featured/preview" events; the/events/subpath hydrates the full upcoming list (up to 30) underGroup.events({...filter})— different ROOT_QUERY path, richer event schema. Always use/<slug>/events/when listing a group's upcoming events. - Group-event page hydration is the richest available without a detail-page hop. Each event includes
endTime,going,feeSettings,eventHosts,actions,isOnline,socialLabels,topics— i.e. nearly everything an event-detail page has. Prefer this surface when the input is a group. featuredEventPhoto.highResUrlis the full-size photo. The same entity hasbaseUrl+idfor templated sizes (<baseUrl>/<id>/676x676.jpg,676x507.jpg,676x380.jpg).- Group
lat/lononly present on group-event pages. Group entity on find/search pages omits coordinates; group entity on/<slug>/events/includeslat,lon,organizer,welcomeBlurb,memberships. - Read-only enforcement. Never click any of:
Attend / RSVP,Join this group,Save,Sign In,Sign Up, or anyactions[]entries returned on the Event (those are RSVP-state mutations). All extraction is page-load only.
Expected Output
Three distinct shapes:
// 1. Events found
{
"success": true,
"query": { "keywords": "AI", "location": "us--ca--san-francisco", "eventType": null, "distance": null, "categoryId": null, "sortField": "DATETIME" },
"resolved_location": { "city": "San Francisco", "state": "CA", "country": "us", "lat": 37.78, "lon": -122.42, "zip": "94102", "timezone": "US/Pacific" },
"total_count": 30,
"page_info": { "has_next_page": true, "end_cursor": "MTI=" },
"events": [
{
"event_id": "314579537",
"title": "Vibe Code LA Meetup Event",
"event_url": "https://www.meetup.com/vibe-code-la/events/314579537/",
"description": "We're back, LA! ...",
"format": "in_person",
"start_at": "2026-05-27T18:00:00-07:00",
"end_at": "2026-05-27T20:00:00-07:00",
"duration_minutes": 120,
"rsvp_state": "JOIN_OPEN",
"going_count": 57,
"waitlist_count": 0,
"capacity": null,
"is_free": true,
"price": null,
"photo_url": "https://secure-content.meetupstatic.com/images/classic-events/534004625/highres_534004625.jpeg",
"topics": [
{ "id": "488822", "name": "Artificial Intelligence", "urlkey": "artificial-intelligence" }
],
"hosts": [
{ "member_id": "930091", "name": "Matt", "photo_url": "https://..." }
],
"venue": {
"id": "28001128", "name": "Total Wine",
"address": "11441 Jefferson Blvd",
"city": "Culver City", "state": "CA", "country": "us",
"lat": 33.99, "lon": -118.39706
},
"online_platform": null,
"is_featured": false,
"is_network_event": false,
"group": {
"id": "38287434", "name": "Vibe Code LA", "slug": "vibe-code-la",
"url": "https://www.meetup.com/vibe-code-la",
"city": "Santa Monica", "state": "CA", "country": "us",
"member_count": 342,
"photo_url": "https://...",
"category": { "id": "546", "name": "Technology", "urlkey": "technology" },
"active_topics": [ { "id": "488822", "name": "Artificial Intelligence" } ],
"rating": { "average": 4.83, "total": 18 }
}
}
]
}
// 2. Search executed, zero results
{
"success": true,
"query": { "keywords": "underwater-basket-weaving", "location": "us--mt--billings", "eventType": null, "distance": "tenMiles" },
"resolved_location": { "city": "Billings", "state": "MT", "country": "us", "lat": 45.78, "lon": -108.50 },
"total_count": 0,
"page_info": { "has_next_page": false, "end_cursor": null },
"events": []
}
// 3. Location slug malformed — fell back to request IP
{
"success": false,
"reason": "location_not_resolved",
"input_location": "us--ca--san_francisco",
"resolved_to": { "city": "La Canada Flintridge", "state": "CA", "country": "us", "lat": 34.21, "lon": -118.20 },
"hint": "Location slug uses dashes between words, not underscores. Try `us--ca--san-francisco`."
}
For online-only events (format: "online"): venue is null, online_platform is "zoom" | "google_meet" | "hopin" | "discord" | null (best-effort regex match against description). For paid events: is_free: false, price: { amount: <decimal>, currency: <ISO-4217>, accepts: ["CARD","PAYPAL",...] }.
How to use search-events on Cursor
AI-first code editor with Composer
Prerequisites
Before installing skills in Cursor, ensure your development environment meets these requirements:
- ›Cursor installed and configured on your development machine
- ›Node.js version 16.0+ with npm package manager (verify with
node --version) - ›Active project directory or workspace where you want to add search-events
Execute installation command
Execute the skills CLI command in your project's root directory to begin installation:
The skills CLI fetches search-events from GitHub repository meetup.com/search-events-8bdsvy and configures it for Cursor.
Select Cursor when prompted
The CLI will show a list of available agents. Use arrow keys to navigate and space to select Cursor:
Verify installation
Confirm successful installation by checking the skill directory location:
Reload or restart Cursor to activate search-events. Access the skill through slash commands (e.g., /search-events) or your agent's skill management interface.
Security & Verification Notice
We perform automated surface-level scans (Gen AI Scanner, Socket, Snyk) during installation. These checks detect common vulnerabilities but do not guarantee complete security. Always review skill source code and verify the publisher's reputation before production use.
Skills execute code in your development environment. Always verify the publisher's identity, review recent commits, and test in isolated environments before production deployment.
List & Monetize Your Skill
Submit your Claude Code skill and start earning
Use Cases▌
Task Automation & Efficiency
Automate repetitive workflows and reduce manual effort
Example
Generate reports, summarize documents, draft communications
Save 3-5 hours per week on routine tasks
Knowledge Enhancement
Learn new skills, understand complex topics, get expert guidance
Example
Explain concepts, provide examples, suggest learning resources
Accelerate learning and skill development by 2x
Quality Improvement
Enhance output quality through reviews, suggestions, and refinements
Example
Review drafts, suggest improvements, catch errors
Improve work quality by 30-40% with less effort
Implementation Guide▌
Prerequisites
- ›Claude Desktop or compatible AI client with skill support
- ›Clear understanding of task or problem to solve
- ›Willingness to iterate and refine outputs
Time Estimate
15-45 minutes depending on use case complexity
Installation Steps
- 1.Install skill using provided installation command
- 2.Test with simple use case relevant to your work
- 3.Evaluate output quality and relevance
- 4.Iterate on prompts to improve results
- 5.Integrate into regular workflow if valuable
Common Pitfalls
- ⚠Expecting perfect results without iteration
- ⚠Not providing enough context in prompts
- ⚠Using skill for tasks outside its intended scope
- ⚠Accepting outputs without review and validation
Best Practices▌
✓ Do
- +Start with clear, specific prompts
- +Provide relevant context and constraints
- +Review and refine all outputs before using
- +Iterate to improve output quality
- +Document successful prompt patterns
✗ Don't
- −Don't use without understanding skill limitations
- −Don't skip validation of outputs
- −Don't share sensitive information in prompts
- −Don't expect skill to replace human judgment
💡 Pro Tips
- ★Be specific about desired format and style
- ★Ask for multiple options to choose from
- ★Request explanations to understand reasoning
- ★Combine AI efficiency with human expertise
When to Use This▌
✓ Use When
Use when skill capabilities match your task, clear ROI on time saved, and you can validate outputs. Best for repetitive tasks, learning, and quality improvement.
✗ Avoid When
Avoid when task requires deep expertise you can't validate, involves sensitive decisions, or when learning process is more valuable than speed of completion.
Learning Path▌
- 1Familiarize yourself with skill capabilities and limitations
- 2Start with low-risk, non-critical tasks
- 3Progress to more complex and valuable use cases
- 4Build expertise through regular use and experimentation
Discussion
Product Hunt–style comments (not star reviews)- No comments yet — start the thread.
Ratings
4.8★★★★★39 reviews- ★★★★★Pratham Ware· Dec 28, 2024
search-events fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.
- ★★★★★Yusuf Ghosh· Dec 16, 2024
We added search-events from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
- ★★★★★Sakshi Patil· Nov 19, 2024
search-events is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.
- ★★★★★Layla Zhang· Nov 7, 2024
Keeps context tight: search-events is the kind of skill you can hand to a new teammate without a long onboarding doc.
- ★★★★★Noor Ghosh· Oct 26, 2024
search-events is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.
- ★★★★★Chaitanya Patil· Oct 10, 2024
Keeps context tight: search-events is the kind of skill you can hand to a new teammate without a long onboarding doc.
- ★★★★★Hassan Diallo· Sep 17, 2024
search-events reduced setup friction for our internal harness; good balance of opinion and flexibility.
- ★★★★★Aditi Huang· Sep 13, 2024
Useful defaults in search-events — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.
- ★★★★★Isabella Chen· Sep 9, 2024
We added search-events from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
- ★★★★★Piyush G· Sep 1, 2024
Registry listing for search-events matched our evaluation — installs cleanly and behaves as described in the markdown.
showing 1-10 of 39