# Luma Event & Attendee Scraper - Cheapest (`doin2much/luma-attendee-scraper`) Actor

Scrape hosted Luma events and full guest/attendee lists (email, LinkedIn, X/Twitter, Instagram, TikTok, YouTube, website, phone, bio, registration answers, check-in status) using a host session cookie.

- **URL**: https://apify.com/doin2much/luma-attendee-scraper.md
- **Developed by:** [Neel Majmudar](https://apify.com/doin2much) (community)
- **Categories:** Automation, Lead generation, Business
- **Stats:** 2 total users, 2 monthly users, 75.0% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### What does Luma Event & Attendee Scraper do?

**Luma Event & Attendee Scraper** scrapes **hosted events** and their **full guest / attendee lists** from [Luma](https://lu.ma) using a host session cookie. It calls Luma’s private JSON API (`api.lu.ma`) — the same surfaces as the host dashboard — so you get event metadata **plus** rich attendee profiles: email, phone, bio, **LinkedIn, X/Twitter, Instagram, TikTok, YouTube, website**, location, RSVP/check-in status, UTM/referral, and registration answers.

Runs on the [Apify](https://apify.com) platform with scheduling, monitoring, API access, and integrations.

### Why use Luma Event & Attendee Scraper?

- Export full attendee CRM lists (email + socials) from events you host
- Sync hosted event catalogs and guest status counts into spreadsheets or pipelines
- Backfill past events and monitor upcoming ones on a schedule
- Avoid browser automation: authenticated HTTP only (fast and predictable)

### How to use Luma Event & Attendee Scraper

1. Open the Actor in [Apify Console](https://console.apify.com).
2. Paste your Luma host session cookie into **Luma session cookie** (`sessionCookie`).
3. Leave **Include attendees** on (default) to scrape guest lists with socials. Optionally keep **Include guest status counts** on for approved/waitlist/checked-in breakdowns.
4. Choose **Event period** (`all`, `past`, or `future`). Use **Max events** while testing.
5. Click **Start**. Raise **Max total charge USD** if you need more than ~500 attendees (platform default is often ~$5 ≈ 1 event + ~495 attendees at $0.01 each).
6. Open **Output**: **Attendees** (default dataset) and **Events** (separate dataset). Storage → Dataset dropdown also lists both.

#### How to get the Luma session cookie

1. Sign in to [lu.ma](https://lu.ma) with a **host** account.
2. Open DevTools → Application (or Storage) → Cookies → `lu.ma`.
3. Copy the value of `luma.auth-session-key`.
4. Paste the raw value **or** `luma.auth-session-key=...` into `sessionCookie`.

Sessions expire. A 401 means refresh the cookie; a 403 usually means the cookie is not a host/admin session.

### Input

| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `sessionCookie` | string (secret) | yes | — | Raw `luma.auth-session-key` or full cookie string |
| `period` | enum | no | `all` | `all`, `past`, or `future` |
| `maxEvents` | integer | no | `0` | Cap on events (`0` = no cap) |
| `maxAttendeesPerEvent` | integer | no | `0` | Cap attendees scraped per event (`0` = no cap); stops guest pagination early |
| `maxAttendees` | integer | no | `0` | Cap total attendees across the whole run (`0` = no cap) |
| `includeGuestCounts` | boolean | no | `true` | Nested `guestCounts` status breakdown on event rows |
| `includeGuests` | boolean | no | `true` | Emit one attendee dataset row per guest (billed per row) |

#### Example input

```json
{
    "sessionCookie": "YOUR_LUMA_AUTH_SESSION_KEY",
    "period": "all",
    "maxEvents": 0,
    "maxAttendeesPerEvent": 500,
    "maxAttendees": 5000,
    "includeGuestCounts": true,
    "includeGuests": true
}
```

### Output

Events and attendees are stored in **separate datasets** (Apify views cannot filter a mixed dataset by `recordType`):

| Dataset | PPE charge | Meaning |
| --- | --- | --- |
| **Events** (`events`) | `event-scraped` (**$0.01** each) | One row per hosted event (metadata + counts; no nested guests) |
| **Attendees** (`default`) | `attendee-scraped` (**$0.01** each / $10 per 1,000) | One row per guest with email/socials/status + parent event fields |

Example: 1 event + 495 attendees ⇒ **$4.96** PPE (plus a tiny actor-start fee). As the **Actor owner**, Console may show only platform compute (~$0.02) because your own runs are not billed for PPE — check the run’s `chargedEventCounts` to verify event/attendee charges.

#### Example event row

```json
{
    "recordType": "event",
    "lumaApiId": "evt-xxxxxxxx",
    "lumaUrl": "your-event-slug",
    "name": "Founder meetup",
    "coverImageUrl": "https://images.lumacdn.com/...",
    "address": "123 Market St, San Francisco, CA",
    "city": "San Francisco",
    "country": "United States",
    "countryCode": "US",
    "descriptionShort": "An evening for founders",
    "startAt": "2026-07-20T18:00:00+00:00",
    "endAt": "2026-07-20T21:00:00+00:00",
    "timezone": "America/Los_Angeles",
    "guestCountApproved": 42,
    "guestCounts": {
        "approved": 42,
        "checkedIn": 30,
        "declined": 2,
        "invited": 10,
        "joinedOnline": 0,
        "notCheckedIn": 12,
        "pendingApproval": 0,
        "session": 0,
        "waitlist": 5
    },
    "scrapedAttendeeCount": 42
}
```

#### Example attendee row

```json
{
    "recordType": "attendee",
    "eventName": "Founder meetup",
    "eventLumaApiId": "evt-xxxxxxxx",
    "eventLumaUrl": "your-event-slug",
    "eventStartAt": "2026-07-20T18:00:00+00:00",
    "eventCity": "San Francisco",
    "eventCountry": "United States",
    "lumaGuestApiId": "gst-xxxxxxxx",
    "lumaUserApiId": "usr-xxxxxxxx",
    "email": "alex@example.com",
    "name": "Alex Founder",
    "firstName": "Alex",
    "lastName": "Founder",
    "phone": "+1…",
    "avatarUrl": "https://…",
    "bio": "Building something new",
    "linkedinHandle": "in/alexfounder",
    "twitterHandle": "alexfounder",
    "instagramHandle": null,
    "tiktokHandle": null,
    "youtubeHandle": null,
    "website": "https://example.com",
    "city": "San Francisco",
    "country": "United States",
    "locale": "en-US",
    "approvalStatus": "approved",
    "registeredAt": "2026-06-01T18:00:00+00:00",
    "registeredOrCreatedAt": "2026-06-01T18:00:00+00:00",
    "checkedInAt": null,
    "lastCheckedInAt": null,
    "invitedAt": null,
    "joinedAt": null,
    "hasJoinedEvent": false,
    "declineMessage": null,
    "utmSource": "newsletter",
    "referredByUserApiId": null,
    "registrationAnswers": []
}
```

If a run scrapes 10 events and 2,000 attendees, the dataset has **2,010 items** and billing is approximately `(10 × $0.01) + (2,000 × $0.01) = $20.10` plus the Actor start event.

### Attendee schema (emphasized)

Every **attendee** dataset row includes these Luma admin guest-list fields:

| Field | Description |
| --- | --- |
| `lumaGuestApiId` | Guest row id |
| `lumaUserApiId` | Luma user id |
| `email` / `name` / `firstName` / `lastName` | Identity |
| `phone` / `avatarUrl` / `bio` | Contact & profile |
| `linkedinHandle` | LinkedIn |
| `twitterHandle` | X / Twitter |
| `instagramHandle` | Instagram |
| `tiktokHandle` | TikTok |
| `youtubeHandle` | YouTube |
| `website` | Personal / company site |
| `city` / `country` / `locale` | Geo / locale |
| `approvalStatus` | e.g. approved, pending\_approval, waitlist |
| `registeredAt` / `registeredOrCreatedAt` / `invitedAt` / `joinedAt` | Lifecycle timestamps |
| `checkedInAt` / `lastCheckedInAt` / `hasJoinedEvent` | Check-in / join |
| `declineMessage` | Decline note when present |
| `utmSource` / `referredByUserApiId` | Attribution |
| `registrationAnswers` | Event-specific Q\&A (JSON array) |

**Not included** (intentionally omitted, same as our internal product mapping): ticket purchase objects, pending revenue, crypto/web3 wallet fields, and Luma internal proxy keys.

### Event data table

| Field | Description |
| --- | --- |
| `lumaApiId` | Luma event API id |
| `lumaUrl` | Event URL slug |
| `name` | Event title |
| `startAt` / `endAt` | Schedule (ISO-8601) |
| `city` / `country` / `countryCode` / `address` | Location |
| `guestCountApproved` | Approved count from host role |
| `guestCounts` | Optional status breakdown on **event** rows |
| `scrapedAttendeeCount` | How many **attendee** rows were produced/charged for that event |
| Attendee fields (`email`, socials, …) | On **attendee** rows only — see schema above |

### Pricing / Cost estimation

How much does it cost to scrape Luma events and attendees? This Actor uses **pay-per-event (PPE)** pricing:

| Charge event | Price | When charged |
| --- | --- | --- |
| `event-scraped` | **$0.01** per event | Each event dataset row |
| `attendee-scraped` | **$0.01** per attendee ($10 / 1,000) | Each attendee dataset row |
| `apify-actor-start` | Apify default (very low) | Actor run start (covers first seconds of compute) |

Example: scrape 10 events with 2,000 total attendees → `(10 × $0.01) + (2,000 × $0.01) = $20.10` (plus the tiny start event), before any Store discounts. Use `maxAttendees` / `maxAttendeesPerEvent` to cap spend.

HTTP-only scraping keeps platform usage low relative to these event charges. Set a **max total charge** on the run if you want a hard spending cap.

### Tips or Advanced options

- Prefer `period: "future"` for recurring sync jobs.
- Set `maxEvents` while testing before scraping multi-thousand guest lists (guest pages use ~1.2s delays).
- Turn off `includeGuests` only when you need event metadata / counts without PII.
- Cookie must be from a **host** account with admin access to the events.

### FAQ, disclaimers, and support

**Is scraping Luma allowed?** Only scrape data you are authorized to access — typically **your own** hosted events. Respect Luma’s Terms of Service and privacy laws when handling guest PII.

**Why 401?** Session expired — refresh `luma.auth-session-key`.

**Why 403?** Not a host/admin cookie for those events.

**Does this search public Luma events by keyword?** No. It lists **hosted** events for the authenticated host and their admin guest lists — not public keyword/location search.

Open the Actor **Issues** tab for feedback, or ask about custom CRM / webhook integrations.

# Actor input Schema

## `sessionCookie` (type: `string`):

Your Luma auth session cookie. Paste the raw `luma.auth-session-key` value, or the full `luma.auth-session-key=...` cookie string. Must belong to a host account that can access admin guest lists.

## `period` (type: `string`):

Which hosted events to fetch: past, future, or both (all).

## `maxEvents` (type: `integer`):

Maximum number of hosted events to scrape. Use 0 for no cap.

## `maxAttendeesPerEvent` (type: `integer`):

Maximum guest/attendee rows to scrape for each event. Use 0 for no per-event cap. Pagination stops early once the cap is reached.

## `maxAttendees` (type: `integer`):

Maximum attendee rows to scrape across the whole run. Use 0 for no global cap. Useful for cost control when scraping many large events.

## `includeGuestCounts` (type: `boolean`):

If true, adds nested `guestCounts` (approved, checkedIn, waitlist, invited, declined, etc.) from `/event/admin/get`.

## `includeGuests` (type: `boolean`):

If true (recommended), scrapes attendees for each event into separate dataset rows (email, socials, status, etc.). Each attendee row is billed as attendee-scraped.

## Actor input object example

```json
{
  "period": "all",
  "maxEvents": 0,
  "maxAttendeesPerEvent": 0,
  "maxAttendees": 0,
  "includeGuestCounts": true,
  "includeGuests": true
}
```

# Actor output Schema

## `attendees` (type: `string`):

Default dataset: one row per guest (attendee-scraped, $0.01 each).

## `events` (type: `string`):

Separate dataset: one row per hosted event (event-scraped, $0.01 each).

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("doin2much/luma-attendee-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 = {}

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

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

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

```

## CLI example

```bash
echo '{}' |
apify call doin2much/luma-attendee-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=doin2much/luma-attendee-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/AU0zUVPFntxRxDbz7/builds/jv9IULRkaaUbqMJWj/openapi.json
