# Luma Events Scraper (`parsebird/luma-events-scraper`) Actor

Scrape Luma (lu.ma) events by city, category, community calendar, search query, or direct URL. Get schedule, location, ticketing, hosts, and registration data.

- **URL**: https://apify.com/parsebird/luma-events-scraper.md
- **Developed by:** [ParseBird](https://apify.com/parsebird) (community)
- **Stats:** 2 total users, 1 monthly users, 66.7% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.89 / 1,000 events

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### Luma Events Scraper

Luma Events Scraper extracts event data from [Luma](https://lu.ma) (lu.ma) — the event platform behind thousands of tech, crypto, AI, and community calendars — by city, category, community calendar, search query, or direct URL.

<table><tr>
<td style="border-left:4px solid #1C1917;padding:12px 16px;font-weight:600">
Mix Luma URLs and free-text searches in one run, filter by category, date range, event type, and price, and get schedule, venue, ticketing, hosts, and registration-question data for every matching event.
</td>
</tr></table>

##### Copy to your AI assistant

```
Use the Apify actor "parsebird/luma-events-scraper" via the ApifyClient to scrape Luma (lu.ma) events. Example: client.actor("parsebird/luma-events-scraper").call(run_input={"discoverCity": "sf", "category": "ai", "maxResults": 250}). Inputs: lumaUrls (array of strings, any Luma URL type — event, calendar, community, city, category, discover, or user-profile, default ["https://lu.ma/discover"]), searchQueries (array of strings, free-text search against Luma's discover feed, up to 50 matches each), discoverCity (string, a Luma city handle like "sf" or "nyc", not the full city name), category (enum: ai/tech/crypto/food/arts/climate/fitness/wellness), dateFrom/dateTo (YYYY-MM-DD), eventType (all/in_person/virtual), pricing (all/free/paid), scrapeEventDetails (boolean, default true, fetches description/ticketTypes/registrationQuestions/locale/categoryNames), includeFeaturedGuests (boolean, default false), maxEventsPerUrl (integer, default 1000, 0=unlimited), maxResults (integer, default 1000, 0=unlimited up to a 50,000 safety cap). Output fields per event include eventId, eventUrl, name, description, startAt, endAt, timezone, eventType, categoryNames, location (name/address/neighborhood/city/region/country/coordinates/isVirtual), organizer, hosts, featuredGuests, ticketing (isFree/minPrice/maxPrice/currency/spotsRemaining), ticketTypes, registrationQuestions, guestCount, detailsFetched, sourceUrl, sourceQuery, and scrapedAt. Full API spec: https://apify.com/parsebird/luma-events-scraper/api. Get an API token at https://console.apify.com/settings/integrations.
```

### What does Luma Events Scraper do?

Luma Events Scraper is a search and listing scraper for **lu.ma**, the event platform widely used by tech meetups, crypto conferences, AI communities, and recurring city calendars. Point it at a city, a category, a community's calendar, a search term, or a specific event URL, and it returns structured event data ready for a spreadsheet, CRM, or lead list.

- 📍 Accepts any mix of Luma URLs in one run — event, calendar/community, city, category, discover, or user-profile pages
- 🔍 Free-text search queries run against Luma's own discover feed, independent of any URL
- 🏙️ City targeting by Luma's short handle (`sf`, `nyc`, `london`, `tokyo`, `berlin`, and more)
- 🎯 Filter by category (AI, Tech, Crypto, Food & Drink, Arts & Culture, Climate, Fitness, Wellness), date range, event type, and price
- 📝 Full event details on request: clean plain-text description, ticket tiers with prices, category labels, and public registration questions
- 🌟 Optional featured-guest list per event
- 🏷️ Rich host and organizer data with social handles (Twitter, Instagram, LinkedIn, YouTube, TikTok, website)
- ⚙️ Runs on Apify's infrastructure with scheduling, API access, and integrations

### Input parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| lumaUrls | array of strings | No\* | `["https://lu.ma/discover"]` | Luma URLs of any type — event, calendar, community, city, category, discover, or user-profile. Mix freely in one list. |
| searchQueries | array of strings | No\* | `[]` | Free-text queries run against Luma's discover feed. Each runs independently, up to 50 best matches. |
| discoverCity | string | No\* | — | Luma city handle (the handle in `lu.ma/<handle>`), e.g. `sf`, `nyc`, `london`. An unrecognized handle stops the run with a clear message. |
| category | enum | No | All categories | `ai`, `tech`, `crypto`, `food`, `arts`, `climate`, `fitness`, or `wellness`. Combines with `discoverCity`, `lumaUrls`, and `searchQueries`. |
| dateFrom | date | No | — | Only events starting on or after this date (`YYYY-MM-DD`). |
| dateTo | date | No | — | Only events starting on or before this date. Triggers an early stop on ascending feeds. |
| eventType | enum | No | All | `all`, `in_person`, or `virtual`. |
| pricing | enum | No | All | `all`, `free`, or `paid`. |
| scrapeEventDetails | boolean | No | `true` | Fetch each event's full page for description, ticket types, category labels, and registration questions. |
| includeFeaturedGuests | boolean | No | `false` | Attach Luma's public featured-guest list (up to 10 per event). |
| maxEventsPerUrl | integer | No | `1000` | Cap on events per URL or search query. `0` = no per-source cap. |
| maxResults | integer | No | `1000` | Hard cap on total rows across every source. `0` = unlimited (internal safety cap of 50,000). |

\* At least one of `lumaUrls`, `searchQueries`, or `discoverCity` should be set. If all three are empty, the run falls back to `https://lu.ma/discover`.

#### Quickest start — pull this week's discover feed

```json
{
  "lumaUrls": ["https://lu.ma/discover"],
  "maxResults": 100
}
```

#### Find AI events in San Francisco

```json
{
  "discoverCity": "sf",
  "category": "ai",
  "maxResults": 250
}
```

#### Track a community calendar

```json
{
  "lumaUrls": ["https://lu.ma/superteam"],
  "scrapeEventDetails": true,
  "includeFeaturedGuests": true,
  "maxResults": 500
}
```

#### Wide-net research — paid crypto events worldwide for the next month

```json
{
  "lumaUrls": [
    "https://lu.ma/crypto",
    "https://lu.ma/nyc",
    "https://lu.ma/london",
    "https://lu.ma/sf"
  ],
  "searchQueries": ["Web3", "DeFi", "blockchain"],
  "category": "crypto",
  "pricing": "paid",
  "dateFrom": "2026-06-01",
  "dateTo": "2026-06-30",
  "scrapeEventDetails": true,
  "maxResults": 2000
}
```

### What data can you extract from Luma?

| Field | Description |
|-------|-------------|
| name, description, startAt, endAt, timezone | Core event details |
| eventType, categoryNames | In-person/virtual flag and Luma's own category labels |
| location.city, location.name, location.address, location.isVirtual | Venue and geolocation |
| organizer, hosts, featuredGuests | People running and featured on the event, with social handles |
| ticketing.isFree, ticketing.minPrice, ticketing.maxPrice, ticketing.spotsRemaining | Ticketing summary |
| ticketTypes | Per-tier price, availability, and capacity |
| registrationQuestions | Public RSVP form fields (label, type, required) |
| guestCount, detailsFetched, sourceUrl, sourceQuery, scrapedAt | Metadata for reconciling and auditing rows |

### Output example

```json
{
  "eventId": "evt-7jzkcmnq",
  "eventUrl": "https://luma.com/7jzkcmnq",
  "name": "AI Founders Dinner — SF",
  "description": "An intimate dinner for AI founders building in production...",
  "startAt": "2026-06-12T01:00:00.000Z",
  "endAt": "2026-06-12T04:00:00.000Z",
  "timezone": "America/Los_Angeles",
  "eventType": "in_person",
  "categoryNames": ["AI", "Tech"],
  "location": {
    "name": "South Park Commons",
    "address": "529 Bryant St, San Francisco, CA 94107",
    "city": "San Francisco",
    "country": "United States",
    "isVirtual": false
  },
  "organizer": { "name": "Jane Doe", "slug": "janedoe", "profileUrl": "https://luma.com/user/janedoe" },
  "ticketing": { "isFree": false, "minPrice": 25.0, "maxPrice": 100.0, "currency": "USD" },
  "guestCount": 42,
  "detailsFetched": true,
  "sourceUrl": "https://luma.com/discover/sf/ai",
  "sourceQuery": null,
  "scrapedAt": "2026-06-01T14:32:11.421Z"
}
```

Download results as **JSON, CSV, Excel, HTML, or XML** from the Apify Console, or pull them programmatically through the [Apify API](https://docs.apify.com/api/v2).

### How to scrape Luma events

1. Open **Luma Events Scraper** on the Apify Store and click **Try for free**.
2. Add one or more Luma URLs, a city handle, or search terms.
3. Set **Category**, **Date from/to**, **Event type**, and **Pricing** to narrow the results.
4. Set **Max results** and click **Start**.
5. Open the **Dataset** tab to view, filter, and export the scraped events.

### How it works

1. For each Luma URL, the Actor reads the page's own server-rendered data to identify whether it's a city, category, community calendar, single event, or user profile.
2. It paginates that source's event feed, applying date, event-type, and pricing filters as it goes — stopping early once a date-ordered feed passes `dateTo`.
3. For each event kept, if `scrapeEventDetails` is on, it fetches the event's own page for description, ticket types, category labels, and registration questions.
4. Every unique event (deduplicated across all sources in the run) is written as one dataset row.

### How much does it cost to scrape Luma?

Luma Events Scraper uses **pay-per-event** pricing — you're charged only for unique events actually saved to your dataset.

| Event | Price per event | Price per 1,000 |
|-------|------------------|------------------|
| event-scraped | $0.00249 (Free plan) | **$2.49** |

Paid Apify plans unlock lower rates ($2.29/1,000 on Bronze, $2.09/1,000 on Silver, $1.89/1,000 on Gold). Apify's [monthly platform usage credits](https://apify.com/pricing) apply to this Actor like any other.

### Using the API

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run = client.actor("parsebird/luma-events-scraper").call(run_input={
    "discoverCity": "sf",
    "category": "ai",
    "maxResults": 250,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["name"], item["startAt"])
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });

const run = await client.actor('parsebird/luma-events-scraper').call({
    discoverCity: 'sf',
    category: 'ai',
    maxResults: 250,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

Schedule recurring runs to track a city's events week over week, or connect it to Zapier/Make through Apify's [integrations](https://apify.com/integrations).

### Is it legal to scrape Luma?

Scraping publicly available data — like event listings and details shown on a public Luma page — is generally considered legal, and courts have repeatedly upheld this for public web pages. This Actor only collects data Luma already displays to any visitor; it never accesses private guest lists or attendee data, which Luma keeps organizer-only. You are responsible for how you use the collected data and for complying with Luma's terms of service and applicable law in your jurisdiction. See Apify's [blog post on the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) for more detail.

### Related Actors

- [Meetup Events Scraper](https://apify.com/parsebird/meetup-events-scraper) — events, groups, and RSVP data from Meetup.com
- [StubHub Event Scraper](https://apify.com/parsebird/stubhub-event-scraper) — ticketed event listings from StubHub

### FAQ

**What's the difference between `discoverCity` and putting a city URL in `lumaUrls`?**
They resolve to the same place — `discoverCity: "sf"` is a convenience for `lumaUrls: ["https://lu.ma/sf"]`. The one difference: an unrecognized `discoverCity` handle fails the run with a clear message, so you know immediately if a handle is wrong, rather than silently getting nothing.

**Why are some fields empty even with `scrapeEventDetails` on?**
Some fields are optional for organizers — `categoryNames` is empty for roughly one event in ten because picking a category isn't required, and `location.name`/`location.address` are empty when the host keeps the venue address for registered guests only. Check `detailsFetched` to confirm the full page was actually read for that row.

**Does category filtering work on community calendars and user profiles?**
Yes, but it always fetches each event's full detail page to check its category labels, regardless of the `scrapeEventDetails` toggle, since that's the only place category data lives.

**Why did my `searchQueries` return fewer than 50 results?**
Luma's search ranks by relevance, not volume — a narrow or unusual query may simply have fewer than 50 good matches.

**Can I get private attendee lists?**
No. Luma only ever exposes a public featured-guest list (up to 10 people) and aggregate guest counts. Full attendee lists are organizer-only in Luma itself and are never available through this Actor.

**Can I schedule recurring runs?**
Yes. Use Apify's [Scheduler](https://docs.apify.com/platform/schedules) to run this Actor daily, weekly, or at any interval.

**Does this Actor have an API?**
Yes — every Apify Actor is automatically available as an API. See the [API tab](https://apify.com/parsebird/luma-events-scraper/api) for the full spec, or use the Python/JavaScript examples above.

**Something not working?**
Report it on the Actor's **Issues** tab in Apify Console — Luma occasionally changes its site, and prompt reports help keep this Actor maintained.

# Changelog

This Actor's version history is a separate document: https://apify.com/parsebird/luma-events-scraper/changelog.md

# Actor input Schema

## `lumaUrls` (type: `array`):

Luma URLs of any type — event, calendar, community, city, category, discover, or user-profile. Mix freely in one list. When this, Search queries, and Discover city are all empty, the run falls back to https://lu.ma/discover.

## `searchQueries` (type: `array`):

Free-text queries run against Luma's discover feed (e.g. "AI Tokyo", "Brooklyn music"). Each runs independently and returns up to 50 best matches.

## `discoverCity` (type: `string`):

Luma city handle, not the full city name: sf, nyc, la, london, tokyo, berlin, paris, singapore, toronto, amsterdam, sydney, mumbai, dubai, seoul, and more — it's the handle in the city's Luma address (lu.ma/<handle>). An unrecognized handle stops the run with a message rather than returning another city's events.

## `category` (type: `string`):

Restrict to one category. Combines with Discover city, Luma URLs, and Search queries.

## `dateFrom` (type: `string`):

Only include events starting on or after this date.

## `dateTo` (type: `string`):

Only include events starting on or before this date. Triggers an early stop on feeds that list events in ascending date order.

## `eventType` (type: `string`):

Restrict to in-person or virtual events.

## `pricing` (type: `string`):

Restrict to free or paid events.

## `scrapeEventDetails` (type: `boolean`):

Fetch each event's full page for description, ticket types, category labels, richer hosts, and registration questions. Turn off for faster, lighter runs — those fields then come back empty.

## `includeFeaturedGuests` (type: `boolean`):

Attach Luma's public featured-guest list (up to 10 names per event). Full attendee lists are organizer-only and never available publicly.

## `maxEventsPerUrl` (type: `integer`):

Cap on events per URL or search query. Set 0 for no per-source cap.

## `maxResults` (type: `integer`):

Hard cap on total rows across every source. 0 = unlimited (internal safety cap of 50,000).

## Actor input object example

```json
{
  "lumaUrls": [
    "https://lu.ma/discover"
  ],
  "searchQueries": [],
  "category": "",
  "eventType": "all",
  "pricing": "all",
  "scrapeEventDetails": true,
  "includeFeaturedGuests": false,
  "maxEventsPerUrl": 20,
  "maxResults": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "lumaUrls": [
        "https://lu.ma/discover"
    ],
    "maxEventsPerUrl": 20,
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/luma-events-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "lumaUrls": ["https://lu.ma/discover"],
    "maxEventsPerUrl": 20,
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/luma-events-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "lumaUrls": [
    "https://lu.ma/discover"
  ],
  "maxEventsPerUrl": 20,
  "maxResults": 20
}' |
apify call parsebird/luma-events-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parsebird/luma-events-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/xRgdcs6mK0VqooTNh/builds/1mPp585fH68zlEwpQ/openapi.json
