# Events Lead Scraper — lu.ma, Meetup & Eventbrite (`nanomicon/events-leads-scraper`) Actor

Extract event listings with organizer, venue, price and host social handles from lu.ma, Meetup and Eventbrite in one run. Reports per-source coverage.

- **URL**: https://apify.com/nanomicon/events-leads-scraper.md
- **Developed by:** [NaNomicon](https://apify.com/nanomicon) (community)
- **Categories:** Lead generation, Social media, Agents
- **Stats:** 2 total users, 1 monthly users, 33.3% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 dataset items

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

## Events Lead Scraper

Public Apify Actor, intentionally public per operator confirmation since 2026-10-29, priced on `PAY_PER_EVENT` at `$0.05` USD per Actor Start plus `$0.01` USD per dataset item. It extracts event listings from Eventbrite, Luma, and Meetup in one run. `source` defaults to `auto`: URLs route by host and keyword searches run in Eventbrite, Luma, Meetup order. Set a source explicitly to limit adapters. Supply at least one listing URL or keyword. All adapters use plain HTTP without proxies or retry loops; Luma transport may follow one same-family HTTPS redirect. Eventbrite can fetch event detail pages for organizer and price data when `includeDetails` is true (default); Luma and Meetup never fetch per-event details. Luma listing data includes available host/calendar socials and attendee visibility. Luma URLs on `luma.com`, `www.luma.com`, `lu.ma`, or `www.lu.ma` normalize to canonical `https://luma.com`.

### Development

Run tests with `python -m pytest tests`. CI pins Python 3.12.13 and runs this suite after a separate integrity guard. `constraints.txt` freezes runtime and test dependencies; refresh it in the same change as dependency edits using `python -m pip install -r requirements.txt -r requirements-dev.txt`, then `python -m pip freeze > constraints.txt`.

### Input

Search sources automatically using keywords:

```json
{"keywords":["AI founders"],"location":"san-francisco","maxResults":200}
```

Search selected source using one or more listing URLs:

```json
{"source":"luma","urls":["https://luma.com/<calendar-or-user>"],"maxResults":200}
```

Input fields:

- `source`: optional `auto`, `eventbrite`, `luma`, or `meetup`; defaults to `auto`.
- `urls`: optional array of listing, calendar, group, or discovery URLs. Luma accepts exact hosts `luma.com`, `www.luma.com`, `lu.ma`, and `www.lu.ma`; inputs normalize to `https://luma.com`, and transport follows at most one same-family HTTPS redirect.
- `keywords`: optional array of search terms.
- At least one of `urls` or `keywords` must be supplied; both may be used together.
- `location`: optional provider-specific location for keyword searches and Eventbrite filtering. For San Francisco keyword discovery, Eventbrite uses its search path and a conservative client-side filter over structured physical addresses; Luma uses `/sf` plus title-keyword and venue-text filters; Meetup uses `location=us--ca--san-francisco` plus the same conservative venue filter. The filter accepts only OMB-listed principal cities of the SF MSA, not every postal locality. Unknown and online-only venues are excluded; no geocoding is performed. A recognized Eventbrite `/d/ca--san-francisco/` URL activates its client-side address filter even without `location`, but explicit Luma/Meetup URLs do not get discovery title/metro filtering. Keyword-search filters are not a guarantee for arbitrary explicit URLs.
- `startDate`, `endDate`: optional ISO dates bounding event dates inclusively.
- `maxResults`: global result cap, default `200`, range `1`–`5000`.
- `includeDetails`: default `true`; Eventbrite-only detail enrichment. Ignored by Luma and Meetup.
- `maxFetches`: defaults to `30`, range `1`–`1000`; shared cap for outbound discovery and Eventbrite detail requests. Requests are spaced at least 400 ms apart.
- `skipSeenDays`: defaults to `0` (off), range `0`–`365`; when set, events whose URL already appeared in a run with the same source, URLs, keywords, location and date window are skipped for that many days, so scheduled runs report only what is new. Skipped rows are counted in `run_summary.rowsSkippedSeen`.
- `compact`: defaults to `false`; when true, emits exactly `recordType`, `eventUrl`, `eventName`, `startDate`, `venue`, `organizerName` and `source`. It skips Eventbrite detail enrichment and overrides `includeDetails` to `false` in `exactConfig`.

The actor processes sources in stable Eventbrite, Luma, Meetup order and preserves source-by-source ordering within the global cap. A capped run may return no rows from later sources; `sourceStatuses` marks those as `skipped_cap_reached`. Provider-specific search results may interpret free-text locations differently; no geocoding is performed. San Francisco keyword filtering is conservative and explicit Luma/Meetup URLs bypass discovery title/metro filters.

### Results

Dataset contains actual event rows and one `run_summary`; valid empty source results are successful. Event rows carry concrete `source` and retain event lead fields, host and calendar structures, and available source data. Eventbrite and Luma rows carry venue; Meetup rows do not. Hidden attendee counts remain `attendeeCount: null` with `attendeeCountHidden: true`; a visible zero remains zero. Missing source values stay null. No synthetic records or cost fields are emitted.

Eventbrite rows include `detailStatus`: `fetched`, `failed`, `not_requested`, or `skipped_cap_reached`. Luma and Meetup rows omit this field.

The summary reports `coverageStatus` (`complete`, `shortfall`, `partial`, or `blocked`), `sourcesRun`, `sourceStatuses`, `sourceCounts` (all sources, including zero counts for unattempted sources), `sourceErrors` (source and redacted message only; URL-level request details are in `diagnostics`), date-exclusion counts, and extraction/transport diagnostics. `sourceStatuses` distinguishes `not_requested`, `skipped_cap_reached`, `returned_zero`, `filtered`, `returned`, and `blocked`. `blocked` means a source or detail request errored; otherwise, empty results never raise and overall `coverageStatus` is `shortfall`. `partial` applies only when at least one row is returned and a requested source was skipped at the cap, returned zero, or was fully filtered. If neither condition applies, `complete` means the global cap was filled and `shortfall` means it was not. `rowsExcludedOutOfDateRange` and `rowsExcludedBadDate` distinguish valid dates outside the inclusive range from missing or invalid dates. The terminal status message reports both counters when a date filter is active. Genuine source errors fail the run after summary output; valid empty results remain successful.
When `startDate` is omitted, events whose `endDate` date is before today UTC (or whose `startDate` date is before today UTC when `endDate` is absent) are excluded; comparison uses calendar dates, not instants. `rowsExcludedAlreadyEnded` counts these rows and adds a terminal-status clause when non-zero. Supplying `startDate` disables this exclusion.

`eventbriteDetailSummary` records detail request/response counts, non-200 responses, non-200 ratio, and requests with no HTTP response.

### Operational constraints

The operator used Apify `maxTotalChargeUsd: 0.30` as a run cap during validation probes, with no retries or proxies. The operator's `$0.05` per-probe cap applied during validation only; it is not a runtime feature. At runtime, source requests share `maxFetches` as a per-run request-count limit. Sources skipped when it is exhausted appear as `skipped_cap_reached`, and terminal status reports request-budget exhaustion. Do not start additional runs or add unapproved source URLs.

The Actor is public on purpose since 2026-10-29 and uses `PAY_PER_EVENT` pricing: `$0.05` per Actor Start plus `$0.01` per dataset item. It uses `LIMITED_PERMISSIONS` and keeps standby mode disabled (`standbyUrl: null`). These are platform-managed settings, not source metadata in `.actor/actor.json`; verify them on the existing Actor before deployments. Keep Apify credentials in the OS keyring; never put tokens in files or command output.

# Actor input Schema

## `source` (type: `string`):

Source to search, or auto to search all sources. Defaults to auto.

## `urls` (type: `array`):

Optional nonempty array of event listing, calendar, group, or discovery URLs. Supply urls, keywords, or both.

## `keywords` (type: `array`):

Optional nonempty array of search terms. Supply keywords, urls, or both.

## `location` (type: `string`):

Optional provider-specific location value for keyword searches. Passed through without geocoding. San Francisco keyword searches use conservative client-side title/physical-venue filters for Luma and Meetup and structured-address filtering for Eventbrite.

## `startDate` (type: `string`):

Optional inclusive ISO date lower bound for event dates.

## `endDate` (type: `string`):

Optional inclusive ISO date upper bound for event dates.

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

Global maximum number of event rows returned across all sources.

## `maxFetches` (type: `integer`):

Maximum outbound HTTP requests per run, shared across discovery and Eventbrite detail fetches.

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

Fetch Eventbrite event details for organizer and price data. Eventbrite only; ignored by Luma and Meetup.

## `compact` (type: `boolean`):

Returns one short row per event for agent/MCP consumers with recordType, eventUrl, eventName, startDate, venue, organizerName and source; skips detail enrichment.

## `skipSeenDays` (type: `integer`):

Cross-run deduplication. When above 0, events whose URL was returned by a run with the same source, URLs, keywords, location and date window are skipped for this many days, so a scheduled run only reports what is new. 0 disables it.

## Actor input object example

```json
{
  "source": "auto",
  "urls": [
    "https://www.eventbrite.com/d/ca--san-francisco/ai/"
  ],
  "maxResults": 25,
  "maxFetches": 10,
  "includeDetails": true,
  "compact": false,
  "skipSeenDays": 0
}
```

# Actor output Schema

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

Full event rows contain eventName, eventUrl, dates, venue, organizer, and source data. Eventbrite and Luma rows carry venue; Meetup rows do not. With compact: true, event rows contain exactly recordType, eventUrl, eventName, startDate, venue, organizerName and source, with Eventbrite detail enrichment skipped. The run_summary reports coverageStatus, sourceStatuses, errors, exclusions, detail coverage, and diagnostics.

## `console` (type: `string`):

Open run in Apify Console to inspect dataset records and run details.

# 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 = {
    "urls": [
        "https://www.eventbrite.com/d/ca--san-francisco/ai/"
    ],
    "maxResults": 25,
    "maxFetches": 10,
    "includeDetails": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("nanomicon/events-leads-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 = {
    "urls": ["https://www.eventbrite.com/d/ca--san-francisco/ai/"],
    "maxResults": 25,
    "maxFetches": 10,
    "includeDetails": False,
}

# Run the Actor and wait for it to finish
run = client.actor("nanomicon/events-leads-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 '{
  "urls": [
    "https://www.eventbrite.com/d/ca--san-francisco/ai/"
  ],
  "maxResults": 25,
  "maxFetches": 10,
  "includeDetails": false
}' |
apify call nanomicon/events-leads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nanomicon/events-leads-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/9aHX1UgDs1XigDn7B/builds/RBRVNd5zSXZzccLO3/openapi.json
