# Ticketmaster Scraper - Events, Artists & Venues (`abotapi/ticketmaster-event-discovery`) Actor

Discover and scrape Ticketmaster events across the US, UK, Australia and Canada. Search by keyword, artist or venue, filter by city and date, or paste URLs directly. Includes incremental monitoring and resume support for ongoing event tracking.

- **URL**: https://apify.com/abotapi/ticketmaster-event-discovery.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 event records

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

## Ticketmaster Scraper: Events, Venues, Artists and Presale Dates

Ticketmaster Scraper turns Ticketmaster event listings into structured data you can use anywhere. Get upcoming events across 16 Ticketmaster markets, including the US, UK, Australia and Canada, with venue details, full artist lineups, presale windows and live status flags such as sold out, cancelled or postponed. Search by keyword on one market, or paste Ticketmaster search, venue and artist links to read their listings directly. Narrow by city or date, then export to JSON, CSV or Excel, or pull records straight into your app through the API.

### Why This Scraper?

- **Two ways to find events.** Search by keyword on one market, or paste search, venue and artist links to read exact listings without building URLs by hand.
- **Sixteen markets.** `us`, `uk`, `au`, `ca`, `ae`, `at`, `ch`, `cz`, `de`, `dk`, `fi`, `it`, `mx`, `nz`, `se` and `za`, each read from its own Ticketmaster site.
- **Rich event records.** Venue address and coordinates, the full artist lineup, every presale window, and status flags for cancelled, postponed, rescheduled, sold out and limited availability shows.
- **Narrow without extra requests.** City and date filters trim the fetched rows down to just what you need.
- **Built for schedules.** Incremental mode returns only new and changed events on recurring runs, and a refused run fails loudly instead of returning an empty dataset.
- **Resume anytime.** Continue an interrupted crawl without paying twice for records you already collected.
- **Nothing lost.** The complete source event object rides along with every record.

### Use Cases

- **Ticket resale and pricing tools:** track lineups, sold out status and onsale dates to plan when to buy or list tickets.
- **Fan alert services:** watch an artist or venue for newly announced shows and presale windows.
- **Event aggregators and listing sites:** build a searchable calendar of concerts, sports and other live events across multiple markets.
- **Tour and venue analytics:** track how often venues host events, and which cities an artist is touring through.
- **Marketing and CRM teams:** match upcoming shows in a city to customer segments for local promotions.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live record.

| Field | Example |
| --- | --- |
| `kind` | `"event"` |
| `recordId` | `"us:SAMPLE0001A"` |
| `eventId` / `discoveryId` | `"SAMPLE0001A"` / `"sampleDiscoveryId1"` |
| `market` | `"us"` (also `"uk"`, `"au"`, `"ca"`, `"ae"`, `"at"`, `"ch"`, `"cz"`, `"de"`, `"dk"`, `"fi"`, `"it"`, `"mx"`, `"nz"`, `"se"`, `"za"`) |
| `title` | `"Sample Arena Rock Night"` |
| `url` | Ticketmaster link to the event page |
| `startDate` / `onsaleDate` | `"2027-06-12T19:30:00Z"` / `"2027-01-05T14:00:00Z"` |
| `spanMultipleDays` / `timeZone` | `false` / `"America/New_York"` |
| `cancelled` / `postponed` / `rescheduled` | `false` / `false` / `false` |
| `soldOut` / `limitedAvailability` | `false` / `false` |
| `ticketingStatus` / `virtual` | `"onsale"` / `false` |
| `venueName` / `venueCity` | `"Sample Arena"` / `"Sampleville"` |
| `venueState` / `venueCountry` / `venueCountryCode` | `"SV"` / `"Sample Country"` / `"SC"` |
| `venueAddress` / `venuePostalCode` | `"1 Sample Way"` / `"00000"` |
| `venueLatitude` / `venueLongitude` | `40.0` / `-75.0` |
| `venueUrl` / `venueImageUrl` | venue page link / venue photo link |
| `artists` | `[{ "name": "Sample Act", "url": "...", "imageUrl": "..." }]` |
| `artistNames` | `["Sample Act"]` |
| `presales` | `[{ "name": "Artist Presale", "startDateTime": "...", "endDateTime": "..." }]` |
| `seatmapImageUrl` | static seatmap image link |
| `categoryId` | `"SampleCategoryId1"` |
| `changeType` / `changedFields` | `"NEW"` / `[]` (incremental mode only) |
| `firstSeenAt` / `lastSeenAt` | timestamps (incremental mode only) |
| `raw` | the complete source object |

Per-event ticket price tiers are not part of any record: Ticketmaster serves them only on its event detail pages, and those pages refuse automated reads on every connection. The listing pages this actor reads carry no price fields either.

### How to Use

1. Pick a **mode**: `search` (keyword lookup on one market) or `url` (paste Ticketmaster links).
2. For search mode, set the **market**, **search query**, and optionally **sort**, **city filter** or a date range. For URL mode, paste one or more **Ticketmaster links**.
3. Set **Max items** and, if needed, **Max pages** to control run size and cost, then click **Start**.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Search by keyword:**

```json
{
  "mode": "search",
  "query": "sample rock festival",
  "market": "us",
  "maxItems": 20
}
```

**Narrow by city and date range:**

```json
{
  "mode": "search",
  "query": "concerts",
  "city": "Chicago",
  "dateFrom": "2027-01-01",
  "dateTo": "2027-03-31",
  "maxItems": 50
}
```

In URL mode, if you leave the links field untouched it now reads one example per link type: US keyword search, a paginated search, a date-sorted search, a venue page, an artist page, and one search each on the UK, Australian and Canadian sites. Max items is split across them, so replace the list with your own links for a real job.

**Paste links (search, venue or artist):**

```json
{
  "mode": "url",
  "urls": [
    "https://www.ticketmaster.com/search?q=sample+festival",
    "https://www.ticketmaster.com/sample-arena-tickets-sampleville/venue/000000"
  ],
  "maxItems": 100
}
```

**Track one search across scheduled runs:**

```json
{
  "mode": "search",
  "query": "sample band tour",
  "incrementalMode": true,
  "stateKey": "sample-band-tour-us",
  "maxItems": 0
}
```

**Supported link shapes (8):** keyword search (`/search?q=...`), a later search page (`&page=2`), a date-sorted search (`&sort=date`), a venue page (`/venue/<id>`), an artist page (`/artist/<id>`), and keyword searches on the UK, Australian and Canadian sites. Any other Ticketmaster link (category pages, `/discover/` pages, event pages) is skipped with a "Link skipped, not a search, venue or artist page" warning, and if no link is usable the run fails with a message saying so.

Event detail links cannot be read by automated clients and are skipped with a warning; paste the venue or artist link instead, or use search mode for the keyword.

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/ticketmaster-event-discovery").call(
    run_input={"mode": "search", "query": "sample rock festival", "market": "us"})
for event in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(event["title"], event["venueCity"], event["startDate"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/ticketmaster-event-discovery').call({
  mode: 'search', query: 'sample rock festival', market: 'us',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### How Max items works across multiple links

In URL mode, Max items is split evenly across the links you paste, calculated once at the start of the run. A link with fewer available events than its share cannot hand its unused budget to another link that has plenty more available. If one link needs a much larger share than the others, give it its own run, or space your links across a few runs instead of one.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset ID and the actor skips every record id already collected there, so you don't pay twice. Ids are matched on the `recordId` field only, so the ID must belong to a run or dataset of this actor. An ID whose items carry no `recordId` seeds nothing (the log shows "0 record id(s) seeded") and every record is collected and billed again.
- **Incremental mode** (`incrementalMode`) is for scheduled runs over the same search or links. Each record is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED` or `EXPIRED` (only after a run that scanned the whole scope end to end, and only with `emitExpired`). `stateKey` names or shares the stored state. With Incremental mode off, output is exactly as before.
- **What counts as a change.** `UPDATED` means any field of the event record changed (title, dates, venue, artists, presale windows, status flags such as sold out, cancelled or postponed, image links), except fields you list in `ignoreFieldsForChanges`. Ticket prices are not part of the record, so price moves are never flagged. Ignored fields stay in the output and are never named in `changedFields`. A dotted name such as `presales.endDateTime` ignores that key inside every presale element only. Saved baselines are re-compared with your current ignore list, so changing it never marks stored events as updated.
- **Availability monitoring.** `changeScope` set to availability only compares just the on-sale date, sold out, limited availability, ticketing status, cancelled, postponed, rescheduled and presale windows; title, venue, artist and image changes never return a row. `compactUpdates` turns `UPDATED` and `EXPIRED` rows into short rows with `priceChanges` and `variantChanges` (old and new values); `NEW` rows stay complete. Switching `changeScope` keeps the same stored baseline: stored events are re-compared with the new scope, so nothing is returned as `NEW` or `UPDATED` just because you changed it. Both are off by default and the row count and billing unit do not change: every returned row is billed as before.
- **Expiry is a listing drop, not a delisting.** `expireAfterMissedScans` (default 1) marks an event `EXPIRED` only after it was missing from that many complete scans in a row. A run that was resumed, hit Max items or Max pages, or started from a link past the first page never expires anything.
- **Do not turn on Resume from run and Incremental mode in the same run.** The actor does not block the combination. Records that Resume skips are never added to the Incremental baseline, so if they were not already in it (for example on the first Incremental run, or when the interrupted run never saved its state), the next Incremental run reports them as `NEW` again and bills them a second time. To pick up an interrupted Incremental schedule, simply run it again with Incremental mode alone.
- **Expired rows in URL mode.** If one pasted link hits an error partway through its listing (for example a page the actor cannot parse), that link is skipped with a "Link ... errored" warning in the log, but the run still counts as a complete scan. With `emitExpired` on, every stored event from that link's unread pages is then returned as `EXPIRED` and billed, even though it is still live, and the next clean run returns the same events as `REAPPEARED`, billed again. The run succeeds and shows no status warning. Search mode is not affected: there the same error stops the run without saving state. Workaround: in URL mode, leave `emitExpired` off, or check the log for "errored" before acting on `EXPIRED` rows.

#### Output views

The dataset has three views: **Records** (the core event columns), **Venue, artists & presales** (location, lineup and presale windows), and **Changes (incremental)** (change type, changed fields, `priceChanges`, `variantChanges`, first and last seen).

### Send results into your apps (MCP connectors)

Results can be piped straight into the apps you already use through Apify MCP connectors. Authorize a connector under Apify, Settings, API & Integrations, then select it in the input. Notion receives a rich page-per-event export; other connectors receive a best-effort write or digest. This is optional: leave the field empty and the run is unchanged.

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mcpConnectors` | array | `empty` | Select one or more authorized MCP connectors. |
| `notionParentPageUrl` | string | `empty` | URL or id of the Notion page under which event pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. |

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` (keyword lookup) or `url` (paste Ticketmaster links). |
| `query` | string | `concerts` | Search mode: a keyword, for example an artist, team, venue or city name. |
| `market` | string | `us` | Search mode: one of `us`, `uk`, `au`, `ca`, `ae`, `at`, `ch`, `cz`, `de`, `dk`, `fi`, `it`, `mx`, `nz`, `se`, `za`. Each market reads its own site. |
| `sort` | string | (none, effectively relevance) | Search mode: `relevance` or `date` result order. |
| `city` | string | (none) | Narrow rows to a venue city, state or country substring. Applied after the fetch. |
| `dateFrom` | string | (none) | Keep events starting on or after this date (`YYYY-MM-DD`). Applied after the fetch. |
| `dateTo` | string | (none) | Keep events starting on or before this date (`YYYY-MM-DD`). Applied after the fetch. |
| `startDate` | string | (none) | Alias of `dateFrom`. |
| `endDate` | string | (none) | Alias of `dateTo`. |
| `urls` | array | eight example links (see below) | URL mode: one or more Ticketmaster search, venue or artist links. Event detail links and other page types are skipped with a warning in the log. |
| `maxItems` | integer | `20` | Maximum event records returned. `0` means no limit. |
| `maxPages` | integer | `0` | Maximum listing pages read per scope. `0` means no cap set by you; a built-in hard limit of 1000 pages per scope always applies. |
| `proxyConfiguration` | object | Apify Proxy (Residential) | Connection settings. Residential is required for reliable results (see Plan Requirement). |
| `resumeFromRunId` | string | (none) | Continue an interrupted crawl: record ids (`recordId`) from this actor's run or dataset id are skipped. |
| `incrementalMode` | boolean | `false` | Track this search across runs: only new or changed events are returned, with `changeType` stamps. Do not combine with Resume from run: the combination is not blocked and can bill skipped records again as `NEW` later (see the tips above). |
| `stateKey` | string | (none) | Custom baseline name for Incremental mode. Leave empty to derive one from the mode, market, query, filters and links; in search mode the pre-filled link list is ignored, and the ignore list and change scope are never part of it. |
| `emitUnchanged` | boolean | `false` | Incremental mode: also return (and bill) unchanged events, with `changeType` `UNCHANGED`. |
| `emitExpired` | boolean | `false` | Incremental mode: also return (and bill) events that vanished since the last run, with `changeType` `EXPIRED`. In URL mode a link that errors partway can produce false `EXPIRED` rows (see the tips above). |
| `changeScope` | string | `all` | Incremental mode: `all` compares the whole record, `priceAndStock` compares only availability fields (on-sale date, status flags, presale windows). Ticket prices are not part of the record. |
| `compactUpdates` | boolean | `false` | Incremental mode: short `UPDATED` and `EXPIRED` rows with `priceChanges` and `variantChanges`. |
| `expireAfterMissedScans` | integer | `1` | Incremental mode with `emitExpired`: expire an event only after it was missing from this many complete scans in a row. |
| `ignoreFieldsForChanges` | array | (none) | Incremental mode: field names (or dotted names such as `presales.endDateTime`) that never make a row `UPDATED`. |
| `mcpConnectors` | array | (none) | Optional: select authorized MCP connectors to receive the results (see the MCP section above). |
| `notionParentPageUrl` | string | (none) | Notion connector only: URL or id of the parent page for event pages. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live record.

```json
{
  "kind": "event",
  "recordId": "us:SAMPLE0001A",
  "eventId": "SAMPLE0001A",
  "discoveryId": "sampleDiscoveryId1",
  "market": "us",
  "url": "https://www.ticketmaster.com/sample-arena-rock-night-sampleville/event/SAMPLE0001A",
  "title": "Sample Arena Rock Night",
  "startDate": "2027-06-12T19:30:00Z",
  "onsaleDate": "2027-01-05T14:00:00Z",
  "spanMultipleDays": false,
  "timeZone": "America/New_York",
  "cancelled": false,
  "postponed": false,
  "rescheduled": false,
  "soldOut": false,
  "limitedAvailability": false,
  "ticketingStatus": "onsale",
  "virtual": false,
  "venueName": "Sample Arena",
  "venueCity": "Sampleville",
  "venueState": "SV",
  "venueCountry": "Sample Country",
  "venueCountryCode": "SC",
  "venueAddress": "1 Sample Way",
  "venuePostalCode": "00000",
  "venueLatitude": 40.0,
  "venueLongitude": -75.0,
  "venueUrl": "https://www.ticketmaster.com/sample-arena-tickets-sampleville/venue/000000",
  "venueImageUrl": "https://example.invalid/sample-venue.jpg",
  "artists": [
    { "name": "Sample Act", "url": "https://www.ticketmaster.com/sample-act-tickets/artist/000000", "imageUrl": "https://example.invalid/sample-act.jpg" }
  ],
  "artistNames": ["Sample Act"],
  "presales": [
    { "name": "Artist Presale", "startDateTime": "2027-01-03T14:00:00Z", "endDateTime": "2027-01-05T02:00:00Z" }
  ],
  "seatmapImageUrl": "https://example.invalid/sample-seatmap.png",
  "categoryId": "SampleCategoryId1",
  "raw": {}
}
```

### Plan Requirement

**A residential proxy is required for reliable results, so a paid Apify plan (or your own residential proxy URLs) is needed.** Ticketmaster answers plain datacenter connections inconsistently: in our measurements some connections were served normally while others got a "Let's Get Your Identity Verified" page instead of listings, so datacenter access is a lottery rather than a working option. The default connection setting therefore uses the residential group. A single refused connection is retried on a fresh one within a 25 second budget per page, and the run stops with a clear failure message when no page can be read at all.

Apify free plans include no residential proxies. On a free plan the actor logs "The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable." and keeps going on a backup connection. When that backup cannot load the requested pages either, the run fails with "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Ticketmaster pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again." If the account's proxy access is refused outright, the failure reads "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required: https://apify.com/pricing. If you entered your own proxy URLs, check that their credentials are valid." When pages fail for other reasons the run fails with "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later." instead of returning an empty dataset.

### FAQ

#### How much does it cost?

You pay per event record returned, plus a small per run start charge. The **Pricing** tab shows the current rates for your plan tier. Use **Max items** to cap the cost of any run.

#### Is it legal to scrape Ticketmaster?

This actor collects only publicly available event listings. You are responsible for how you use it: follow Ticketmaster's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Event and venue facts are generally not protected, but artist and venue photos may be subject to third party rights.

#### Can I get only new or changed events on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. Each run then returns only new, updated, reappeared or expired records for that search or link set, and unchanged ones are not billed unless you turn that on too. Do not add Resume from run to these runs: records it skips are not added to the baseline and can come back later as `NEW` and be billed again. In URL mode with **Emit expired** on, a link that errors partway through can return still-live events as `EXPIRED`, so check the log for "errored" before acting on those rows, or leave **Emit expired** off.

#### Why doesn't this include ticket prices?

Ticketmaster serves per-event ticket price tiers only on its event detail pages, and those pages refuse automated reads on every connection. The listing pages this actor reads carry no price fields either, so price tiers are never part of a record. Paste a venue or artist link instead of an event link to read everything else about the same show.

#### Why did my run fail instead of returning an empty dataset?

If every request is refused, the run stops with a clear message so "no events found" is never confused with "nothing could be read". Run it again in a few minutes. If only some pages or links could be read, you still get what was found, and the run succeeds.

#### Can I use it with AI agents?

Yes. Call it from any Apify integration, or through Apify's API, and read the results from your own agent or app.

### 🔗 More scrapers you might like

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🧩 <a href="https://apify.com/abotapi/bandsintown-concert-event-scraper"><b>Bandsintown Scraper</b></a><br>Scrape Bandsintown concert and festival dates: artist tour calendars, venue profiles...</td><td>🧩 <a href="https://apify.com/abotapi/songkick-concert-calendar-scraper"><b>Songkick Scraper</b></a><br>Scrape Songkick concert and event calendars: upcoming and past dates, venues, cities...</td></tr>
<tr><td>✈️ <a href="https://apify.com/abotapi/pollstar-concert-tour-scraper"><b>Pollstar Scraper</b></a><br>Scrape Pollstar upcoming concerts and tour dates: play date, venue with full address and...</td><td>🧩 <a href="https://apify.com/abotapi/viagogo-events-scraper"><b>Viagogo Scraper</b></a><br>Scrape Viagogo events by artist, production, venue, city, category, or URL. Extract event...</td></tr>
<tr><td>🛒 <a href="https://apify.com/abotapi/seatgeek-events-scraper"><b>SeatGeek Scraper</b></a><br>Scrape SeatGeek events with ticket price ranges (lowest, highest, average, median)...</td><td>🧩 <a href="https://apify.com/abotapi/fever-com-scraper"><b>Fever Scraper</b></a><br>Scrape Fever events by city, category, keyword or URL. Extract from-prices, venues, dates...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/ticketmaster-event-discovery/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `mode` (type: `string`):

Search looks up events by keyword on one market. URL mode reads the Ticketmaster pages you paste.

## `query` (type: `string`):

Search mode: a keyword, for example an artist, team, venue or city name.

## `market` (type: `string`):

Search mode: which Ticketmaster market to read. Each market has its own site and listings.

## `sort` (type: `string`):

Search mode: result order. Relevance is the site default, date orders by start date.

## `city` (type: `string`):

Narrow rows to a venue city, state or country substring, for example Chicago or TX. Applied after the fetch.

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

Keep events starting on or after this date (YYYY-MM-DD). Applied after the fetch.

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

Keep events starting on or before this date (YYYY-MM-DD). Applied after the fetch.

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

Alias of dateFrom (YYYY-MM-DD); dateFrom wins when both are set.

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

Alias of dateTo (YYYY-MM-DD); dateTo wins when both are set.

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

URL mode: one or more Ticketmaster search, venue or artist links. Event detail links cannot be read by automated clients and are skipped with a warning.

## `maxItems` (type: `integer`):

Maximum event records returned. The only default cap: 0 means no limit.

## `maxPages` (type: `integer`):

Maximum listing pages read per scope. 0 means no page cap set by you; the actor still stops at its built-in hard limit of 1000 pages per scope, or earlier at the natural end of the listing.

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

Residential connections are required for reliable reads (datacenter exits are refused at random). Free Apify plans do not include residential proxies; the run then continues on a backup connection. Bring your own proxy URLs if you prefer.

## `resumeFromRunId` (type: `string`):

Continue an interrupted crawl: record ids from this run or dataset id are skipped. See Incremental mode below.

## `incrementalMode` (type: `boolean`):

Track this search across runs: only new or changed events are returned, with changeType stamps. An event is UPDATED when any field of its record changes (title, dates, venue, artists, presale windows, status flags such as sold out, cancelled or postponed, image links), except fields you list under Ignore fields; the raw upstream object is never compared. Ticket prices are not part of the record. Cannot be combined with Resume from run when a baseline exists.

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

Custom baseline name for Incremental mode. Leave empty to derive one from the mode, market, query, filters and links; in search mode the pre-filled link list is ignored, and the ignore list and change scope are never part of it.

## `emitUnchanged` (type: `boolean`):

Incremental mode: also return unchanged events, with changeType UNCHANGED. Returned rows are billed as usual.

## `emitExpired` (type: `boolean`):

Incremental mode: also return events that vanished since the last run, with changeType EXPIRED. Only a complete scan can expire events: runs that were resumed, hit Max items or Max pages, or started from a link past the first page never do. A vanished listing may be a delisting or just a listing change. Returned rows are billed as usual.

## `changeScope` (type: `string`):

All fields (default): any change to the event record returns an UPDATED row. Availability only: only on-sale date, sold out, limited availability, ticketing status, cancelled, postponed, rescheduled and presale window changes return an UPDATED row; changes to title, venue, artists or images never do. Ticket prices are not part of the record.

## `compactUpdates` (type: `boolean`):

Off by default. When on, UPDATED and EXPIRED rows are short: record id, event id, url, title, start date and current availability flags, plus priceChanges and variantChanges showing the old and new value of each moved availability field and presale window. NEW rows always carry the complete record.

## `expireAfterMissedScans` (type: `integer`):

Only used with Emit expired. An event is marked EXPIRED only after it has been missing from this many complete scans in a row (default 1). A returning event resets the count. A vanished listing may be a delisting or a listing change; the status flags report sold out or cancelled events.

## `ignoreFieldsForChanges` (type: `array`):

Optional. Field names to exclude from UPDATED change detection, for example venueImageUrl or seatmapImageUrl if an image link keeps rotating. Use a dotted name such as presales.endDateTime to ignore a key inside every presale or artist element while the rest of the element is still compared. Ignored fields stay in the output. Changing this list does not mark saved events as updated.

## `mcpConnectors` (type: `array`):

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write or digest. Leave empty to skip; never changes the dataset output.

## `notionParentPageUrl` (type: `string`):

URL or id of the Notion page under which event pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "query": "concerts",
  "market": "us",
  "urls": [
    "https://www.ticketmaster.com/search?q=concerts",
    "https://www.ticketmaster.com/search?q=concerts&page=2",
    "https://www.ticketmaster.com/search?q=concerts&sort=date",
    "https://www.ticketmaster.com/hertz-arena-tickets-estero/venue/107143",
    "https://www.ticketmaster.com/barry-manilow-tickets/artist/735585",
    "https://www.ticketmaster.co.uk/search?q=coldplay",
    "https://www.ticketmaster.com.au/search?q=concerts",
    "https://www.ticketmaster.ca/search?q=hockey"
  ],
  "maxItems": 20,
  "maxPages": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "changeScope": "all",
  "compactUpdates": false,
  "expireAfterMissedScans": 1,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `detail` (type: `string`):

No description

## `changes` (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 = {
    "mode": "search",
    "query": "concerts",
    "market": "us",
    "urls": [
        "https://www.ticketmaster.com/search?q=concerts",
        "https://www.ticketmaster.com/search?q=concerts&page=2",
        "https://www.ticketmaster.com/search?q=concerts&sort=date",
        "https://www.ticketmaster.com/hertz-arena-tickets-estero/venue/107143",
        "https://www.ticketmaster.com/barry-manilow-tickets/artist/735585",
        "https://www.ticketmaster.co.uk/search?q=coldplay",
        "https://www.ticketmaster.com.au/search?q=concerts",
        "https://www.ticketmaster.ca/search?q=hockey"
    ],
    "maxItems": 20,
    "maxPages": 0,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "compactUpdates": false,
    "expireAfterMissedScans": 1,
    "ignoreFieldsForChanges": [],
    "maxNotifyListings": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/ticketmaster-event-discovery").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 = {
    "mode": "search",
    "query": "concerts",
    "market": "us",
    "urls": [
        "https://www.ticketmaster.com/search?q=concerts",
        "https://www.ticketmaster.com/search?q=concerts&page=2",
        "https://www.ticketmaster.com/search?q=concerts&sort=date",
        "https://www.ticketmaster.com/hertz-arena-tickets-estero/venue/107143",
        "https://www.ticketmaster.com/barry-manilow-tickets/artist/735585",
        "https://www.ticketmaster.co.uk/search?q=coldplay",
        "https://www.ticketmaster.com.au/search?q=concerts",
        "https://www.ticketmaster.ca/search?q=hockey",
    ],
    "maxItems": 20,
    "maxPages": 0,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "compactUpdates": False,
    "expireAfterMissedScans": 1,
    "ignoreFieldsForChanges": [],
    "maxNotifyListings": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/ticketmaster-event-discovery").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 '{
  "mode": "search",
  "query": "concerts",
  "market": "us",
  "urls": [
    "https://www.ticketmaster.com/search?q=concerts",
    "https://www.ticketmaster.com/search?q=concerts&page=2",
    "https://www.ticketmaster.com/search?q=concerts&sort=date",
    "https://www.ticketmaster.com/hertz-arena-tickets-estero/venue/107143",
    "https://www.ticketmaster.com/barry-manilow-tickets/artist/735585",
    "https://www.ticketmaster.co.uk/search?q=coldplay",
    "https://www.ticketmaster.com.au/search?q=concerts",
    "https://www.ticketmaster.ca/search?q=hockey"
  ],
  "maxItems": 20,
  "maxPages": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "compactUpdates": false,
  "expireAfterMissedScans": 1,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}' |
apify call abotapi/ticketmaster-event-discovery --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/ticketmaster-event-discovery"
        }
    }
}
```

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/ZbVMBdvMV6iMnyzyx/builds/oreP2Jgr24QwxubfJ/openapi.json
