# Tresor Berlin Events Scraper (`axiomworks/tresor-berlin-events-scraper`) Actor

Scrape upcoming Tresor Berlin techno club events: date, title, floor-by-floor DJ lineups with set times, description, ticket link and image. Filter by date range or event URL, up to 100 events per run. If no event matches the dates, the earliest upcoming events are returned.

- **URL**: https://apify.com/axiomworks/tresor-berlin-events-scraper.md
- **Developed by:** [Axiom Works](https://apify.com/axiomworks) (community)
- **Categories:** Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.79 / 1,000 results

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

## Tresor Berlin Events Scraper

### What does Tresor Berlin Events Scraper do?

Tresor Berlin Events Scraper collects public event information from the Tresor Berlin website and saves one clean record per event in an Apify dataset. It reads the site's public event sitemap, opens each event page and extracts the title, the date, the lineup for every floor with the listed set times, the description, the ticket link and the event image.

Records are sorted by event date, earliest first. You can restrict the date range, cap the number of events, or pass specific event page URLs. No login is needed, because the Actor only reads pages that anyone can open in a browser.

Typical uses:

- Building a calendar or listing of upcoming Tresor nights.
- Tracking which artists are booked on which floor.
- Feeding event data into a newsletter, a spreadsheet or a booking database.
- Monitoring new announcements by running the Actor on a schedule.

The Actor is an independent tool. It is not affiliated with, endorsed by or connected to Tresor Berlin.

### What data can you get?

Every record contains the fields below. Fields that a page does not provide are returned as `null`, and `floors` is an empty list when no lineup is published.

| Field | Type | Description |
|---|---|---|
| `id` | string | Stable event identifier built from the URL slug, for example `tresor-20260930-tresor-new-faces-hosted-by-tresor`. |
| `sourceUrl` | string | The event page the record was read from. |
| `url` | string | Canonical event URL. |
| `title` | string | Event title. |
| `date` | string | Event date in `YYYY-MM-DD` format, taken from the event URL. |
| `startTime` | string or null | Earliest evening set time, for example `23:00`. `null` when the page lists no set times. |
| `floors` | array | Floors with their lineups. Each floor has `floor` (name) and `lineup`, a list of `name`, `time` and `link` (artist link or `null`). |
| `description` | string or null | Event information and ticket policy text. Shortened to a preview of about 200 characters when `includeDescription` is false. |
| `ticketUrl` | string or null | External ticket listing URL. |
| `image` | string or null | Event image URL. |
| `eventType` | string or null | Event series classification. Filled only when the `enrich` input is true and the AI step succeeds, otherwise `null`. |

The Actor does not download ticket pages or artist pages. It returns the links to them, not their content.

### How to use Tresor Berlin Events Scraper

1. Open the Actor on Apify and go to the **Input** tab.
2. Set **Maximum events** to the number of events you want. The value must be between 1 and 100.
3. Optionally set **From date** and **To date** to limit the range, or paste event page URLs into **Specific event URLs**.
4. Click **Start**. A run with five events takes well under a minute.
5. Open the **Output** tab to view, filter or download the dataset as JSON, CSV, Excel or HTML.

#### Behaviour worth knowing

- The website only publishes upcoming events. If the date range you choose matches no listed event, the Actor returns an empty dataset, logs a warning with the first and last date the site lists, and charges nothing.
- If you provide event URLs and none of them is still published, the Actor also returns no records. URLs that are no longer published are skipped when at least one other URL works.
- Set times are normalised to `HH:MM-HH:MM` or `HH:MM-END`.
- When `fromDate` is empty, it defaults to today's date in Berlin.
- `fromDate` and `toDate` do not filter URLs you pass in `startUrls`. Those pages are scraped as given.
- Invalid input stops the run at once with a clear error message. Examples are a URL that is not a Tresor event page, an impossible calendar date, a `toDate` earlier than `fromDate`, a `maxItems` outside 1 to 100, or a value of the wrong type.

### Input

| Field | Type | Description |
|---|---|---|
| `maxItems` | integer | Maximum number of events to return, 1 to 100. Default 50. |
| `fromDate` | string | Earliest event date, `YYYY-MM-DD`. Defaults to today in Berlin. |
| `toDate` | string | Latest event date, `YYYY-MM-DD`. Must not be earlier than `fromDate`. |
| `includeDescription` | boolean | Return the full description and ticket policy text. When false, only a preview of about 200 characters. Default true. |
| `enrich` | boolean | Add an AI-generated event series label in `eventType`. Costs extra per labelled result. Default false. |
| `startUrls` | array of strings | Optional Tresor event page URLs in the form `https://tresorberlin.com/event/YYYYMMDD-slug/`. When given, only these pages are scraped. |

Example input:

```json
{
  "maxItems": 5,
  "fromDate": "2026-10-01",
  "toDate": "2026-12-31",
  "includeDescription": true
}
```

Example input with specific pages:

```json
{
  "startUrls": [
    "https://tresorberlin.com/event/20260930-tresor-new-faces-hosted-by-tresor/"
  ]
}
```

### Output

The dataset holds one item per event. The example below comes from a local run of the Actor (the description is shortened here for readability):

```json
{
  "id": "tresor-20260930-tresor-new-faces-hosted-by-tresor",
  "sourceUrl": "https://tresorberlin.com/event/20260930-tresor-new-faces-hosted-by-tresor/",
  "url": "https://tresorberlin.com/event/20260930-tresor-new-faces-hosted-by-tresor/",
  "title": "Tresor New Faces hosted by Tresor",
  "date": "2026-09-30",
  "startTime": "23:00",
  "floors": [
    {
      "floor": "Tresor",
      "lineup": [
        { "name": "Auryn", "time": "23:00-02:00", "link": "https://soundcloud.com/auryn303" },
        { "name": "INDACID LIVE", "time": "02:00-03:00", "link": "https://on.soundcloud.com/7ZGObYR960dE9jRlLS" },
        { "name": "MIHEMI", "time": "03:00-05:00", "link": "https://on.soundcloud.com/9eQwsyeAvkXq3sWdou" },
        { "name": "PAREKA", "time": "05:00-END", "link": "http://www.soundcloud.com/pareka" }
      ]
    },
    {
      "floor": "Aurora Bar",
      "lineup": [
        { "name": "Miss Italia", "time": "23:00-05:00", "link": null }
      ]
    }
  ],
  "description": "In the week where we celebrate 35 years of Tresor Records, the club takes this opportunity to look at the future of techno with an in-house New Faces curation. ...",
  "ticketUrl": "https://ra.co/events/2499879",
  "image": "https://tresorberlin.com/wp-content/uploads/2026/07/10-1521x1536.jpg",
  "eventType": null
}
```

Set times are normalised to `HH:MM-HH:MM`, and a value such as `05:00-END` is possible when the page shows an open end. In the run above `eventType` is `null` because `enrich` was off.

You can download the dataset in JSON, CSV, Excel, XML or HTML format from the Output tab or through the API.

### How much does it cost?

The Actor uses pay-per-event pricing, charged per result, meaning per event record saved to the dataset. The current price is shown on the Pricing tab of the Actor page, so check it there before you run large jobs. Because a run is capped at 100 events and the Actor reads a small number of pages, the cost of a single run stays small. Use `maxItems` to control how many results you pay for. AI enrichment is off by default. If you switch on `enrich`, each event that receives a label is charged extra, as listed on the Pricing tab.

### Use with the API

You can start the Actor from code and read the results with the Apify API clients. Replace `YOUR_API_TOKEN` with your own Apify API token.

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("axiomworks/tresor-berlin-events-scraper").call(
    run_input={"maxItems": 5}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["date"], item["title"])
```

**JavaScript**

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

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('axiomworks/tresor-berlin-events-scraper').call({ maxItems: 5 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((e) => `${e.date} ${e.title}`));
```

**cURL**

```bash
curl -X POST "https://api.apify.com/v2/acts/axiomworks~tresor-berlin-events-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"maxItems": 5}'
```

You can also connect the Actor to Apify schedules, webhooks and integrations such as Make, Zapier or Google Sheets, to refresh your event list automatically.

### Use with AI agents (MCP)

You can call this Actor from any MCP-compatible AI assistant through the Apify MCP server. Add the Actor to the server's tool list with this configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=axiomworks/tresor-berlin-events-scraper"
    }
  }
}
```

Example prompts:

- "List the next five events at Tresor Berlin with the artists on each floor."
- "Which events at Tresor are scheduled between 1 October and 31 December 2026, and where can I buy tickets?"
- "Get the lineup and start time for https://tresorberlin.com/event/20260930-tresor-new-faces-hosted-by-tresor/."

### FAQ

**How many events can I get?**
Up to 100 per run. The number of events available depends on what the website has published, which is a limited window of upcoming events. A recent local run found 15 event pages in the sitemap.

**Can I get past events?**
No. The website publishes upcoming events only. A date range in the past matches nothing, so the Actor returns an empty dataset.

**Why is `startTime` null?**
The event page lists no set times. Records are still returned with the other fields.

**Why is `eventType` null?**
AI enrichment is optional and off by default. When you set `enrich` to true, the Actor classifies the event series into `eventType`. It sends the event title and a short part of the description to TypeSafe, a third-party AI processor. If enrichment is off or fails, the record is still returned with `eventType: null`. The same processor may also be asked to pick a title or artist name from text already on the page when the usual page structure is missing.

**Why did I get no events?**
No listed event falls inside your date range, or none of your `startUrls` is still published. The Actor then returns an empty dataset and logs the first and last date the site lists.

**How fast does it run?**
The Actor requests pages one by one at a modest rate, with retries and backoff on errors, to be polite to the website. Small runs finish in under a minute.

**The run failed with an input error. What now?**
Read the error message in the log. It names the field and the reason, for example a URL that is not a Tresor event page.

### Is it legal to scrape Tresor Berlin?

The Actor reads only public pages that open without a login, and it does not bypass any access control. The data is event information such as titles, dates, lineups and links. Laws and website terms differ by country and by use, so you are responsible for checking that your use of the data complies with applicable law, including copyright and database rights, and with the site's terms. Images and text remain the property of their owners. This is not legal advice.

### Feedback

If a field is missing, a page layout changes or you need another field, open an issue from the Actor's Issues tab on Apify. Include the input you used and the event URL involved so the problem can be reproduced.

# Actor input Schema

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

Maximum number of event records to return, from 1 to 100 (default 50).

## `fromDate` (type: `string`):

Earliest event date, YYYY-MM-DD. Defaults to today in Berlin. Does not filter event URLs given in startUrls. If no listed event falls in the range, no records are returned.

## `toDate` (type: `string`):

Latest event date, YYYY-MM-DD. Must not be earlier than fromDate.

## `includeDescription` (type: `boolean`):

Return the full event information and ticket policy text. When false, only a preview of about 200 characters is returned.

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

Optional Tresor event page URLs (https://tresorberlin.com/event/YYYYMMDD-slug/). When given, only these pages are scraped. Other URLs make the run fail. Events that are no longer published are skipped; if none is published, no records are returned.

## `enrich` (type: `boolean`):

Add an AI-generated event series label (eventType) to each event. Costs extra per labelled result, billed as an additional event. Default false.

## Actor input object example

```json
{
  "maxItems": 5,
  "includeDescription": true,
  "enrich": false
}
```

# Actor output Schema

## `dataset` (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 = {
    "maxItems": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("axiomworks/tresor-berlin-events-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "maxItems": 5 }

# Run the Actor and wait for it to finish
run = client.actor("axiomworks/tresor-berlin-events-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 '{
  "maxItems": 5
}' |
apify call axiomworks/tresor-berlin-events-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,axiomworks/tresor-berlin-events-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/UeDkYBfW5cckNX9fW/builds/hHV2kAh4qtF6LYSGP/openapi.json
