# Luma Events Scraper: Tech, AI & Crypto Events by City (`rjmacarthy/luma-events-scraper`) Actor

Scrape Luma (lu.ma / luma.com) events by city, category (AI, tech, crypto...), calendar or event URL: dates, venue, coordinates, ticket prices, guest counts, hosts with public social links, description. Incremental "only new events" mode. No login.

- **URL**: https://apify.com/rjmacarthy/luma-events-scraper.md
- **Developed by:** [rj](https://apify.com/rjmacarthy) (community)
- **Categories:** Lead generation, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 luma event scrapeds

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/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: Tech, AI & Crypto Events by City

**Luma Events Scraper** extracts public events from **Luma** (lu.ma / luma.com), the platform most AI, tech, startup and crypto communities use for meetups, hackathons, demo days and conference side events. Give it **cities** (London, San Francisco, New York, Berlin...), **categories** (AI, Tech, Crypto, Climate...), **calendar URLs** or **event URLs**, and get clean, structured event data: dates in UTC and local time, venue and coordinates, ticket prices, sold-out / waitlist / approval flags, guest count, the organising calendar and every host's public profile with their social links.

It reads the same public JSON API that luma.com uses, so it is **fast, cheap and reliable**: no login, no browser, no proxy by default. Unlike other Luma scrapers it accepts **all four input types in one run** (city, category x city, calendar, event URL), returns **structured ticket pricing and host profiles**, handles **external events listed on calendars**, and has an **incremental "only new events" mode** so you can schedule a daily feed of newly announced events. You **only pay for the events you get**.

### What data can you get from Luma?

| Field group | Fields |
|---|---|
| Event | `id` (evt-...), `url`, `name`, `description` (plain text), `coverImageUrl`, `categories`, `tags` |
| Time | `startAt`, `endAt` (UTC ISO), `timezone`, `startAtLocal`, `endAtLocal` (local time with offset) |
| Location | `locationType` (in-person / online), `onlinePlatform` (zoom, google-meet...), `venueName`, `address`, `city`, `region`, `country`, `countryCode`, `latitude`, `longitude`, `addressHidden` |
| Tickets | `isFree`, `priceMin`, `priceMax`, `currency`, `isPayWhatYouWant`, `ticketTypes[]` (name, price, currency, availability, sales end), `isSoldOut`, `spotsRemaining`, `requiresApproval`, `waitlistActive`, `registrationStatus` |
| Audience | `guestCount` (a number only) |
| Organiser | `calendar` (name, slug, URL, avatar, city, website, X / Instagram / LinkedIn / YouTube / TikTok) |
| Hosts | `hosts[]` (name, Luma profile URL, avatar, short bio, verified flag, website, X / Instagram / LinkedIn / TikTok / YouTube links), `hostNames` |
| Provenance | `sourceType`, `sourceValue`, `discoverCity`, `isExternal`, `detailsFetched`, `scrapedAt` |

### Use cases

- **Event discovery feeds.** A daily list of new AI, crypto or startup events in your cities for a newsletter, Slack channel, community calendar or "what's on" site.
- **Developer relations and community teams.** Track every meetup and hackathon in your ecosystem, who hosts them and how many people register.
- **Sales and partnerships.** Find active community organisers, venues and sponsors in a city, with their public websites and social profiles.
- **Market and competitor research.** Which topics, companies and venues run the most events, how prices and attendance compare, which calendars are growing.
- **Travel and conference planning.** All side events around a conference (NeurIPS, ETHGlobal, Web Summit...) from its Luma calendar in one spreadsheet.

### How to use

1. Click **Try for free** or **Start**.
2. Add one or more **Cities** (e.g. `london`, `sf`, `nyc`), pick **Categories**, and/or paste **Calendar URLs** and **Event URLs**.
3. Optionally narrow it down with **Keywords** and **Events from / until** dates, and set **Max events per source** (default 100).
4. Click **Start**, then download the events as JSON, CSV, Excel or HTML, or fetch them through the API.

#### How the inputs combine

| You give | You get |
|---|---|
| Cities only | The events featured on each city's Luma page (e.g. luma.com/london) |
| Categories + cities | Category events near each city: every category x city pair is one source ("AI near London", "AI near San Francisco") |
| Categories only | Category events near the location of the run's IP address (Luma localises category pages). Add a city for predictable results. |
| Calendar URLs | All upcoming events of each calendar, optionally its past events too |
| Event URLs | Exactly those events, always with full details |

Cities accept Luma's slugs (`london`, `sf`, `nyc`, `la`, `dc`, `berlin`, `singapore`, `tokyo`, `bengaluru`... see [luma.com/discover](https://luma.com/discover)) and common names (`New York`, `San Francisco`, `São Paulo`). URLs can be `lu.ma/...` or `luma.com/...`; the Actor works out whether a link is a calendar or an event.

#### Input examples

AI and crypto events in London and San Francisco in the next 30 days:

```json
{
    "cities": ["london", "sf"],
    "categories": ["ai", "crypto"],
    "dateTo": "30 days",
    "maxEvents": 200
}
```

Every upcoming event of two community calendars, plus their past events since January, hackathons only:

```json
{
    "calendarUrls": ["https://luma.com/genai-collective", "https://lu.ma/ls"],
    "includePastEvents": true,
    "dateFrom": "2026-01-01",
    "keywords": "hackathon, buildathon",
    "maxEvents": 0
}
```

A daily "new events" feed (save as a Task and schedule it):

```json
{
    "cities": ["nyc", "sf", "london", "berlin"],
    "categories": ["ai", "tech"],
    "onlyNewEvents": true,
    "stateKey": "ai-tech-4-cities",
    "maxEvents": 300
}
```

Specific events:

```json
{
    "eventUrls": ["https://luma.com/4lkgf2hc", "https://lu.ma/event/evt-b5bf1CMZEGpykgB"]
}
```

| Field | Description |
|---|---|
| `cities` | Luma discover cities (slug or name). |
| `categories` | `ai`, `tech`, `crypto`, `climate`, `arts`, `fitness`, `wellness`, `food`, `books`, `games`, `running`, `family`. |
| `calendarUrls` | Calendar links or slugs (`https://luma.com/ls`, `lu.ma/deepmind`, `ls`, `https://luma.com/calendar/cal-...`). |
| `eventUrls` | Event links or ids (`https://luma.com/4lkgf2hc`, `https://lu.ma/event/evt-...`, `evt-...`). |
| `keywords` | Comma-separated; an event matches if its name, description, calendar, hosts, venue, city, tags or categories contain any of them. Short words like `ai` match whole words only. |
| `dateFrom`, `dateTo` | `YYYY-MM-DD` or relative (`7 days`, `+2 weeks`, `-1 month`). Default: upcoming events (from now, including events in progress), no end date. |
| `includePastEvents` | Calendars only: also scrape past events, most recent first. |
| `includeExternalEvents` | Calendars can list events hosted elsewhere; on by default (output with `isExternal: true`). |
| `maxEvents` | Limit per source (each city, category x city pair and calendar). `0` = no limit. Default `100`. |
| `includeDetails` | Load each event's full record for the description, ticket types and categories (one extra request per event). Default `true`. |
| `onlyNewEvents`, `stateKey` | Incremental mode and the name of the monitor. |
| `maxConcurrency`, `maxRequestsPerSecond` | Politeness limits (defaults 3 and 3). |
| `proxyConfiguration` | Off by default; see the FAQ. |

### Output example

One dataset item per event (from a real run; description shortened, two of three hosts and one ticket type omitted):

```json
{
    "id": "evt-jpvedgsEI3u6nq1",
    "url": "https://luma.com/4lkgf2hc",
    "name": "Designing Futures: What We Give Forward",
    "startAt": "2026-11-05T18:00:00.000Z",
    "endAt": "2026-11-05T21:00:00.000Z",
    "timezone": "Europe/London",
    "startAtLocal": "2026-11-05T18:00:00+00:00",
    "endAtLocal": "2026-11-05T21:00:00+00:00",
    "locationType": "in-person",
    "onlinePlatform": null,
    "venueName": "French Protestant Church of London",
    "address": "French Protestant Church of London, French Protestant Church, 8-9 Soho Square, London W1D 3QD, UK",
    "city": "London",
    "region": "England",
    "country": "United Kingdom",
    "countryCode": "GB",
    "latitude": 51.5156376,
    "longitude": -0.1329888,
    "addressHidden": false,
    "coverImageUrl": "https://images.lumacdn.com/uploads/aw/b53b97d6-df9f-459d-99c8-4ed94fbd8bf7.png",
    "description": "Join us for Designing Futures!\n\n⚡ Event Overview\n\nJoin us for a unique evening of UX, networking and forward-thinking to champion education. ...",
    "isFree": false,
    "priceMin": 5,
    "priceMax": 20,
    "currency": "GBP",
    "isPayWhatYouWant": true,
    "ticketTypes": [
        { "name": "Standard ticket", "price": 5, "minPrice": null, "currency": "GBP", "isPayWhatYouWant": false, "requiresApproval": false, "isSoldOut": false, "spotsRemaining": null, "salesEndAt": "2026-11-04T12:00:59.000Z", "kind": "fiat-price" },
        { "name": "Changemaker ticket (custom)", "price": 20, "minPrice": 5, "currency": "GBP", "isPayWhatYouWant": true, "requiresApproval": false, "isSoldOut": false, "spotsRemaining": null, "salesEndAt": "2026-11-04T12:00:59.000Z", "kind": "fiat-price" }
    ],
    "isSoldOut": false,
    "spotsRemaining": 6,
    "requiresApproval": false,
    "waitlistActive": false,
    "registrationStatus": "open",
    "guestCount": 73,
    "calendar": { "id": "cal-XPWEL40Bfs1ickY", "name": "Personal", "slug": null, "url": null, "isPersonal": true, "avatarUrl": "https://cdn.lu.ma/avatars-default/community_avatar_16.png", "description": null, "city": null, "country": null, "website": null, "twitterUrl": null, "instagramUrl": null, "linkedinUrl": null, "youtubeUrl": null, "tiktokUrl": null },
    "hosts": [
        {
            "id": "usr-f3QmhBlQCZQWVFi",
            "name": "Children of the Mekong",
            "username": "childrenmekong",
            "profileUrl": "https://luma.com/user/childrenmekong",
            "avatarUrl": "https://images.lumacdn.com/avatars/he/20d35a11-cd87-4ed0-9616-893e84095db1",
            "bio": "Passionate about providing access to education in Southeast Asia",
            "isVerified": false,
            "website": "https://www.childrenofthemekong.org/",
            "twitterUrl": null,
            "instagramUrl": "https://www.instagram.com/childrenofthemekong",
            "linkedinUrl": "https://www.linkedin.com/in/children-of-the-mekong",
            "tiktokUrl": null,
            "youtubeUrl": "https://www.youtube.com/@childrenofthemekong"
        }
    ],
    "hostNames": "Children of the Mekong, ...",
    "categories": ["arts", "tech"],
    "tags": [],
    "discoverCity": "london",
    "isExternal": false,
    "sourceType": "event",
    "sourceValue": "https://luma.com/4lkgf2hc",
    "detailsFetched": true,
    "scrapedAt": "2026-11-02T13:28:05.594Z"
}
```

Notes on the fields:

- `id` is Luma's event id and is stable across runs; use it to de-duplicate. An event found by several of your sources in one run is output (and charged) once.
- `addressHidden: true` means the host shows the exact address to registered guests only. You still get the city, region, country and an approximate point (`latitude`/`longitude`), but `address` and `venueName` are null.
- Prices are in currency units (5 = £5.00). `priceMin`/`priceMax` come from Luma's ticket summary and are refined from the ticket types when details are loaded. Free events have `isFree: true` and prices of 0.
- `description`, `ticketTypes` and Luma `categories` need **Include full details** (on by default). With it off, `detailsFetched` is false and those fields are null or empty; everything else is still filled.
- `calendar.isPersonal: true` means the event was created from the host's personal calendar rather than a community calendar; see `hosts` for the organiser.
- External events (`isExternal: true`, id `calev-...`) are listed on a Luma calendar but hosted on another site. `url` is the external page; you get name, times, place, organiser name and calendar tags.
- `startAtLocal` is the start time in the event's own time zone, which is what you want for "Tuesday 6 pm" style displays.

A `RUN_SUMMARY` record in the run's key-value store lists every source with its status, events output, events listed, duplicates, already-seen and filtered counts, plus request statistics and warnings.

### What this scraper does not collect

**No guest or attendee lists, ever.** Luma shows some registered guests' names and avatars on event pages; this Actor never reads them into the output. `guestCount` is a number only. It also never outputs e-mail addresses or phone numbers: hosts' short bios are scrubbed of them, and online events' meeting links are private to registered guests and not available. Host data is limited to what Luma shows publicly on a host's profile.

### Pricing

This Actor uses **pay-per-event** pricing. You pay only for events in your dataset; there is no start fee from us.

| Event | Price | 1,000 events |
|---|---|---|
| `event`: one Luma event in the output | $0.0015 | $1.50 |

Examples: the default "20 London events" run costs about **$0.03**; a daily feed that finds 50 new events a day costs about **$0.075 a day** (~$2.25 a month). Events skipped as already seen in incremental mode, duplicates across your sources, filtered events and failed sources cost nothing. Set **Maximum cost per run** in the run options to cap spending: the scraper stops cleanly when the budget is reached and says so in its status message.

### Scheduling: a feed of new events

1. Turn on **Only new events** and give the monitor a name in **Monitor name** (e.g. `ai-london`).
2. Save the configuration as a **Task** and add a **Schedule** (e.g. every morning).
3. The first run outputs all matching upcoming events (up to **Max events per source** each) and saves them as the baseline.
4. Every later run outputs **only events it has not output before**, so you get newly announced events, and pay only for those.

The memory lives in a named key-value store (`luma-events-scraper-state` by default) under the monitor name and is shared by all sources in the run. Events are forgotten 120 days after they were last listed. Don't run two runs with the same monitor name at the same time.

### Tips and limits

- **City pages are curated.** A Luma city page features a selection of events (London shows about 60 upcoming events at a time). For broader coverage of a topic in a city, combine the city with categories (`ai`, `tech`, `crypto`...): category feeds near a city are much larger.
- **Categories without a city** follow the location of the run's IP address, as on luma.com. On Apify that is a data-centre location, so add cities for predictable results.
- **Upcoming only on discover pages.** Luma's city and category pages list upcoming events. For past events, use calendar URLs with **Include past events**.
- **Event creation date** is not published by Luma, so there is no `createdAt` field. Use incremental mode to learn when an event first appeared.
- **Speed.** Lists return up to 50 events per request; with full details each event takes one more request. At the default 3 requests per second, 100 events with details take about 40 seconds.
- **Unofficial interface.** Luma has no public API for discovery; this Actor uses the endpoints luma.com itself uses, which can change without notice. Parsing is covered by tests against saved responses and failures are reported clearly. If Luma ever answers HTTP 403 or 429, the run stops with a clear message, keeps what it already saved, and suggests enabling a proxy.

### Integrations and API

- **API.** Start runs and fetch results with the [Apify API](https://docs.apify.com/api/v2), or the JavaScript and Python clients:

  ```bash
  curl -X POST "https://api.apify.com/v2/acts/rjmacarthy~luma-events-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"cities":["sf"],"categories":["ai"],"maxEvents":50}'
  ```

- **Webhooks.** Get notified, or trigger your pipeline, when a run finishes.

- **Make, Zapier, n8n.** Send new events to Google Sheets, Airtable, Notion, Slack, Discord, e-mail or your CRM with no code.

- **Google Sheets, Slack, Airbyte, Keboola and more** through Apify integrations.

- **AI agents (MCP).** Use the Actor as a tool through the Apify MCP server, e.g. "find AI hackathons in Berlin next month".

### FAQ

**Do I need a Luma account, cookies or a proxy?**
No. The events are public and the Actor uses no login. The proxy option is only there in case Luma starts blocking requests from Apify's servers.

**Which cities are supported?**
Every city on [luma.com/discover](https://luma.com/discover) (about 90, from Amsterdam to Zurich). Other slugs are checked live against Luma, and an unknown name gets a "did you mean" hint.

**Why does an event have no address?**
The host chose to show the address to registered guests only (`addressHidden: true`), or it is an online event.

**Can I get the attendee list?**
No. That is personal data, and this Actor deliberately does not collect it. You get `guestCount`.

**Can I scrape a host's profile or all events of a user?**
Profiles (`luma.com/user/...`) are not an input. Use the host's calendar URL, which lists their events.

**Is it legal to scrape Luma?**
The Actor only collects event information that organisers publish publicly to promote their events, and public host profile fields. It does not collect guest lists, e-mail addresses or phone numbers. You are responsible for making sure your use complies with Luma's terms and the laws that apply to you (for example GDPR if you process data about people in the EU).

### More scrapers by the same developer

- [Google Ads Transparency Scraper](https://apify.com/rjmacarthy/google-ads-transparency-scraper)
- [Substack Scraper](https://apify.com/rjmacarthy/substack-scraper)
- [Telegram Channel Scraper](https://apify.com/rjmacarthy/telegram-channel-scraper)
- [ATS Jobs Scraper: Greenhouse, Lever, Ashby & Workday](https://apify.com/rjmacarthy/ats-jobs-scraper)
- [Dice Jobs Scraper](https://apify.com/rjmacarthy/dice-jobs-scraper)
- [SEEK Jobs Scraper](https://apify.com/rjmacarthy/seek-jobs-scraper)

Browse all my Actors on [my Apify Store profile](https://apify.com/rjmacarthy).

### Support

Found an input that doesn't work, or need another field? Open an issue on the **Issues** tab with your input. Fixes are usually quick.

### Changelog

- **0.1** (November 2026): First release. Cities, categories (with city coordinates), calendars (upcoming, past, external events) and event URLs; full details with plain-text descriptions and ticket types; host profiles with social links; keyword and date filters; incremental "only new events" mode; budget-aware pay-per-event billing.

# Actor input Schema

## `cities` (type: `array`):

Luma discover cities: the slug from luma.com/discover (e.g. "london", "sf", "nyc", "berlin", "singapore") or the city name ("New York", "San Francisco"). Without categories you get the events featured on each city's page (luma.com/london). With categories, the cities set where to look for category events.

## `categories` (type: `array`):

Luma discover categories (luma.com/ai, luma.com/crypto, ...). Combine with cities to get, e.g., AI events in London and San Francisco. Luma localises category feeds, so without a city you get events near the location of the run's IP address.

## `calendarUrls` (type: `array`):

Luma calendars (communities and organisers), e.g. https://luma.com/ls, lu.ma/genai-collective or just the slug "ls". All upcoming events of each calendar, including events it lists from other calendars and external sites.

## `eventUrls` (type: `array`):

Single Luma events, e.g. https://luma.com/abc123xy or https://lu.ma/event/evt-... These are always output with full details; the date and keyword filters do not apply to them.

## `keywords` (type: `string`):

Only events whose name, description, calendar, hosts, venue, city, tags or categories contain one of these words. Separate several with commas (any of them matches). Case-insensitive; short words such as "ai" match whole words only. Leave empty for all events.

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

Only events that end on or after this date (YYYY-MM-DD, or relative such as "7 days"). Empty = from now (upcoming events, including ones in progress).

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

Only events that start on or before this date (end of that day, UTC). YYYY-MM-DD or relative such as "30 days". Empty = no end date.

## `includePastEvents` (type: `boolean`):

For calendar URLs, also scrape the calendar's past events (most recent first) after its upcoming ones. Combine with "Events from" to limit how far back. Luma's city and category pages only list upcoming events.

## `includeExternalEvents` (type: `boolean`):

Calendars can list events hosted on other websites. They are output with name, time, place, organiser name, tags and the external link (no tickets, hosts' profiles or description). Turn off to get only events hosted on Luma.

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

Stop after this many events from each source (each city, each category x city pair and each calendar is one source). 0 = no limit.

## `includeDetails` (type: `boolean`):

Load each event's page data for the plain-text description, ticket types with prices and Luma categories (one extra request per event). Turn off for a faster scrape from list data only (still includes dates, location, price range, hosts, calendar and guest count).

## `onlyNewEvents` (type: `boolean`):

Output (and charge) only events this monitor has not output in earlier runs. Schedule the Actor daily to get a feed of newly announced events. The first run outputs everything and becomes the baseline.

## `stateKey` (type: `string`):

Name of this monitor's memory of already-output events. Use different names for unrelated scheduled tasks; runs with the same name share it.

## `stateStoreName` (type: `string`):

Named key-value store that keeps the incremental state between runs.

## `maxConcurrency` (type: `integer`):

How many requests to Luma run at the same time.

## `maxRequestsPerSecond` (type: `integer`):

Upper limit on the request rate to Luma. The Actor slows down further by itself if Luma answers HTTP 429.

## `proxyConfiguration` (type: `object`):

Not needed normally: Luma's public API answers without a proxy. Enable Apify Proxy if Luma starts answering HTTP 403 or 429 for this run's IP.

## Actor input object example

```json
{
  "cities": [
    "london",
    "sf",
    "nyc"
  ],
  "includePastEvents": false,
  "includeExternalEvents": true,
  "maxEvents": 20,
  "includeDetails": true,
  "onlyNewEvents": false,
  "stateKey": "default",
  "stateStoreName": "luma-events-scraper-state",
  "maxConcurrency": 3,
  "maxRequestsPerSecond": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One item per event: name, start time, city, venue, price range, guest count, calendar, hosts and URL.

## `eventsFull` (type: `string`):

Every field for each event, including the plain-text description, ticket types, coordinates and host social links.

## `summary` (type: `string`):

Per-source status, counts, request statistics and any warnings.

# 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 = {
    "cities": [
        "london"
    ],
    "maxEvents": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("rjmacarthy/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 = {
    "cities": ["london"],
    "maxEvents": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("rjmacarthy/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 '{
  "cities": [
    "london"
  ],
  "maxEvents": 20
}' |
apify call rjmacarthy/luma-events-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rjmacarthy/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/FDcmgeQTczc1Fr9xW/builds/WXMsddHNbEC0pID8i/openapi.json
