# Eventbrite Scraper - Events, Ticket Prices & Sold-Out Monitor (`neverempty/eventbrite-scraper`) Actor

For event aggregators, newsletters and ticket-market research: Eventbrite events by city, keyword, category, date and free/paid, with venue, organizer, the price range buyers see and ticket status (sold out, cancelled, postponed). Keyword matches are checked. Monitor: only new events and changes.

- **URL**: https://apify.com/neverempty/eventbrite-scraper.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Lead generation, Travel, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.60 / 1,000 event returneds

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

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

## Eventbrite Scraper - Events, Ticket Prices & Sold-Out Monitor

Search **Eventbrite** events by city, keyword, category, date range and free/paid, and get each event's date and time, venue and address, organizer, **price range as shown on the event page** and **ticket status** (on sale, sold out, sales ended, not yet on sale, cancelled, postponed). Turn on **monitor mode** and every run returns only **new events** and **events whose price, ticket status, start time, venue or title changed** since the last run.

Unofficial. Reads only public Eventbrite pages, without logging in. Organizers are returned by name and Eventbrite organizer page only - no personal contact details.

### What makes it different

- **Keyword matches are checked.** Eventbrite's keyword search is a ranking, not a filter: a made-up word such as `qwxyzplokqq` still returns "10,000 events" in New York, and deep pages of a `jazz` search are mostly other music (measured 2026-09-24). Every row has `keywordMatch`; by default only events whose title, summary, category or tags contain every word of the keyword are returned, and a search stops after 3 list pages in a row without a match.
- **Prices as the buyer sees them.** Price range and sold-out come from the same ticket panel the event page uses ("From $23.07"), not from the search-engine markup in the page source, which can differ (for one boat party it said $28.39-$374.34 while the page said from $23.07).
- **Filters are verified.** Eventbrite reports which filters it applied to each list page. If a category, date, price or keyword filter you asked for was not applied, the list is not sold as a filtered list - you get a free row saying so.
- **Monitor mode that does not invent news.** A watch only judges a list it could read to the end. A search larger than what Eventbrite shows (980 events) returns a free row asking you to narrow it, instead of selling events that merely moved into view as "new".
- **No results, no charge.** Unknown places, empty searches, unreadable pages and verification pages come back as free rows that say why. The run start fee is charged only when something was actually returned or a watch check was completed.

### Input

| Field | Type | Description |
|---|---|---|
| `locations` | list | `City, ST` in the US (`Austin, TX`), `City, Country` elsewhere (`London, United Kingdom`, `Berlin, Germany`), `online`, or the part after `/d/` in an Eventbrite search link (`ny--new-york`). Each location is searched with each keyword (up to 10 searches per run). Empty everything = example search New York, NY. |
| `keywords` | list | Optional search words (`jazz`, `wine tasting`, `startup`). |
| `category` | select | Optional: business, food-and-drink, health, music, auto-boat-and-air, charity-and-causes, community, family-and-education, fashion, film-and-media, hobbies, home-and-lifestyle, arts, government, spirituality, school-activities, science-and-tech, holiday, sports-and-fitness, travel-and-outdoor, other. |
| `dateRange` | select | Optional: today, tomorrow, this-weekend, this-week, next-week, this-month, next-month. |
| `startDate` / `endDate` | date | Optional custom range (YYYY-MM-DD). Use this or `dateRange`, not both. |
| `price` | select | Optional: `free` or `paid`. |
| `maxResultsPerSearch` | number | Events per search, 1-980. Empty = 20. |
| `includeDetails` | checkbox | On (default): open each event page for price range, ticket status, organizer, UTC times, full address. Off: faster, search list only. |
| `onlyKeywordMatches` | checkbox | On (default): return only events matching every word of the keyword. |
| `eventUrls` | list | Optional Eventbrite event links or IDs (up to 50) to check directly. |
| `onlyNew` | checkbox | Monitor mode: only new and changed events. |
| `watchName` | text | Optional name to keep separate monitor memories (letters, digits, `.`, `-`, `_`). |
| `resetMonitoringState` | checkbox | Forget this watch's memory and start again. |

#### Examples

Jazz this weekend in New York, free only:

```json
{ "locations": ["New York, NY"], "keywords": ["jazz"], "dateRange": "this-weekend", "price": "free" }
```

Watch tech events in San Francisco and get only new ones and price/sold-out changes (schedule it daily):

```json
{ "locations": ["San Francisco, CA"], "category": "science-and-tech", "onlyNew": true, "watchName": "sf-tech" }
```

Check the price and status of specific events:

```json
{ "eventUrls": ["https://www.eventbrite.com/e/16th-annual-nyc-pizza-run-tickets-1995478167917"] }
```

### Output

One row per event (`status: "ok"`), for example:

```json
{
  "status": "ok",
  "changeType": null,
  "name": "16th Annual NYC Pizza Run",
  "eventId": "1995478167917",
  "eventUrl": "https://www.eventbrite.com/e/16th-annual-nyc-pizza-run-tickets-1995478167917",
  "startDate": "2026-09-27", "startTime": "11:00", "startUtc": "2026-09-27T15:00:00Z", "timezone": "America/New_York",
  "ticketStatus": "on-sale", "isSoldOut": false, "isFree": false,
  "priceMin": 80.81, "priceMax": 92.55, "currency": "USD", "ticketTypes": 2,
  "venueName": "Fort Greene Park", "venueAddress": "320 Myrtle Ave, Brooklyn, NY 11205", "city": "Brooklyn", "region": "NY", "country": "US",
  "organizerName": "NYC Pizza Run", "organizerUrl": "https://www.eventbrite.com/o/nyc-pizza-run-109137132381",
  "category": "Food & Drink", "format": "Race",
  "detailsRead": true, "keywordMatch": null
}
```

Main fields: `name`, `eventId`, `eventUrl`, `summary`, `startDate`, `startTime`, `endDate`, `endTime`, `startUtc`, `endUtc`, `timezone`, `isOnline`, `ticketStatus` (`on-sale`, `sold-out`, `sales-ended`, `not-yet-on-sale`, `unavailable`, `cancelled`, `postponed`, `started`, `ended`), `isSoldOut`, `isFree`, `priceMin`, `priceMax`, `currency`, `ticketTypes`, `waitlistAvailable`, `salesStatus`, `salesMessage`, `fewTicketsLeft`, `goingFast`, `salesEndSoon`, `category`, `subcategory`, `format`, `tags`, `venueName`, `venueAddress`, `city`, `region`, `country`, `postalCode`, `latitude`, `longitude`, `organizerId`, `organizerName`, `organizerUrl`, `organizerVerified`, `organizerEventCount`, `isSeries`, `ticketsBy`, `hasExternalTickets`, `publishedAt`, `imageUrl`, `detailsRead`, `keywordMatch`, `positionInSearch`, `eventsInSearch`, `eventsInSearchIsCapped`, `searchLocation`, `searchKeyword`, `searchCategory`, `searchDateRange`, `searchPrice`, `searchUrl`, `watchName`, `checkedAt`.

Monitor mode adds `changeType` (`first-check`, `new`, `changed`), `changes` (for example `ticket status on-sale -> sold-out`, `price 80.81-92.55 USD -> 99.5-120.25 USD`) and `previousTicketStatus`, `previousPriceMin`, `previousPriceMax`, `previousStartUtc`.

`priceMin` / `priceMax` are `null` (not 0) when Eventbrite no longer shows prices, for example after sales ended or for a cancelled event. `eventsInSearch` is the number Eventbrite reports for the search (`null` when it only says "10,000+"); for keyword searches that number includes Eventbrite's filler events.

Free rows (not charged) have another `status` and a `note`: `no-results`, `no-keyword-matches`, `not-found`, `no-changes`, `too-broad-to-watch`, `not-checked`, `more-not-returned`, `incomplete`, `unreadable`, `blocked`, `budget-reached`, `bad-input`.

### How monitor mode works

1. The first run reads the whole list of each search, returns up to `maxResultsPerSearch` events (`first-check`) and remembers the whole list as the starting point.
2. Later runs read the whole list again and return events that were not on it before (`new`). Each run also re-opens up to 30 remembered events - first those whose list entry changed or that left the list, then the ones checked longest ago - and returns those whose price, ticket status, start time, venue or title changed (`changed`). An event whose page disappeared is returned once with `ticketStatus: "removed"`.
3. Events that could not be returned (charge limit, a page that could not be opened) are not remembered, so a later run returns them.
4. `new` means new on this search's list. With a rolling date range (for example `this-weekend`), events also enter the list as the dates move; `publishedAt` tells a newly published event from one that just came into the date range.

### Pricing

Pay per event: one fee per run start (charged when the first event row is returned, or when a watch has read and checked its whole list, even if nothing changed) plus one fee per event row. Free rows are never charged. If the maximum charge you set for a run has no room for the start fee plus one row, nothing is requested and nothing is charged.

### Measured (2026-09-24, Apify, 256 MB)

- Default input (20 New York events with prices): 41 requests (list page, then each event page and its ticket panel), 35-50 s.
- Checked against the event pages in a browser (title, venue, organizer, date, "From" price, sold-out / cancelled wording, where the page shows them): Chicago comedy 29 of 29, New York default 24 of 24, London free events 24 of 24, specific links incl. sold-out and cancelled 21 of 21.
- Monitor mode, 32-event list: first check 7-17 s, next check (whole list plus 30 remembered event pages) 36-61 s.
- From Apify's own connection 50 of 50 Eventbrite pages loaded; Apify datacenter proxies got Eventbrite's human-verification page 40 of 40 times, so they are not used. When the plain connection is refused, the Actor asks again through a residential connection.

### Limits

- Eventbrite shows at most 49 pages (980 events) for one search. Narrow big searches with a category, dates, free/paid or a smaller area. A keyword does not narrow the list (Eventbrite only reorders it), so it does not help a watch.
- Keyword matching looks at title, summary, category and tags - not the full description.
- When Eventbrite shows a human-verification (CAPTCHA) page, this Actor stops and says so. It does not solve or bypass it; events already returned are kept and charged, nothing else is.
- Two runs of the same watch at the same moment can both return the same new event. Avoid overlapping schedules for the same search and watch name.
- Private and password-protected events are not visible.

### Support

Found a problem or need another field? Open an issue in the **Issues** tab.

# Actor input Schema

## `locations` (type: `array`):

Where to search. "City, ST" in the US (Austin, TX), "City, Country" elsewhere (London, United Kingdom; Berlin, Germany), "online" for online events, or the part after /d/ in an Eventbrite search link (ny--new-york). Each location is searched with each keyword (up to 10 searches per run). Leave Locations, Keywords and Event links all empty to run the example search New York, NY.

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

Optional search words, for example jazz, wine tasting, startup, yoga. Eventbrite ranks by the keyword but also fills the list with other events; with "Only events that match the keyword" on (the default) only events whose title, summary, category or tags contain every word are returned.

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

Optional. One Eventbrite category. Empty = all categories.

## `dateRange` (type: `string`):

Optional. Eventbrite's own date filter. Use this or Start date / End date, not both. Empty = all upcoming events.

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

Optional. Events on or after this date (YYYY-MM-DD). Without an End date, only this day.

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

Optional. Events on or before this date (YYYY-MM-DD). Needs a Start date.

## `price` (type: `string`):

Optional. Empty = both.

## `maxResultsPerSearch` (type: `integer`):

Most events returned for one search (one location with one keyword). Eventbrite shows at most 980 (49 pages) for one search. Empty = 20. In monitor mode it limits the new events returned per search in one run; the rest come in the next run.

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

On (default): each returned event's page is opened for the price range and currency, ticket status (on sale, sold out, sales ended, not yet on sale, cancelled, postponed), organizer name and page, UTC times and full address. Off: faster, from the search list only (no price, ticket status or organizer name). Monitor mode needs it on to see price and status changes.

## `onlyKeywordMatches` (type: `boolean`):

On (default): return only events whose title, summary, category or tags contain every word of the keyword, and stop a search after 3 list pages in a row without a match. Off: return Eventbrite's list as it is (every row still has keywordMatch true/false).

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

Optional. Eventbrite event links or event IDs (up to 50), for example https://www.eventbrite.com/e/...-tickets-1995478167917. Each is opened and returned; in monitor mode only when its price, ticket status, start time, venue or title changed.

## `onlyNew` (type: `boolean`):

On: every run reads the whole list of each search and returns only events that were not on it at the previous check (new), and remembered events whose price, ticket status (sold out, cancelled, postponed...), start time, venue or title changed (changed, with the previous values). Each run re-opens up to 30 remembered events: those whose list entry changed or that left the list first, then the ones checked longest ago. The first run returns up to Max events per search and remembers the whole list. Runs with nothing new return a free row saying so. A search with more events than Eventbrite shows (980) cannot be watched completely and returns a free row asking to narrow it. Off = return the list as it is now.

## `watchName` (type: `string`):

Optional. Keeps separate memories for monitor mode, for example one per client (letters, digits, dot, dash, underscore; up to 40). Runs with the same watch name and the same search share what has already been returned.

## `resetMonitoringState` (type: `boolean`):

On: forget what this watch has seen for these searches and event links before running, so this run is a first check again.

## Actor input object example

```json
{
  "locations": [
    "New York, NY"
  ],
  "keywords": [
    "jazz"
  ],
  "includeDetails": true,
  "onlyKeywordMatches": true
}
```

# Actor output Schema

## `results` (type: `string`):

One row per Eventbrite event: name, link, start and end (local and UTC), venue and address, organizer name and page, category, ticket status (on sale, sold out, sales ended, cancelled, postponed...), price range and currency, and whether it matches every word of the keyword. Monitor mode marks rows first-check, new or changed (with what changed and the previous status and price). A search with no events, nothing new or changed, a place Eventbrite does not know, a human-verification page, an unreadable page or a run that hit its maximum charge comes back as a free row that says why.

# 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 = {
    "locations": [
        "New York, NY"
    ],
    "keywords": [
        "jazz"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/eventbrite-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 = {
    "locations": ["New York, NY"],
    "keywords": ["jazz"],
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/eventbrite-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 '{
  "locations": [
    "New York, NY"
  ],
  "keywords": [
    "jazz"
  ]
}' |
apify call neverempty/eventbrite-scraper --silent --output-dataset

```

## MCP server setup

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