# Fever Scraper - Events, Prices, Venues & Dates (`abotapi/fever-com-scraper`) Actor

Scrape Fever events by city, category, keyword or URL. Extract from-prices, venues, dates and ratings, with optional enrichment for event descriptions, venue addresses and available sessions.

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

## Pricing

from $1.50 / 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

## Fever Event Scraper

Browse [Fever](https://feverup.com) events and experiences by city, category or keyword, or paste Fever URLs. Every row carries the event identity, the from-price with its currency, the venue, the date range and the rating pair from the listing page itself. The per-record extras (description, venue address with coordinates, categories, session dates and ticket availability) are one toggle away.

### Modes

- **Browse by city**: walk one or more city catalogues (`new-york`, `london`, `madrid`, `paris`, `milan`, `sao-paulo`, and more), optionally narrowed to one category (`candlelight`, `music-events`, `exhibitions`, `food`) and one keyword. City pages render their catalogue inline in one read; category pages serve a capped window per grid (48 plans) with the rest behind the site's Load more control, and the run says so ("Partial results: ...") instead of pretending the window is the whole catalogue. Max items is the single cap on a run.
- **Paste Fever URLs**: event pages (`https://feverup.com/m/653922`) return that single event in full; city pages (`https://feverup.com/en/new-york`) and category pages (`https://feverup.com/en/london/candlelight`) are read like a search, the pasted URL deciding its own scope.

### Inputs

- `cities`: city slugs to browse (search mode). Defaults to New York.
- `locale`: site language prefix (`en`, `es`, `fr`, `it`, `pt`, `de`). Defaults to `en`.
- `category`: optional category slug applied to every city walk (search mode).
- `query`: optional keyword kept against the event title and categories (search mode).
- `urls`: Fever URLs to process (URL mode).
- `minPrice`, `maxPrice`: keep only events whose from-price honours the bound, in the row's own currency. Every walk in both modes; a pasted event URL is the exception and returns that single event in full.
- `fetchDetails`: fetch each event's page for the description, venue address with coordinates, categories, session dates and ticket availability. Charged once per record. Leave off for a fast crawl.
- `maxItems`: the single cap on a run (default 20, 0 for unlimited).
- `resumeFromRunId`, `incrementalMode`, `stateKey`, `emitUnchanged`, `emitExpired`: resume one interrupted run, or monitor the same search on a schedule and receive only NEW, UPDATED, REAPPEARED (and optionally EXPIRED) rows.
- `proxy`: leave the default pool unless a run reports it could not read results.

### Output

Each dataset row is one event:

| Field | Source |
|---|---|
| `recordId`, `eventId`, `url`, `title` | listing card |
| `citySlug`, `locale`, `category` | walk scope |
| `priceFrom`, `priceText`, `originalPrice`, `onSale`, `discountPercent`, `currency`, `priceType` | listing card |
| `startDate`, `endDate`, `sessionDate`, `venueName`, `rating`, `ratingCount`, `isNew`, `imageUrl` | listing card |
| `description`, `venueAddress`, `latitude`, `longitude`, `categories`, `firstSessionDate`, `lastSessionDate`, `ticketsAvailable`, `sessionsText` | event page (Fetch event details) |
| `changeType`, `changedFields`, `firstSeenAt`, `lastSeenAt` | incremental mode |

Sample row (illustrative values, not a live listing):

```json
{
  "recordId": "000000",
  "title": "Sample Candlelight Concert",
  "citySlug": "new-york",
  "priceFrom": 25.0,
  "currency": "USD",
  "venueName": "Sample Hall",
  "startDate": "2026-10-01T19:00:00-04:00",
  "url": "https://feverup.com/m/000000"
}
```

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

Results can be piped into the apps you already use through Model Context
Protocol (MCP) connectors, as an optional side channel. This never changes
the dataset output.

- `mcpConnectors`: authorize a connector under Apify, Settings, API &
  Integrations, then select it here. Notion receives a page per record;
  other connectors receive a best-effort write or digest. Each connector
  gets a condensed summary per record; the complete record always stays in
  the dataset.
- `notionParentPageUrl`: the Notion page under which record pages are
  created. Required for the Notion connector, ignored by the others.
- `maxNotifyListings`: cap on records written to each connector per run.

### Compute

This actor reads pages over plain HTTP; 512 MB of memory is the default and
is plenty. A minimal run finishes in well under a minute.

### Notes and limits

- City and category pages are complete single reads; a run stops at Max
  items, never at a page bound.
- Prices are quoted in each event's own currency (USD in New York, GBP in
  London, and so on); the price bounds compare against the row currency.
- Rating counts drift as reviews accumulate, so they never mark a row
  UPDATED on their own in incremental mode; price moves, venue changes and
  date changes do.

# Actor input Schema

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

How to start the scrape. 'search' walks city catalogues. 'url' processes the Fever URLs you paste: an event URL is fetched as a single event, and a city or category URL is read like a search, its own city and category deciding the scope. The filters below apply to every walk in both modes; a pasted event URL is the one exception and returns that single event in full.

## `cities` (type: `array`):

City slugs to browse, for example 'new-york', 'london', 'madrid', 'paris', 'milan', 'sao-paulo'. Each city is scraped independently. Search mode only: in URL mode the scope is read out of each pasted URL instead. Defaults to New York when empty.

## `locale` (type: `string`):

The site language prefix for city pages: en, es, fr, it, pt or de. Unknown values fall back to en. Search mode only: in URL mode the pasted URL carries its own language.

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

Narrow every city walk to one category slug, for example 'candlelight', 'music-events', 'exhibitions' or 'food'. Leave empty to browse the whole city catalogue. Search mode only: in URL mode a pasted category URL decides its own scope.

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

Only keep events whose title or categories contain this text, for example 'candlelight' or 'jazz'. The site has no keyword parameter, so it is applied to the rows this run reads. Search mode only: in URL mode the pasted URL decides its own scope.

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

Paste event URLs (https://feverup.com/m/653922), city URLs (https://feverup.com/en/new-york) or category URLs (https://feverup.com/en/london/candlelight). A pasted URL decides its own scope. The price bounds below narrow what the walks read; a pasted event URL is the exception and returns that single event in full.

## `minPrice` (type: `integer`):

Only keep events whose from-price is at least this amount, in the row's own currency. The site has no parameter for this, so it is applied to the rows this run reads. Applies to every walk in both modes; a pasted event URL is the exception and returns that single event in full.

## `maxPrice` (type: `integer`):

Only keep events whose from-price is at most this amount, in the row's own currency. The site has no parameter for this, so it is applied to the rows this run reads. Applies to every walk in both modes; a pasted event URL is the exception and returns that single event in full.

## `fetchDetails` (type: `boolean`):

Fetch each event's page for the description, the venue address with coordinates, the categories, the session dates and the ticket availability. Slower, and charged once per record. Leave off for a fast crawl: identity, from-price, venue, dates and rating are included either way.

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

The single cap on this run: stop after collecting this many records across all cities and URLs. A listing page serves what the site renders in one read (city pages render the catalogue; category pages serve a capped window per grid with the rest behind the site's Load more control), so there is no page cap. Set 0 for unlimited.

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

Paste a previous run ID or dataset ID to continue a large crawl without returning or charging for records already collected there. Use this after an interrupted or capped run. For recurring monitoring of the same search, use Incremental mode below instead.

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

Turn this on for daily or weekly recurring monitoring of the same search, for example a price watch. The first run returns everything matching as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED records. Price moves and new dates ARE reported as UPDATED: on an events catalogue they are the signal, not noise. Turn on Emit unchanged or Emit expired only when you also want those rows returned (and billed). State is kept separately per city, URL and filter setup; use State key to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.

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

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently configured runs. Leave empty to let the actor derive a key automatically from the cities, URLs and filters, so two different searches never mix state.

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

Off by default. Turn on to also return records that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you specifically want a full snapshot every run.

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

Off by default. Turn on to also return records that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search: not when Max items capped it, not when Resume was used, not when the run was refused, and not when a category page served a capped window of its catalogue (the run says Partial results instead). This returns, and bills, extra synthetic rows, so leave it off unless you need expiry tracking.

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

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API and Integrations, then select it here. Notion gets a page per record; other connectors get a best-effort write or digest. Each connector receives a condensed summary per record, not the full record; the complete record always stays in the dataset. Leave empty to skip; this never changes the dataset output. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

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

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

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

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

## `proxy` (type: `object`):

Leave the default for the cheapest run. The site serves ordinary shared connections, so the default pool is enough. Change it only if a run reports that it could not read any results.

## Actor input object example

```json
{
  "mode": "search",
  "cities": [
    "new-york"
  ],
  "locale": "en",
  "urls": [
    "https://feverup.com/en/new-york/candlelight"
  ],
  "fetchDetails": false,
  "maxItems": 20,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "maxNotifyListings": 50,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `overview` (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",
    "cities": [
        "new-york"
    ],
    "locale": "en",
    "urls": [
        "https://feverup.com/en/new-york/candlelight"
    ],
    "fetchDetails": false,
    "maxItems": 20,
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/fever-com-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 = {
    "mode": "search",
    "cities": ["new-york"],
    "locale": "en",
    "urls": ["https://feverup.com/en/new-york/candlelight"],
    "fetchDetails": False,
    "maxItems": 20,
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/fever-com-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 '{
  "mode": "search",
  "cities": [
    "new-york"
  ],
  "locale": "en",
  "urls": [
    "https://feverup.com/en/new-york/candlelight"
  ],
  "fetchDetails": false,
  "maxItems": 20,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call abotapi/fever-com-scraper --silent --output-dataset

```

## MCP server setup

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