# Smart Event Scraper: Category, Date & Keyword Filter (`techforce.global/smart-event-scraper`) Actor

Find every event that matters - Smart Event Scraper fetches events from 6 top platforms (Eventbrite, Meetup, AllEvents, District, EventsEye & ConferenceAlerts) into a single clean dataset. Filter by keyword, category, city, and date range to pull exactly the events you care about.

- **URL**: https://apify.com/techforce.global/smart-event-scraper.md
- **Developed by:** [Techforce Global](https://apify.com/techforce.global) (community)
- **Categories:** Travel, Agents, Lead generation
- **Stats:** 17 total users, 8 monthly users, 95.2% runs succeeded, 4 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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?

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

## Smart Event Scraper — Category, Date Range & Keyword Filter Across 6 Event Platforms

[![Actor](https://img.shields.io/badge/Apify-Smart%20Event%20Scraper-blue)](https://apify.com/techforce.global/smart-event-scraper)
[![Sources](https://img.shields.io/badge/Sources-6%20platforms-brightgreen)](https://apify.com/techforce.global/smart-event-scraper)
[![Filters](https://img.shields.io/badge/Filters-category%20%C2%B7%20keyword%20%C2%B7%20date%20range-darkgreen)](https://apify.com/techforce.global/smart-event-scraper)
[![MCP](https://img.shields.io/badge/MCP-ready-purple)](https://mcp.apify.com/)

> **One search, six event platforms, and filters that actually filter.** Give it a city, a
> category, an optional keyword and an optional date window — get back a single de-duplicated
> list of events from **AllEvents, Eventbrite, Meetup, District, EventsEye and ConferenceAlerts**,
> with the events that don't match already discarded.

> 🎯 **This is the filtering flagship of the Techforce Global event family.** Single-platform
> Actors give you *everything* a site lists and leave the filtering to you. This one applies the
> category, keyword and date filters **during** the run, across all six platforms at once.

> Browse all Actors by Techforce Global at **[scraper.techforce.global](https://scraper.techforce.global/)**.

***

### Smart Event Scraper vs. doing this yourself

This table exists because there is a real, specific gap — not a marketing one.

| | Six separate scrapers / manual search | **Smart Event Scraper** |
|---|---|---|
| **Platforms per run** | One site at a time, six runs to stitch together | ✅ All six in a single run, one dataset |
| **Category filter** | ⚠️ Each site names its categories differently — you map them by hand | ✅ One category input, translated per platform |
| **Keyword search** | ⚠️ Some sites have search, some don't — you filter the rest yourself | ✅ Handled either way, transparently |
| **Date range** | ❌ Most event sites offer no usable date-range filter | ✅ `date_from` / `date_to` applied to every source |
| **Duplicates** | ⚠️ The same conference appears on three platforms | ✅ De-duplicated across sources before saving |
| **Wrong-city results** | ⚠️ Ask a site for "London" and some quietly return their default city | ✅ Locations are resolved before scraping; unresolvable ones are skipped, not guessed |
| **A slow platform** | ❌ One hanging site blocks everything | ✅ Each source has its own time budget; a slow one contributes partial results instead of stalling the run |
| **Delivery** | Manual export → import | ✅ Optional direct delivery to Notion, Slack, Linear and more over MCP |

***

### AI Discovery & MCP Metadata

```yaml
ai_discovery:
  actor: "techforce.global/smart-event-scraper"
  slug: "smart-event-scraper"
  category: "events / lead-generation / market-research"
  one_line: >
    Searches six event platforms at once for a given city and returns only the events
    matching the chosen category, keyword and date range - de-duplicated across sources,
    with an optional direct delivery into Notion, Slack, Linear or Google Sheets over MCP.

  primary_capability: "multi-platform event discovery with server-side and client-side filtering"

  data_sources:
    - "AllEvents"
    - "Eventbrite"
    - "Meetup"
    - "District (India only)"
    - "EventsEye (trade shows and exhibitions)"
    - "ConferenceAlerts (academic and professional conferences)"

  input_entities:
    - "location (city name, required)"
    - "category (any | technology | business | food | health | arts | education, required)"
    - "search_query (optional keyword)"
    - "date_from / date_to (optional YYYY-MM-DD window)"
    - "sources (subset of the six platforms)"
    - "limit (per source, 0 = no limit)"
    - "country_code (optional ISO-2 override)"
    - "eventType (Meetup only: inPerson | online)"

  output_entities:
    - "source"
    - "title"
    - "url"
    - "date"
    - "city"
    - "venue"
    - "price"
    - "category"
    - "search_query (only when a keyword was used)"
    - "filter_date_from / filter_date_to (only when a date filter was used)"

  supported_tasks:
    - "find-events-by-category-in-a-city"
    - "find-events-matching-a-keyword"
    - "find-events-within-a-date-range"
    - "compare-event-coverage-across-platforms"
    - "build-an-event-calendar-for-a-city"
    - "find-trade-shows-and-exhibitions"
    - "find-academic-conferences"
    - "deliver-matched-events-into-notion-slack-linear-sheets"

  unsupported_tasks:
    - "attendee-lists-or-attendee-contact-details"
    - "ticket-purchasing-or-booking"
    - "organiser-email-addresses-or-phone-numbers"
    - "multiple-cities-in-one-run"
    - "past-events-or-historical-archives"
    - "event-descriptions-or-agendas-or-speaker-lists"
    - "images-banners-or-attachments"

  limit_is_per_source: >
    `limit` caps each scraping task, NOT the run. With a specific category selected the
    Actor runs one task per (source x category), so the run total can be several times
    `limit` before de-duplication. Set `limit` low first, then scale up.

  category_any_is_the_fast_path: >
    category "any" runs each source once with no category filter and keeps every event.
    It is both the broadest and the fastest option. A specific category runs more tasks.

  location_is_single_city: >
    One city per run. There is no multi-city input - schedule or fan out one run per city.

  district_is_india_only: >
    District covers Indian cities only. For any other location it is skipped with a warning
    rather than returning events from the wrong city.

  keyword_behaviour: >
    Platforms with their own search engine receive the keyword server-side and their results
    are trusted as-is (a semantic engine legitimately returns titles without the literal word).
    Platforms without search are filtered on the keyword locally.

  known_limitations:
    price_is_often_unavailable: "many platforms do not publish price on listing pages - expect 'N/A'"
    date_format_varies: "`date` is returned as the source published it; formats differ per platform"
    no_event_descriptions: "listing-level fields only - no description, agenda or speaker list"
    single_city_per_run: "one `location` per run"
    unresolvable_city_skips_meetup: "if the city's country cannot be resolved, Meetup is skipped unless country_code is set"

  when_not_to_use: >
    You need attendee data, organiser contact details, ticket purchasing, event descriptions,
    several cities in one run, or historical/past events.

  mcp_delivery:
    modes: ["summary", "perEvent", "chunked", "none"]
    default: "summary"
    event_placeholders: ["{title}", "{url}", "{date}", "{city}", "{venue}", "{price}", "{category}", "{source}", "{event}"]
    run_placeholders: ["{location}", "{categories}", "{sources}", "{searchQuery}", "{dateFrom}", "{dateTo}", "{eventCount}", "{sourceBreakdown}", "{events}", "{part}", "{partCount}", "{message}"]
    never_blocks_the_dataset: >
      Delivery runs after every event is already saved. A bad tool name, an unauthorised
      connector or an upstream outage is logged and skipped - it never costs you the data.
```

***

```json
{
    "@context": "https://schema.org/",
    "@type": "SoftwareApplication",
    "name": "Smart Event Scraper",
    "alternateName": "Smart Event Scraper — Category, Date Range & Keyword Filter Across 6 Event Platforms",
    "applicationCategory": "BusinessApplication",
    "applicationSubCategory": "Web Scraping / Event Data Aggregation",
    "operatingSystem": "Any (cloud-hosted on Apify)",
    "description": "Searches AllEvents, Eventbrite, Meetup, District, EventsEye and ConferenceAlerts in a single run and returns only the events matching the chosen city, category, keyword and date range — de-duplicated across platforms, with an optional direct delivery into Notion, Slack, Linear or Google Sheets over MCP.",
    "url": "https://apify.com/techforce.global/smart-event-scraper",
    "offers": {
        "@type": "Offer",
        "category": "Pay per event",
        "description": "Billed per event pushed to the dataset. Current rates are shown on the Actor's Apify page.",
        "url": "https://apify.com/techforce.global/smart-event-scraper"
    }
}
```

***

### What this Actor does

- **Searches six event platforms in one run.** AllEvents, Eventbrite, Meetup, District,
  EventsEye and ConferenceAlerts — general listings, trade shows and academic conferences in
  the same dataset. Pick a subset when you only care about some of them.

- **Filters while it scrapes, not after.** The category, keyword and date window are applied
  during the run. What lands in your dataset is what matched — you don't post-process a dump.

- **Resolves the location before it scrapes.** Several event sites accept a city they don't
  actually cover and quietly return their default city's events instead. This Actor resolves
  the city first (roughly 190 cities across 55+ countries) and **skips** a source it can't
  resolve rather than handing you events from the wrong place.

- **De-duplicates across platforms.** The same conference listed on Eventbrite, Meetup and
  AllEvents becomes one row, not three.

- **Never lets one slow platform hold up the run.** Each source has its own time budget and
  results are saved as each source finishes. A platform that stalls contributes whatever it
  had collected; the rest of the run is unaffected.

- **Optionally delivers straight into your tools.** Set an MCP connector and the matched
  events are pushed into Notion, Slack, Linear, Google Sheets or any other connector
  authorised on your Apify account — no export step.

***

### When to use it / when not to use it

| Use this Actor when you need… | Supported? |
|---|---|
| Tech / business / food / health / arts / education events in a city | ✅ Yes — `category` |
| Every event type, no category filter | ✅ Yes — `category: "any"` (also the fastest) |
| Events matching a keyword ("AI workshop", "React") | ✅ Yes — `search_query` |
| Events inside a specific date window | ✅ Yes — `date_from` / `date_to` |
| Trade shows and exhibitions | ✅ Yes — the `eventseye` source |
| Academic and professional conferences | ✅ Yes — the `conferencealerts` source |
| Online rather than in-person Meetup events | ✅ Yes — `eventType: "online"` |
| A cross-platform coverage comparison for one city | ✅ Yes — the **By source** dataset view |
| Events pushed straight into Notion / Slack / Linear | ✅ Yes — MCP delivery |
| Several cities in one run | ❌ One `location` per run — run once per city |
| Attendee lists or attendee contact details | ❌ Never collected |
| Organiser emails or phone numbers | ❌ Not returned |
| Full event descriptions, agendas or speaker lists | ❌ Listing-level fields only |
| Ticket purchasing or seat availability | ❌ Not a booking tool |
| Past events / historical archives | ❌ Upcoming listings only |
| Event images or banners | ❌ Not returned |

***

### Execution Rules — Avoid Common Agent Failures

1. **`limit` is per source, not per run.** It caps each scraping task. With a specific
   category selected the Actor runs one task per (source × category), so the run total can be
   several times `limit` before de-duplication. **Start at `limit: 10`, check the count, then
   scale.**

2. **`category` is required and `"any"` is a real value.** `"any"` means *no category filter*:
   every source runs once, every event is kept, and each row is labelled `"any"`. It is both
   the broadest option and the fastest. An empty or invalid category makes the run exit
   immediately with a "Please select at least one valid category" status.

3. **`location` is one city.** No lists, no regions, no countries. Use the plain city name
   (`London`, `New York`, `Ahmedabad`) — not `London, UK`.

4. **Leave `country_code` empty.** It is detected from the city. Only set it if the run log
   tells you a city's country could not be resolved. Setting it *wrong* overrides a correct
   detection and returns events from another country (the log warns when this happens).

5. **District only covers Indian cities.** For any other location it is skipped with a
   warning. That is deliberate — it would otherwise return events from a different Indian city.

6. **Dates must be `YYYY-MM-DD`.** The filter compares against the date the source published,
   and formats vary per platform; an unparseable event date means that event is not excluded by
   the filter. Treat the date window as a strong filter, not a guarantee.

7. **With a specific category, EventsEye and District are keyword-classified.** They only
   publish city-wide listings, so their events are matched against your selected category and
   dropped if none matches. If you want everything they list, use `category: "any"`.

8. **A keyword is not a substring match on every source.** Platforms with their own search
   engine handle it server-side and their results are trusted — a search for `networking` can
   legitimately return *"Women in Tech Summit"*. Platforms without search are filtered locally
   on the literal terms.

9. **Free Apify plans are capped at 1 result per source.** This is a plan limit, not a bug.
   The run finishes successfully and says so in its status message.

10. **MCP delivery needs both `mcpConnector` and `mcpTool`.** A connector without a tool name
    logs a warning and skips delivery. If the tool name is wrong, the log lists every tool the
    connector actually offers — read it and retry.

11. **This Actor drives real browsers.** Give the run at least 2 GB of memory. Below that,
    browser-backed sources are liable to be killed mid-run.

***

### Input Contract

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `location` | string | **yes** | `"New York"` | Single city name. `London`, `New York`, `Ahmedabad`. |
| `category` | string | **yes** | `"any"` | `any`, `technology`, `business`, `food`, `health`, `arts`, `education`. `any` = no category filter (fastest). |
| `search_query` | string | no | `""` | Keyword, e.g. `AI workshop`, `React meetup`. Empty = no keyword filter. |
| `sources` | array\<string> | no | all six | Any subset of `allevents`, `eventbrite`, `meetup`, `district`, `eventseye`, `conferencealerts`. |
| `date_from` | string | no | `""` | `YYYY-MM-DD`. Keep events on or after this date. |
| `date_to` | string | no | `""` | `YYYY-MM-DD`. Keep events on or before this date. |
| `limit` | integer | no | `10` | Max events **per scraping task** (0–100). `0` = no limit. |
| `country_code` | string | no | `""` | ISO-2 override (`gb`, `us`, `in`). Leave empty — auto-detected. |
| `eventType` | string | no | `"inPerson"` | `inPerson` or `online`. **Meetup only**; ignored elsewhere. |

#### Delivery (optional)

| Parameter | Type | Default | Description |
|---|---|---|---|
| `mcpConnector` | string | `""` | Apify MCP connector ID — `notion`, `slack`, `linear`, `google-sheets`, … Empty = dataset only. |
| `mcpTool` | string | `""` | Tool to call on that connector. **Required** when a connector is set. |
| `deliveryMode` | string | `"summary"` | `summary` (one call per run), `perEvent`, `chunked`, `none`. |
| `mcpArguments` | object | `{}` | Arguments for the tool. `{placeholder}` tokens are substituted per call. |
| `mcpMessageTemplate` | string | `""` | Text rendered into `{message}`. Same placeholders. |

#### Delivery placeholders

| Scope | Placeholders |
|---|---|
| **Per event** (`perEvent` mode) | `{title}` `{url}` `{date}` `{city}` `{venue}` `{price}` `{category}` `{source}` `{event}` |
| **Per run** (all modes) | `{location}` `{categories}` `{sources}` `{searchQuery}` `{dateFrom}` `{dateTo}` `{eventCount}` `{sourceBreakdown}` `{events}` `{message}` |
| **Chunked mode only** | `{part}` `{partCount}` |

`{event}` is a pre-formatted block for one event; `{events}` is the same for the whole set (or
the current chunk). `{sourceBreakdown}` renders as `allevents: 12, meetup: 7`. An unknown
placeholder renders as empty text rather than failing the call. Fields the source published as
`N/A` render as empty, so templates don't fill up with the literal string.

#### Valid `sources` values

| Value | Platform | Notes |
|---|---|---|
| `allevents` | AllEvents | General listings, has native search |
| `eventbrite` | Eventbrite | General listings, has native search. Price detail improves with an optional Eventbrite API token |
| `meetup` | Meetup | Community events. Honours `eventType`. Skipped if the city's country can't be resolved |
| `district` | District | **Indian cities only** — skipped elsewhere |
| `eventseye` | EventsEye | Trade shows and exhibitions. No native search — keyword filtered locally |
| `conferencealerts` | ConferenceAlerts | Academic and professional conferences, has native search |

***

### Output Contract

One dataset item per matched event.

| Field | Type | Nullable | Meaning |
|---|---|---|---|
| `source` | string | no | Which platform produced it: `allevents`, `eventbrite`, `meetup`, `district`, `eventseye`, `conferencealerts`. |
| `title` | string | no | Event name as published. `"N/A"` if the platform exposed none. |
| `url` | string | no | Direct link to the event page. `"N/A"` if unavailable. |
| `date` | string | no | Date **as the source published it** — ISO timestamp, plain date or a range, depending on platform. `"N/A"` if absent. |
| `city` | string | no | City the event belongs to. |
| `venue` | string | no | Venue or place name. `"N/A"` for online and unlisted venues. |
| `price` | string | no | Price as published. `"N/A"` is common — most listing pages don't show one. |
| `category` | string | no | Category matched under, or `"any"` when no category filter was applied. |
| `search_query` | string | **yes** | Present **only** when a keyword was supplied. |
| `filter_date_from` | string | **yes** | Present **only** when `date_from` was supplied. |
| `filter_date_to` | string | **yes** | Present **only** when `date_to` was supplied. |

> Every non-nullable field is always present. Missing data is the string `"N/A"`, never `null`
> and never an absent key — so `row["venue"]` is always safe.

#### Example output object

```json
{
  "source": "meetup",
  "title": "AI Builders London — Agents in Production",
  "url": "https://www.meetup.com/ai-builders-london/events/301884492/",
  "date": "2026-09-17T18:30:00+00:00",
  "city": "London",
  "venue": "Runway East, Borough",
  "price": "Free",
  "category": "technology",
  "search_query": "AI",
  "filter_date_from": "2026-09-01",
  "filter_date_to": "2026-09-30"
}
```

#### What a successful run looks like

- **Status:** `SUCCEEDED`
- **Dataset:** one item per matched event, saved incrementally as each source finishes
- **Log:** a per-source progress line, then a final count with how many events were excluded
  by the date filter
- **Zero results is also a success.** A narrow keyword, a tight date window, a small city or a
  subset of sources can all legitimately match nothing. The run still succeeds with an empty
  dataset — check the log to see which sources ran and which were skipped.

#### Dataset views

| View | Shows |
|---|---|
| **Events** | Every matched event with date, venue, price, category, source and link |
| **By source** | The same events grouped for coverage comparison across platforms |
| **Filters applied** | Which keyword and date window each event was matched against |

***

### Invocation & Integration

#### Apify Console

Open the [Actor page](https://apify.com/techforce.global/smart-event-scraper), fill in the
Input tab, click **Start**.

#### MCP — add as an agent tool

```bash
claude mcp add apify --transport http https://mcp.apify.com/?actors=techforce.global/smart-event-scraper
```

Then ask your agent for *"technology events in London in September"* and it will call this
Actor with the right input.

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")

run = client.actor("techforce.global/smart-event-scraper").call(run_input={
    "location": "London",
    "category": "technology",
    "search_query": "AI",
    "date_from": "2026-09-01",
    "date_to": "2026-09-30",
    "sources": ["allevents", "eventbrite", "meetup", "conferencealerts"],
    "limit": 25,
})

for event in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(event["date"], "|", event["title"], "|", event["source"])
```

#### JavaScript / TypeScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });

const run = await client.actor('techforce.global/smart-event-scraper').call({
    location: 'London',
    category: 'technology',
    search_query: 'AI',
    date_from: '2026-09-01',
    date_to: '2026-09-30',
    limit: 25,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.table(items.map(({ title, date, source }) => ({ title, date, source })));
```

#### cURL — synchronous (waits, returns the dataset)

```bash
curl -X POST "https://api.apify.com/v2/acts/techforce.global~smart-event-scraper/run-sync-get-dataset-items?token=%3CYOUR_APIFY_TOKEN%3E" \
  -H 'Content-Type: application/json' \
  -d '{
        "location": "London",
        "category": "technology",
        "date_from": "2026-09-01",
        "date_to": "2026-09-30",
        "limit": 25
      }'
```

#### cURL — asynchronous with a spend cap

```bash
curl -X POST "https://api.apify.com/v2/acts/techforce.global~smart-event-scraper/runs?token=%3CYOUR_APIFY_TOKEN%3E&maxTotalChargeUsd=2" \
  -H 'Content-Type: application/json' \
  -d '{ "location": "London", "category": "any", "limit": 50 }'
```

`maxTotalChargeUsd` is the hard ceiling for the run. Use it on any unattended or scheduled run.

#### With MCP delivery — matched events straight into Notion

```json
{
  "location": "London",
  "category": "technology",
  "date_from": "2026-09-01",
  "date_to": "2026-09-30",
  "limit": 25,
  "mcpConnector": "notion",
  "mcpTool": "notion-create-page",
  "deliveryMode": "summary",
  "mcpArguments": {
    "parent": { "database_id": "<YOUR_NOTION_DATABASE_ID>" },
    "title": "Tech events in {location} — {dateFrom} to {dateTo}",
    "content": "{eventCount} events found ({sourceBreakdown})\n\n{events}"
  }
}
```

Switch `deliveryMode` to `perEvent` for one Notion page per event, or `chunked` when the run
returns more events than a single page comfortably holds.

***

### Autonomous Agent Error Handling & Resolution Matrix

Each row is a condition observable from the run's status message, log or dataset.

| Condition | What you see | Cause | Deterministic action |
|---|---|---|---|
| `NO_VALID_CATEGORY` | Status `Skipped: Please select at least one valid category.` — empty dataset | `category` was missing, empty or not a valid value | **Modify Input:** set `category` to `any` or one of the six values. Do not retry unchanged. |
| `DISTRICT_SKIPPED` | Log warns District only covers Indian cities | `location` is not an Indian city District serves | **Expected.** Drop `district` from `sources` for non-Indian cities to remove the warning. |
| `MEETUP_SKIPPED_UNKNOWN_COUNTRY` | Log warns the country for the city could not be resolved; Meetup returns nothing | City is outside the recognised city list | **Modify Input:** set `country_code` to the correct ISO-2 code and retry. |
| `COUNTRY_CODE_OVERRIDE_WARNING` | Log warns your `country_code` overrides the known country for that city | `country_code` disagrees with the detected country | **Modify Input:** clear `country_code` unless you meant it. Results may be from another country. |
| `ZERO_RESULTS` | `SUCCEEDED`, empty dataset | Filters too narrow, small city, or the chosen sources had nothing | **Widen, then retry once:** drop `search_query`, widen the date window, or use `category: "any"`. |
| `SOURCE_TIMED_OUT` | Log notes a source timed out and kept partial results | That platform was slow or unresponsive this run | **Retry later, or exclude the source.** Other sources are unaffected — data already saved is valid. |
| `FEWER_THAN_LIMIT` | Dataset smaller than `limit × sources` | De-duplication, category classification and date filtering all remove rows | **Expected.** `limit` is a ceiling per task, not a quota. |
| `FREE_PLAN_CAPPED` | Status says up to 1 result per source; tiny dataset | Free Apify plan | **Upgrade the plan.** Retrying will not change it. |
| `EVENTBRITE_PRICE_UNAVAILABLE` | Log notes no Eventbrite API token; `price` is `"N/A"` | Optional price enrichment not configured | **Optional:** set the `EVENTBRITE_API_TOKEN` environment variable for richer price data. |
| `CONNECTOR_TOOL_NOT_FOUND` | Log: tool not available on this connector, followed by the available tools | `mcpTool` name is wrong | **Modify Input:** copy an exact tool name from that log line. Dataset is unaffected. |
| `CONNECTOR_NO_TOOL` | Log: a connector is selected but no tool name was provided | `mcpConnector` set, `mcpTool` empty | **Modify Input:** set `mcpTool`, or clear `mcpConnector`. |
| `CONNECTOR_UNREACHABLE` | Log: could not reach the connector | Connector not authorised on the account, or running outside the Apify platform | **Authorise the connector** in Apify, or set `deliveryMode: "none"`. Data is already saved. |
| `MEMORY_KILLED` | Run fails or a source dies mid-way | Run memory too low for browser-backed sources | **Raise memory to at least 2 GB** and retry. |

> Verify any platform-level HTTP status behaviour against the
> [Apify API reference](https://docs.apify.com/api/v2) before relying on it in automation —
> the rows above describe **this Actor's** observable behaviour, not Apify's transport layer.

***

### Natural Language → Actor Mapping

| A user says… | Intent | Input |
|---|---|---|
| "Tech events in London next month" | Category + city + window | `{"location":"London","category":"technology","date_from":"2026-09-01","date_to":"2026-09-30"}` |
| "What's happening in Chicago this week?" | Everything, narrow window | `{"location":"Chicago","category":"any","date_from":"2026-08-25","date_to":"2026-08-31"}` |
| "Find AI workshops in New York" | Keyword | `{"location":"New York","category":"technology","search_query":"AI workshop"}` |
| "Business networking events in Mumbai" | Category + city | `{"location":"Mumbai","category":"business"}` |
| "Trade shows in Frankfurt" | Exhibitions only | `{"location":"Frankfurt","category":"any","sources":["eventseye"]}` |
| "Academic conferences in Singapore" | Conferences only | `{"location":"Singapore","category":"any","sources":["conferencealerts"]}` |
| "Online React meetups" | Keyword + online | `{"location":"London","category":"technology","search_query":"React","sources":["meetup"],"eventType":"online"}` |
| "Food festivals in Austin in October" | Category + window | `{"location":"Austin","category":"food","date_from":"2026-10-01","date_to":"2026-10-31"}` |
| "Art exhibitions in Berlin" | Category | `{"location":"Berlin","category":"arts"}` |
| "Just Eventbrite and Meetup, Ahmedabad, health" | Source subset | `{"location":"Ahmedabad","category":"health","sources":["eventbrite","meetup"]}` |
| "Give me everything in Delhi, no filters" | Broadest run | `{"location":"Delhi","category":"any","limit":100}` |
| "Put next month's London tech events in our Notion" | Scrape + deliver | Above, plus `mcpConnector`, `mcpTool`, `mcpArguments` |
| "Post today's Bangalore startup events to Slack" | Scrape + deliver | `{"location":"Bangalore","category":"business","search_query":"startup","mcpConnector":"slack","mcpTool":"slack-post-message","deliveryMode":"summary"}` |

**Should NOT route here:** who is *attending* an event · organiser or attendee **email
addresses and phone numbers** · **buying tickets** or checking seat availability · full event
**descriptions, agendas or speaker lists** · **several cities** in one run · **past events** or
historical archives · event **images or banners** · venue reviews or ratings · a **single
platform scraped exhaustively** with no filters (use that platform's dedicated Actor).

***

### Agent Execution & Routing Logic

```
Does the user want UPCOMING EVENTS for ONE city?
├── NO → not this Actor.
│        attendees/contacts → no Actor in this family returns them
│        tickets/booking    → not a scraping task
│        many cities        → one run per city (schedule or fan out)
│        past events        → not available
│
└── YES
    │
    ├── Do they name a category or interest?
    │     ├── yes → category: technology | business | food | health | arts | education
    │     └── no  → category: "any"        (broadest AND fastest)
    │
    ├── Do they name a keyword or topic?  → search_query: "<keyword>"
    │
    ├── Do they name a time window?       → date_from / date_to as YYYY-MM-DD
    │
    ├── Do they name a kind of event?
    │     ├── trade shows / exhibitions   → sources: ["eventseye"]
    │     ├── academic conferences        → sources: ["conferencealerts"]
    │     ├── community meetups           → sources: ["meetup"]  (+ eventType)
    │     ├── Indian city, local listings → sources include "district"
    │     └── unspecified                 → leave sources at all six
    │
    ├── Is the city outside the common list?  → set country_code (ISO-2)
    │
    ├── Set limit: start at 10, confirm the count, then scale (it is PER TASK)
    │
    └── Should the results land in another app?
          ├── yes → mcpConnector + mcpTool + deliveryMode
          │           one item per event   → perEvent
          │           one digest per run   → summary
          │           too many for one doc → chunked
          └── no  → leave mcpConnector empty; dataset only
```

***

### Cost Control & Pricing Transparency

This Actor bills **per event pushed** (pay-per-event), not per minute of compute. You pay for
the events that actually matched your filters — a run that finds nothing costs nothing in event
charges. Current per-event rates are shown on the
[Actor's Apify page](https://apify.com/techforce.global/smart-event-scraper); the Apify Console
shows the live total while a run is in progress.

**What drives the cost of a run:**

| Choice | Effect on cost |
|---|---|
| `limit` | The main lever. It caps each scraping task, so the run ceiling is roughly `limit × number of tasks`. |
| `category: "any"` vs a specific category | `"any"` runs **one task per source**. A specific category runs one task per (source × category) — more tasks, more potential events. |
| `sources` | Fewer sources → fewer tasks → fewer events. Pick only the platforms you need. |
| `search_query` and date window | Narrower filters discard more events **before** they are charged. |
| De-duplication | Cross-platform duplicates are removed before saving, so you are not charged twice for the same event. |

**Keeping runs predictable:**

1. **Start with `limit: 10` and one or two sources.** Read the final log count, then scale.
2. **Always set a spend cap on unattended runs** — `maxTotalChargeUsd` on the API call, or the
   run limit in the Console. This is the only hard ceiling.
3. **Prefer narrow filters over a big `limit`.** A tight date window with `limit: 50` usually
   costs less and is more useful than `limit: 10` with no filters.
4. **Free Apify plans are capped at 1 result per source**, which makes free runs effectively a
   smoke test rather than a data pull.

***

### Troubleshooting

| # | Symptom you see | Most likely cause | Fix |
|:--|---|---|---|
| 1 | Run ends immediately with a `Skipped: Please select at least one valid category.` status | `category` was missing, empty, or not one of the seven accepted values | Set `category` to `any` or one of the six named values. It is a **required** field, and an invalid value exits rather than defaulting. |
| 2 | Empty dataset, `SUCCEEDED` status | Filters too narrow, a small city, or the selected sources had nothing for that window | Widen once: drop `search_query`, open the date window, or switch to `category: "any"`. Then stop — repeated identical retries will not help. |
| 3 | Far fewer rows than `limit × sources` | `limit` is a **per-task ceiling, not a quota**, and de-duplication, category classification and date filtering all remove rows afterwards | Expected. Read the final log count rather than predicting from `limit`. |
| 4 | Many more rows than you expected | A **specific** category runs one task per (source × category); `"any"` runs one task per source | Use `"any"` for the widest and fastest run, or lower `limit` when naming a category. |
| 5 | District returned nothing and the log warns about Indian cities | District covers Indian cities only and is skipped elsewhere by design | Expected. Remove `district` from `sources` for non-Indian locations to silence the warning. |
| 6 | Meetup returned nothing and the log says the city's country could not be resolved | The city is outside the recognised list, so no country could be derived | Set `country_code` to the correct ISO-2 code (`gb`, `us`, `in`) and retry. |
| 7 | Results are from the wrong country | `country_code` was set and disagrees with the city's detected country — your value wins | Clear `country_code` unless you meant it. The log warns when the override happens. |
| 8 | `location: "London, UK"` behaves oddly | `location` takes a **plain city name**, not a city-plus-country string, and not a list or region | Pass `London`. Use `country_code` if disambiguation is genuinely needed. |
| 9 | A keyword search returns events that don't contain the keyword | Platforms with their own search engine handle the query server-side and their relevance ranking is trusted | Expected, and usually desirable. Filter `title` locally afterwards if you need literal matching. |
| 10 | EventsEye or District results look category-filtered oddly | Both publish city-wide listings only, so with a named category their events are keyword-classified and dropped when nothing matches | Use `category: "any"` to keep everything those two list. |
| 11 | Events outside the date window still appear | The filter compares against the date the source published, and an event whose date cannot be parsed is not excluded | Treat the window as a strong filter, not a guarantee. Re-filter on `date` in your consumer if it must be exact. |
| 12 | Eventbrite `price` is `"N/A"` on every row | The optional `EVENTBRITE_API_TOKEN` environment variable is not set, so price enrichment is skipped | Optional. Set the variable for richer Eventbrite pricing; everything else works without it. |
| 13 | One source returned nothing while the others worked | Each source has its own time budget — a slow platform is cancelled and the run keeps whatever it had | Retry later, or drop that source. Data already saved is valid. |
| 14 | Run fails, or a source dies mid-way | Run memory too low for the browser-backed sources | Give the run at least **2 GB**. The Actor declares 2–4 GB for this reason. |
| 15 | Exactly 1 result per source | Free Apify plan cap | Upgrade the plan. The run finishes successfully and says so in its status message. |
| 16 | Connector configured but nothing delivered | `mcpTool` is empty — a connector without a tool name logs a warning and skips delivery | Set `mcpTool`. If the name is wrong, the log lists every tool the connector actually offers. |
| 17 | Connector errors partway through a large run | `perEvent` mode makes one call per event | Switch to `chunked` or `summary`. |

#### Diagnostic checklist before opening an issue

1. **Read the status message first.** An input problem produces a `Skipped: …` terminal status rather than a failure, and it names the reason.
2. **Confirm the run's status.** `SUCCEEDED` with zero rows is a valid outcome here, not a crash.
3. **Probe narrow:** one source, `category: "any"`, `limit: 10`, no `search_query`, no dates. If that returns events, the pipeline works and the issue is your filters.
4. **Check memory is at least 2 GB** before blaming a source that returned nothing.
5. **Scan the log for per-source warnings.** District skipping, an unresolved country, a `country_code` override and a source timeout each look identical from the dataset but need different fixes.

If it survives all five, open an **Issues** ticket with the **run ID**, the **exact input JSON**, and what you expected.

***

### FAQ

#### Setup & scope

**Do I need accounts or API keys for the six platforms?**

No. You need an **Apify** account and API token only. One optional extra: setting an `EVENTBRITE_API_TOKEN` environment variable enriches Eventbrite pricing, but every source works without it.

**Which platforms does it search?**

Six: AllEvents, Eventbrite, Meetup, District (Indian cities only), EventsEye (trade shows) and ConferenceAlerts (academic conferences). Pick a subset in `sources` for a faster, more focused run.

**Is this an official API for any of those platforms?**

No. This is an independent Actor and is not affiliated with, endorsed by, or sponsored by any of the six platforms.

**Can I plug it into Claude, Cursor, or a LangChain agent?**

Yes — it is a native MCP tool:

`claude mcp add --transport http apify "https://mcp.apify.com/?tools=techforce.global/smart-event-scraper"`

**How much memory does it need?**

At least 2 GB. Some sources are driven by a real browser, and below 2 GB those are liable to be killed mid-run. The Actor declares 2–4 GB.

#### Filters & input

**Is `limit` per run or per source?**

Per **task**. With `category: "any"` that is one task per source. With a named category it is one task per (source × category), so the run total can be several times `limit` before de-duplication removes overlaps.

**What does `category: "any"` actually do?**

It applies **no** category filter: every source runs once, every event is kept, and each row is labelled `"any"`. It is both the broadest option and the fastest.

**Can I search more than one city?**

No — `location` is a single plain city name. Loop the Actor per city from your orchestration layer.

**Should I set `country_code`?**

Leave it empty. It is detected from the city. Only set it when the log tells you a city's country could not be resolved — setting it wrongly overrides a correct detection and returns events from another country.

**Why is `eventType` listed as Meetup-only?**

Because only Meetup exposes an in-person vs online distinction the Actor can pass through. Every other source ignores the field.

**Are duplicates removed across platforms?**

Yes. The same event listed on two platforms is de-duplicated before saving, so you are not charged twice for it.

#### Output & data

**What do I get per event?**

Eleven fields: `source`, `title`, `url`, `date`, `city`, `venue`, `price`, `category`, plus `search_query`, `filter_date_from` and `filter_date_to` echoing the filters that produced the row. Three Console views group them: overview, by source, and filters applied.

**Why do the rows carry my own filter values back?**

So a dataset assembled from several runs stays self-describing — you can tell which query and date window produced any given row without keeping a separate log.

**Are the dates normalised to one format?**

No. `date` is captured as each platform presents it, and formats differ between them. Parse before sorting, and expect some values that no parser will accept.

**Do I get attendee lists, organiser emails, or ticket availability?**

No. Public listing fields only — no personal data and no authenticated pages.

**Why is `price` sometimes `"N/A"`?**

Because the platform did not publish one on the listing, or, for Eventbrite specifically, because the optional price-enrichment token is not configured.

#### Cost & runtime

**How is this billed?**

Pay-per-event: you are charged for events **pushed to the dataset**, not for compute time. A run that matches nothing costs nothing in event charges. Current rates are on the Actor's Apify page.

**What drives the cost of a run?**

`limit` first, then the number of sources, then whether you named a category (which multiplies the task count). Narrow filters discard events *before* they are charged, so a tight date window with a higher `limit` is often both cheaper and more useful than a low `limit` with no filters.

**What does the free plan give me?**

1 result per source — a smoke test to confirm a city and category return anything, rather than a data pull.

**How do I guarantee an agent never overspends?**

Pass `maxTotalChargeUsd` as a query parameter on the run endpoint. It is the only hard ceiling, and it is worth setting on every unattended or scheduled run.

***

### Companion machine-readable files

| File | What it defines |
|---|---|
| [`.actor/input_schema.json`](.actor/input_schema.json) | Every input, its type, default, allowed values and validation |
| [`.actor/dataset_schema.json`](.actor/dataset_schema.json) | Output field types and the three Console views |
| [`.actor/output_schema.json`](.actor/output_schema.json) | Where the run's output is exposed |
| [`.actor/actor.json`](.actor/actor.json) | Actor identity, memory bounds and environment variables |

> **If this page and the schema files disagree, the schema files win.** They are what the
> platform validates against at run time; this page is documentation and can lag behind a
> release. Validate generated input against `input_schema.json`, not against this README.

***

### Related Actors by Techforce Global

| Actor | Best for |
|---|---|
| **This Actor** | **Filtered** event discovery across **six platforms** at once — category, keyword, date range |
| [Meetup Scraper](https://apify.com/techforce.global/meetup-scraper) | Meetup only, scraped exhaustively for one city |
| [District Events Scraper](https://apify.com/techforce.global/district-events-scraper) | District only, all categories for an Indian city |
| [All Events Scraper](https://apify.com/techforce.global/all-events-scraper) | AllEvents only, full city listings |
| [Ticketmaster Scraper](https://apify.com/techforce.global/ticketmaster-scraper) | Ticketed concerts, sports and shows |
| [Eventim Scraper](https://apify.com/techforce.global/eventim-scraper) | European ticketed events |

Use a single-platform Actor when you want **everything** one site lists. Use **this** Actor
when you want **only what matches** — across all of them.

> Browse the full catalogue at **[scraper.techforce.global](https://scraper.techforce.global/)**.

***

### Compliance & Data Privacy

- **Public listings only.** Everything returned is published on a public event page with no
  login. Nothing behind authentication is accessed.

- **No personal data is collected.** No attendee names, no attendee or organiser email
  addresses, no phone numbers. Output is event metadata: name, date, city, venue, price,
  category, link. Under **GDPR / UK GDPR** and **CCPA/CPRA**, event metadata of this kind is
  not personal data.

- **Organiser names are out of scope.** The dataset carries a venue or place name, not an
  individual's contact details. If a *venue* field happens to contain a person's name (a
  sole-trader studio, for example), you become a controller for that field the moment you store
  it — apply your own retention policy.

- **Marketing to organisers is your responsibility.** This Actor gives you no contact route,
  and finding one elsewhere puts you under **CAN-SPAM** (US), **CASL** (Canada),
  **ePrivacy/PECR** (UK/EU) and India's **DPDP Act 2023**. Consent and opt-out are the
  sender's obligation, not the scraper's.

- **Each platform's Terms of Service apply to you.** AllEvents, Eventbrite, Meetup, District,
  EventsEye and ConferenceAlerts each set their own terms on automated access and on reusing
  their listings — including republishing them commercially. Review the terms of the sources
  you enable and stay within them.

- **Attribution and re-publication.** Event listings are the platforms' and organisers'
  content. Link back rather than mirroring wholesale, and don't present a scraped listing as
  your own original content.

- **Data minimisation.** Use `sources`, `category`, `search_query`, the date window and `limit`
  to collect what you need and nothing more. It is cheaper, faster and the defensible position.

***

### 🆘 Support & Custom Pipeline Engineering

Need automated multi-city scheduled feeds, webhook enrichment, or enterprise data warehouse syncs?

- **Email**: bhavin.shah@techforceglobal.com
- **Custom Enterprise Integrations**: [Book a 15-Minute Technical Consultation](https://calendly.com/techforce-global/intro-meeting)
- **Maintained by**: [Techforce Global](https://www.techforceglobal.com) — Specialists in High-Performance Web Scrapers and Agentic Workflows.

***

<sub>Built and maintained by **Techforce Global**. Scrapes public event listings only —
no personal data, no authenticated pages. You are responsible for complying with each source
platform's Terms of Service and with the data-protection law of your jurisdiction.</sub>

***

### 🏷️ Structured data for search & AI discovery

`SoftwareApplication` describes the Actor; `FAQPage` wraps the FAQ above so those answers are
eligible for rich results, matching it question-for-question.

```json
{
  "@context": "https://schema.org/",
  "@type": "SoftwareApplication",
  "name": "Smart Event Scraper",
  "alternateName": "Smart Event Scraper — Category, Date Range & Keyword Filter Across 6 Event Platforms",
  "applicationCategory": "BusinessApplication",
  "applicationSubCategory": "Web Scraping / Event Data Aggregation",
  "operatingSystem": "Any (cloud-hosted on Apify)",
  "url": "https://apify.com/techforce.global/smart-event-scraper",
  "description": "Searches AllEvents, Eventbrite, Meetup, District, EventsEye and ConferenceAlerts in a single run and returns only the events matching the chosen city, category, keyword and date range — de-duplicated across platforms, with an optional direct delivery into Notion, Slack, Linear or Google Sheets over MCP.",
  "author": {
    "@type": "Organization",
    "name": "Techforce Global",
    "url": "https://scraper.techforce.global/"
  },
  "provider": {
    "@type": "Organization",
    "name": "Apify",
    "url": "https://apify.com/"
  },
  "offers": {
    "@type": "Offer",
    "category": "Pay per event",
    "description": "Billed per event pushed to the dataset. Current rates are shown on the Actor's Apify page.",
    "url": "https://apify.com/techforce.global/smart-event-scraper"
  },
  "featureList": [
    "Six event platforms searched in one run",
    "Category filter applied during the run, not after",
    "Keyword search handled server-side or locally per platform",
    "Date-range filter across every source",
    "Cross-platform de-duplication, so an event listed twice is charged once",
    "Location resolved before scraping, unresolvable cities skipped rather than guessed",
    "Trade shows and academic conferences alongside general listings",
    "Per-source time budgets so one slow platform never stalls the run",
    "Browser concurrency capped so parallel sources do not starve each other",
    "Each row echoes the query and date window that produced it, keeping multi-run datasets self-describing",
    "Charged per event saved, so a run that matches nothing costs nothing in event charges",
    "Optional Eventbrite price enrichment via an environment variable",
    "Optional MCP delivery to Notion, Slack, Linear, Google Sheets and more",
    "Chunked delivery mode keeps long event lists under connector size and timeout caps",
    "Three Console dataset views including cross-platform coverage"
  ],
  "isAccessibleForFree": false,
  "softwareRequirements": "Apify account and API token; at least 2 GB of run memory",
  "softwareHelp": {
    "@type": "CreativeWork",
    "url": "https://apify.com/techforce.global/smart-event-scraper"
  },
  "keywords": "event scraper, event data API, category filter, date range filter, keyword search, AllEvents scraper, Eventbrite scraper, Meetup scraper, District events, EventsEye trade shows, ConferenceAlerts, event aggregation, MCP connector, event calendar data"
}
```

```json
{
    "@context": "https://schema.org/",
    "@type": "FAQPage",
    "mainEntity": [
        {
            "@type": "Question",
            "name": "Do I need accounts or API keys for the six platforms?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "No. You need an Apify account and API token only. One optional extra: setting an EVENTBRITE_API_TOKEN environment variable enriches Eventbrite pricing, but every source works without it."
            }
        },
        {
            "@type": "Question",
            "name": "Which platforms does it search?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Six: AllEvents, Eventbrite, Meetup, District (Indian cities only), EventsEye (trade shows) and ConferenceAlerts (academic conferences). Pick a subset in sources for a faster, more focused run."
            }
        },
        {
            "@type": "Question",
            "name": "Is this an official API for any of those platforms?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "No. This is an independent Actor and is not affiliated with, endorsed by, or sponsored by any of the six platforms."
            }
        },
        {
            "@type": "Question",
            "name": "Can I plug it into Claude, Cursor, or a LangChain agent?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Yes - it is a native MCP tool. Add it with: claude mcp add --transport http apify \"https://mcp.apify.com/?tools=techforce.global/smart-event-scraper\""
            }
        },
        {
            "@type": "Question",
            "name": "How much memory does it need?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "At least 2 GB. Some sources are driven by a real browser, and below 2 GB those are liable to be killed mid-run. The Actor declares 2-4 GB."
            }
        },
        {
            "@type": "Question",
            "name": "Is limit per run or per source?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Per task. With category any that is one task per source. With a named category it is one task per source and category combination, so the run total can be several times limit before de-duplication removes overlaps."
            }
        },
        {
            "@type": "Question",
            "name": "What does category \"any\" actually do?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "It applies no category filter: every source runs once, every event is kept, and each row is labelled any. It is both the broadest option and the fastest."
            }
        },
        {
            "@type": "Question",
            "name": "Can I search more than one city?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "No - location is a single plain city name. Loop the Actor per city from your orchestration layer."
            }
        },
        {
            "@type": "Question",
            "name": "Should I set country_code?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Leave it empty. It is detected from the city. Only set it when the log tells you a city's country could not be resolved - setting it wrongly overrides a correct detection and returns events from another country."
            }
        },
        {
            "@type": "Question",
            "name": "Why is eventType listed as Meetup-only?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Because only Meetup exposes an in-person versus online distinction the Actor can pass through. Every other source ignores the field."
            }
        },
        {
            "@type": "Question",
            "name": "Are duplicates removed across platforms?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Yes. The same event listed on two platforms is de-duplicated before saving, so you are not charged twice for it."
            }
        },
        {
            "@type": "Question",
            "name": "What do I get per event?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Eleven fields: source, title, url, date, city, venue, price and category, plus search_query, filter_date_from and filter_date_to echoing the filters that produced the row. Three Console views group them: overview, by source, and filters applied."
            }
        },
        {
            "@type": "Question",
            "name": "Why do the rows carry my own filter values back?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "So a dataset assembled from several runs stays self-describing - you can tell which query and date window produced any given row without keeping a separate log."
            }
        },
        {
            "@type": "Question",
            "name": "Are the dates normalised to one format?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "No. date is captured as each platform presents it, and formats differ between them. Parse before sorting, and expect some values that no parser will accept."
            }
        },
        {
            "@type": "Question",
            "name": "Do I get attendee lists, organiser emails, or ticket availability?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "No. Public listing fields only - no personal data and no authenticated pages."
            }
        },
        {
            "@type": "Question",
            "name": "Why is price sometimes \"N/A\"?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Because the platform did not publish one on the listing, or, for Eventbrite specifically, because the optional price-enrichment token is not configured."
            }
        },
        {
            "@type": "Question",
            "name": "How is this billed?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Pay-per-event: you are charged for events pushed to the dataset, not for compute time. A run that matches nothing costs nothing in event charges. Current rates are on the Actor's Apify page."
            }
        },
        {
            "@type": "Question",
            "name": "What drives the cost of a run?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "limit first, then the number of sources, then whether you named a category, which multiplies the task count. Narrow filters discard events before they are charged, so a tight date window with a higher limit is often both cheaper and more useful than a low limit with no filters."
            }
        },
        {
            "@type": "Question",
            "name": "What does the free plan give me?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "1 result per source - a smoke test to confirm a city and category return anything, rather than a data pull."
            }
        },
        {
            "@type": "Question",
            "name": "How do I guarantee an agent never overspends?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Pass maxTotalChargeUsd as a query parameter on the run endpoint. It is the only hard ceiling, and it is worth setting on every unattended or scheduled run."
            }
        }
    ]
}
```

# Actor input Schema

## `search_query` (type: `string`):

Optional keyword search passed to native search bars (e.g. 'AI workshop', 'React meetup'). Falls back to client-side filtering for sources that don't support native search.

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

The event category to scrape. Choose 'Any' to pull all event types (fastest — runs each source once with no category filter).

## `sources` (type: `array`):

Which event platforms to scrape. Leave all selected to search everywhere; pick a subset for faster, more focused runs. Note: District covers Indian cities only — it is automatically skipped for non-Indian locations.

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

City name used by all scrapers (e.g. New York, Chicago, London).

## `country_code` (type: `string`):

Two-letter ISO country code for the location (e.g. 'gb' for London, 'us' for Chicago). Leave empty — it is detected automatically from the city. Only set this if the Actor reports it cannot resolve your city's country.

## `limit` (type: `integer`):

Max events to return. Set to 0 for no limit.

## `date_from` (type: `string`):

Filter events on or after this date.

## `date_to` (type: `string`):

Filter events on or before this date.

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

Whether Meetup should return in-person or online events. Ignored by every other source.

## `mcpConnector` (type: `string`):

Apify MCP connector ID to deliver the events to (for example notion, slack, linear, google-sheets). Leave empty to skip delivery. The connector must be authorised on your Apify account.

## `mcpTool` (type: `string`):

Name of the tool to call on that connector (for example notion-create-page, slack-post-message). Required when a connector is set. If the name is wrong, the run log lists every tool the connector actually offers.

## `deliveryMode` (type: `string`):

How the events are grouped into connector calls. perEvent = one call per event. chunked = several events per call, split so no call gets too large. summary = a single call for the whole run.

## `mcpArguments` (type: `object`):

Arguments passed to the connector tool. Any {placeholder} in a string value is replaced per call. Event placeholders: {title} {url} {date} {city} {venue} {price} {category} {source} {event}. Run placeholders: {location} {categories} {sources} {searchQuery} {dateFrom} {dateTo} {eventCount} {sourceBreakdown} {events} {part} {partCount} {message}.

## `mcpMessageTemplate` (type: `string`):

Text rendered into the {message} placeholder. Accepts the same placeholders as the arguments above.

## Actor input object example

```json
{
  "search_query": "",
  "category": "any",
  "sources": [
    "allevents",
    "eventbrite",
    "meetup",
    "district",
    "eventseye",
    "conferencealerts"
  ],
  "location": "New York",
  "country_code": "",
  "limit": 10,
  "date_from": "",
  "date_to": "",
  "eventType": "inPerson",
  "mcpConnector": "",
  "mcpTool": "",
  "deliveryMode": "summary",
  "mcpArguments": {},
  "mcpMessageTemplate": ""
}
```

# Actor output Schema

## `results` (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 = {
    "sources": [
        "allevents",
        "eventbrite",
        "meetup",
        "district",
        "eventseye",
        "conferencealerts"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("techforce.global/smart-event-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 = { "sources": [
        "allevents",
        "eventbrite",
        "meetup",
        "district",
        "eventseye",
        "conferencealerts",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("techforce.global/smart-event-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 '{
  "sources": [
    "allevents",
    "eventbrite",
    "meetup",
    "district",
    "eventseye",
    "conferencealerts"
  ]
}' |
apify call techforce.global/smart-event-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,techforce.global/smart-event-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/TlT1NfTkQs2qfjzz4/builds/mQLE0sAmt44rgqi7e/openapi.json
