# Crypto Events Scraper (`studious_allergy_mig/crypto-events-scraper`) Actor

Extract crypto conferences, hackathons, meetups and summits from lu.ma — with chain/ecosystem tagging, event-type classification, and pricing/virtual flags. One dataset item per event.

- **URL**: https://apify.com/studious\_allergy\_mig/crypto-events-scraper.md
- **Developed by:** [Conor G](https://apify.com/studious_allergy_mig) (community)
- **Categories:** Agents, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 results

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

## Crypto Events Scraper — crypto conference data & events API for lu.ma

Structured **crypto conference data**: conferences, hackathons, meetups, and summits, pulled from lu.ma and classified with crypto-specific tags. Use it as a crypto events API — run it on a schedule and pull fresh results with the Apify API or client libraries, or just export a dataset from the Console. Start from the crypto hub, a single organizer's calendar, or any city page, and get back one dataset row per event: name, dates, venue, price, organizer — plus the crypto-specific fields below that you won't get from a generic event scraper.

### What makes this different from a generic lu.ma scraper

This actor is purpose-built for crypto/web3 event research. On top of the standard event fields, every item is enriched with:

| Field | Description |
|---|---|
| `eventType` | One of `conference`, `hackathon`, `meetup`, `summit`, `party` (incl. side-events), or `other` — classified from the event's own name/description/tags. |
| `chainMentions` | Array of chains/ecosystems the event text mentions — Bitcoin, Ethereum, Solana, Base, Arbitrum, Polygon, Avalanche, Cosmos, Polkadot, TON, Sui, Aptos, NEAR, Cardano, and more. |
| `isFree` | `true`/`false` — collapses lu.ma's ticket data into a clean boolean. |
| `isVirtual` | `true` for online/hybrid events. |
| `multiDay` | `true` when the event spans more than one calendar day (conferences, summits, hacker houses). |

All enrichment is computed with deterministic, testable text heuristics — no LLM calls, no black box.

#### Default seed: the crypto hub

Leave `startUrls` empty (or use the default) and the actor starts from lu.ma's own crypto topic hub, currently listing ~500 events across dozens of organizer calendars — conferences, hackathons, side-events, and community meetups worldwide. You can just as easily point it at a single calendar or city instead.

### Full field list

| Field | Description |
|---|---|
| `url` | Canonical event page URL |
| `eventId` | Luma's internal event ID |
| `name` | Event title |
| `description` | Full event description as plain text |
| `startAt` / `endAt` | ISO 8601 start/end datetimes |
| `timezone` | IANA timezone of the event |
| `isVirtual` | Whether the event is online/hybrid |
| `venueName`, `address`, `city`, `region`, `country` | Location details, when public |
| `coverImageUrl` | Event cover image |
| `isFree`, `priceDisplay`, `spotsRemaining`, `isSoldOut` | Ticket/pricing info as shown on the page |
| `organizerName`, `organizerSlug`, `organizerWebsite` | The hosting calendar/organizer |
| `organizerSocials` | Public organizer social handles (Twitter/X, Instagram, LinkedIn, TikTok, YouTube) |
| `tags` | Category tags lu.ma itself assigns (e.g. Crypto, AI) |
| `scrapedAt` | Timestamp of extraction |
| `eventType` | Crypto-specific classification — see above |
| `chainMentions` | Crypto-specific chain/ecosystem tags — see above |
| `multiDay` | Crypto-specific span flag — see above |

#### Sample output

```json
{
  "url": "https://lu.ma/37hv55q0",
  "eventId": "evt-M7fzXQdEUctQNYV",
  "name": "OffChainers @ Malaysia Blockchain Week 2026",
  "description": "Heading to Malaysia Blockchain Week 2026? Let's connect! Join fellow OffChainers for an informal meetup right at the venue...",
  "startAt": "2026-07-29T02:00:00.000Z",
  "endAt": "2026-07-29T21:00:00.000Z",
  "timezone": "Asia/Kuala_Lumpur",
  "venueName": "World Trade Centre Kuala Lumpur",
  "address": "World Trade Centre Kuala Lumpur, 41, Jalan Tun Ismail, Chow Kit, 50480 Kuala Lumpur, Malaysia",
  "city": "Kuala Lumpur",
  "region": "Wilayah Persekutuan Kuala Lumpur",
  "country": "Malaysia",
  "coverImageUrl": "https://images.lumacdn.com/uploads/bb/6b6df1d7-ec82-45f1-abab-107380ed9dcc.png",
  "priceDisplay": "Free",
  "spotsRemaining": null,
  "isSoldOut": false,
  "organizerName": "OffChain Global Events",
  "organizerSlug": "offchainglobalevents",
  "organizerWebsite": "https://offchain.social",
  "organizerSocials": {
    "twitter": "offchainglobal",
    "instagram": "offchain_global",
    "linkedin": "/company/offchain",
    "youtube": "offchaing"
  },
  "tags": ["Crypto"],
  "scrapedAt": "2026-07-29T09:09:36.847Z",
  "eventType": "meetup",
  "chainMentions": [],
  "isFree": true,
  "isVirtual": false,
  "multiDay": false
}
```

This is real output from a live run against `luma.com/crypto`.

### Input

| Field | Type | Description |
|---|---|---|
| `startUrls` | array | lu.ma URLs to scrape. Defaults to the crypto hub (`https://luma.com/crypto`) if left empty. See below for other supported URL kinds. |
| `maxEvents` | integer | Stop after this many unique events have been scraped. Leave empty for no limit. |
| `dateFrom` / `dateTo` | string | Optional ISO date bounds — only events starting in this window are kept. |
| `eventTypeFilter` | array | Optional — keep only `conference`, `hackathon`, `meetup`, `summit`, `party`, and/or `other`. Leave empty to keep every type. |
| `maxConcurrency` | integer | Parallel page fetches (default 5). Kept modest to be respectful of lu.ma. |
| `maxRequestRetries` | integer | Retries per page before it's skipped with a warning (default 3). |

#### Supported URL types

1. **The crypto hub** — `https://luma.com/crypto` (the default) — the actor discovers the calendars featured there, then crawls each calendar for its events.
2. **Calendar / organizer pages** — `https://lu.ma/token2049` — the actor discovers that organizer's listed events and scrapes each one.
3. **City or category discovery pages** — `https://lu.ma/sf` — the actor discovers the events shown on that page and scrapes each one.
4. **Individual event pages** — `https://lu.ma/on-mercury-sf` — scraped directly.

Mix and match any of these in one `startUrls` list.

#### Example input

```json
{
  "startUrls": [{ "url": "https://luma.com/crypto" }],
  "maxEvents": 200,
  "eventTypeFilter": ["conference", "hackathon", "summit"]
}
```

### Use cases

- **Sponsor / BD prospecting** — find every hackathon or conference in a chain's ecosystem to pitch sponsorship, a booth, or a talk.
- **Conference calendars** — build a running calendar of major crypto conferences and summits for your team or community.
- **Community research** — track what a specific ecosystem foundation, DAO, or accelerator is running, and where the crypto event calendar is thinning or thickening by region.
- **Chain-specific outreach** — filter `chainMentions` to find every event touching a given ecosystem (e.g. every Solana- or Base-tagged event this quarter).

### How it works (and why it's reliable)

Lu.ma is built on Next.js and server-renders each public page with a full JSON snapshot of the page's data embedded in a `__NEXT_DATA__` script tag. This actor reads that JSON directly instead of scraping visible HTML/CSS — no headless browser required. That means:

- It survives lu.ma redesigning its page layout or CSS classes.
- Field extraction (dates, prices, organizer info) is exact — it comes from the same data lu.ma's own frontend renders from, not fragile text parsing.
- Crawling the crypto hub, a calendar, or a city page all follow the same pattern: read the embedded JSON, pull out the linked calendars/events, and queue them directly (bypassing same-hostname link-following, since lu.ma redirects its bare domain to luma.com).

Every page fetch is retried on failure; a page that can't be parsed is skipped with a logged warning rather than crashing the run. Events are deduplicated by their lu.ma event ID, so the same event linked from multiple discovery pages is only saved once. The run ends with a summary log of events scraped vs. pages that failed or were skipped, and only exits with a failure status if **every** input page failed.

### Limitations (honest, by design)

- **No attendee/guest-list data.** This actor only reads public event/calendar/discovery pages. It does not, and will not, extract guest lists, RSVPs, or any data behind a login.
- **No login, no CAPTCHA bypassing.** Private or invite-only events are out of scope.
- **Enrichment is heuristic, not perfect.** `eventType` and `chainMentions` are derived from text pattern matching, not a model — a poorly-described event may land in `other`, and chain detection is intentionally conservative on ambiguous brand names (e.g. "Base", "NEAR", "TON") to avoid false positives, which means it can occasionally under-count a genuine mention buried in unusual phrasing.
- **The crypto hub surfaces active/featured calendars, not every historical listing.** Very large calendars that lu.ma paginates client-side may not surface every event in one page load; re-run periodically to pick up new listings, or supply direct calendar/event URLs for anything missed.
- **Fields depend on what the organizer made public.** If an organizer hides the exact address or ticket price, this actor won't have it either — it reads only what lu.ma itself shows to a visitor.

### FAQ

**Is it legal to scrape crypto events from lu.ma?**
This actor only reads public pages — the same event, calendar, and hub pages anyone can open in a browser without logging in. It doesn't access private events, guest lists, or anything behind authentication. You're responsible for how you use the data, but the extraction itself is limited to public information by design.

**What does it cost to run?**
Pay per result — you're charged per event returned, not per page crawled or per run. See the Pricing section below for the current rate.

**How do I run this on a schedule?**
In the Apify Console, open this actor, save an input as a **Task**, then add a **Schedule** to that task (e.g. daily or weekly). Each scheduled run appends new events to a fresh dataset, so you can track which conferences/hackathons are newly announced.

**Can I get a field that isn't listed here?**
Only if lu.ma itself shows it on the public page, or if it's derivable with a deterministic text rule (like `eventType` and `chainMentions` are). This actor doesn't invent data or call an LLM. If you need something specific, open an Issue on the actor's Issues tab.

**Does `chainMentions` tell me who's sponsoring or attending?**
No. It only flags which chains/ecosystems are mentioned in the event's own name, description, or tags — useful for finding events to target for sponsorship or BD outreach, not a guest list or sponsor list.

**Can I pull just conferences and hackathons, skip meetups?**
Yes — set `eventTypeFilter` to `["conference", "hackathon"]` (or any subset) and everything else is dropped before it's saved.

### Pricing

Pay per result — you're charged per event returned, not per page crawled or per run. One dataset item = one event.

### Output

One dataset item per event. Use the **Crypto events** dataset view in the Apify Console for a quick table (name, type, chains, dates, city, price), or export the full dataset as JSON/CSV/Excel for further analysis.

# Actor input Schema

## `startUrls` (type: `array`):

lu.ma URLs to scrape. Defaults to the crypto topic hub (https://luma.com/crypto), which is crawled for the calendars featured there and then for the events on each calendar. You can also pass: (1) individual event pages, e.g. https://lu.ma/on-mercury-sf, (2) calendar/organizer pages, e.g. https://lu.ma/token2049, or (3) city/category discovery pages, e.g. https://lu.ma/sf.

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

Maximum number of distinct events to scrape across the whole run. Once this many unique events have been saved, the run stops enqueuing new event pages. Defaults to 100 so a first run stays fast and predictable; clear it for no limit.

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

Only keep events starting on or after this date. Accepts an ISO date/datetime, e.g. 2026-01-01 or 2026-01-01T00:00:00Z.

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

Only keep events starting on or before this date. Accepts an ISO date/datetime, e.g. 2026-12-31.

## `eventTypeFilter` (type: `array`):

Only keep events classified as one of these types. Leave empty to keep every type.

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

Maximum number of pages fetched in parallel. Kept modest by default to be respectful of lu.ma's servers.

## `maxRequestRetries` (type: `integer`):

How many times to retry a page that fails to load or parse before skipping it with a warning.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://luma.com/crypto"
    }
  ],
  "maxEvents": 100,
  "maxConcurrency": 5,
  "maxRequestRetries": 3
}
```

# 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 = {
    "startUrls": [
        {
            "url": "https://luma.com/crypto"
        }
    ],
    "maxEvents": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("studious_allergy_mig/crypto-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 = {
    "startUrls": [{ "url": "https://luma.com/crypto" }],
    "maxEvents": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("studious_allergy_mig/crypto-events-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 '{
  "startUrls": [
    {
      "url": "https://luma.com/crypto"
    }
  ],
  "maxEvents": 100
}' |
apify call studious_allergy_mig/crypto-events-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/ZnE3LoOnR1narnIwf/builds/gXc0j6LM5bjXtfiAH/openapi.json
