# Onoffmix Events (`stone_jadex/onoffmix-events`) Actor

Public Onoffmix (Korea) events: list plus optional detail pages with times, venue/online, tickets and capacity.

- **URL**: https://apify.com/stone_jadex/onoffmix-events.md
- **Developed by:** [Stone Jade](https://apify.com/stone_jadex) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

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

## Onoffmix Events Scraper — Korean event listings with tickets, prices and seats

Get structured event data from Onoffmix, Korea's event platform: every event with its start/end times, venue or online flag, ticket groups with prices and remaining seats, and total capacity — ready for calendars, aggregators and market research, without building or babysitting a scraper.

### Who it is for

- Event aggregators and calendar apps building a Korea events feed
- Community and meetup platforms tracking conferences, classes and contests
- Market researchers following ticket pricing, capacity and sell-through by category or region
- Anyone who needs Korean event data in clean JSON/CSV instead of copy-pasting pages

Why this one: ticket groups come with per-group price and seats (not just "free/paid"), times are ISO 8601 with the +09:00 offset, and filters run before detail pages are fetched, so you only pay for events that match.

### Real sample records

From a verified run (October 2026):

| Event | Category | When | Where | Tickets |
|---|---|---|---|---|
| 2026 소상공인 대회 | 공모전/대회/지원사업 | 2026-10-23 00:00 +09:00 | 부산 해운대구 APEC로 30 | Free (무료) |
| K-Fundraising 아카데미 | 교육/워크숍 | 2026-08-13 13:30 +09:00 | 서울 마포구 잔다리로7안길 6 | 7 groups, 60,000–380,000 KRW, seats per group |

### Example output

One real record, exactly as delivered:

```json
{
  "eventId": "349595",
  "url": "https://onoffmix.com/event/349595",
  "title": "2026 소상공인 대회",
  "status": "ended",
  "category": "공모전/대회/지원사업",
  "tags": ["#소상공인", "#소상공인대회"],
  "isFree": true,
  "feeText": "무료",
  "dateText": "2026.10.23 (금) 0:00 ~ 2026.10.24 (토) 23:59",
  "region": "부산광역시 해운대구",
  "coverImageUrl": "https://static.onoffmix.com/afv2/attach/2026/10/10/v390e0833a6d01b1d5dd7ffeedfb2484a2.png",
  "startAt": "2026-10-23T00:00:00+09:00",
  "endAt": "2026-10-24T23:59:59+09:00",
  "isOnline": false,
  "venue": "부산 해운대구 APEC로 30",
  "address": "부산 해운대구 APEC로 30 제2전시장 4홀",
  "tickets": [
    { "name": null, "price": 0, "currency": "KRW", "availability": "InStock", "selectionType": null, "seatsMax": null, "seatsAvailable": null }
  ],
  "capacity": null,
  "publishedAt": "2026-10-01T00:00:00+09:00",
  "timezone": "Asia/Seoul",
  "organizerName": "소상공인연합회",
  "detailFetched": true,
  "description": null
}
```

#### All fields

| Field | Meaning |
|---|---|
| eventId / url | Event ID and canonical page URL |
| title / status / category / tags | As published on the page |
| isFree / feeText | Free flag and the page's own fee text |
| dateText / region | List-page date and region text |
| startAt / endAt | ISO 8601 with +09:00 offset |
| coverImageUrl | Cover image |
| isOnline / venue / address | Online flag and venue/address as published |
| tickets\[] | Every published ticket/session group: `name`, `price` (KRW, 0 = free), `currency`, `availability`, `selectionType`, `seatsMax`, `seatsAvailable` |
| capacity | Sum of the ticket groups' seatsMax when published |
| publishedAt | Ticket sales start |
| timezone | Always `Asia/Seoul` |
| organizerName | The public organizer name published on the event page (no organizer contact details, no attendee data) |
| detailFetched | Whether the detail page was read |
| description | Plain-text description when `includeDescription` is on, otherwise null |

### Price

**$0.0015 per event — $1.50 per 1,000 events.** No run-start fee. Filters are applied before detail fetching, so filtered-out events cost nothing.

#### Failed detail rows are still charged

Billing uses the pay-per-event `apify-default-dataset-item` event, which charges every row pushed to the dataset at the full per-event price. Rows whose detail fetch failed (`detailFetched: false`) are still pushed, so they are charged as a dataset item. `OUTPUT.skippedDetails` lists each skipped detail URL and reason, and `OUTPUT.skippedCount` counts them. Duplicate event IDs are dropped before push, so they are not charged.

### How to start

1. Click **Start** (or call the Actor via API) — no setup needed.
2. For a first test, try the prefilled example input (5 events with details).
3. Download results as JSON, CSV or Excel, or read them from the dataset API.

Example input:

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

Parameters: `maxItems` (default 50), `maxPages` (default 200), `fetchDetails` (default true), `includeDescription` (default false), `proxyConfiguration` (proxy settings; direct connection by default). List-stage filters, applied before any detail fetch: `keyword`, `category`, `dateFrom`/`dateTo`, `regionContains`, `minEventId`. Collection continues until `maxItems` matching events are found, `maxPages` list pages are read, the run is within 20 seconds of the platform timeout, or pages run out. Each list page is saved as soon as it is parsed. The OUTPUT record reports `truncated` and `stopReason` when the list is cut short. A list-page error stops paging, keeps events already pushed, and stores the message on `error` (the run fails only when nothing was pushed). `skippedDetails` lists every detail URL that failed.

### Limits and compliance

- Only publicly visible event pages are read: no login, no captcha solving, no attendee data.
- Note: Onoffmix's robots.txt disallows all crawling (`Disallow: /`). This is recorded in OUTPUT as `robotsDisallowedHits`; requests run at a conservative ~1 request/second honouring crawl-delay. Whether scraping is permitted depends on the site's terms and your jurisdiction — you are responsible for how you use the data.
- Times and ticket data reflect the page at scrape time; sold-out or changed events update on the next run.

# Actor input Schema

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

Maximum unique events to collect.

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

Stop after this many list pages, even if maxItems is not reached.

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

Fetch each public event page for start/end times, venue, tickets and capacity.

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

Include the plain-text event description from the detail page.

## `keyword` (type: `string`):

Only keep events whose title contains this text (case-insensitive). Empty keeps all.

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

Only keep events whose category text contains this value, e.g. 강연/세미나. Empty keeps all.

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

Direct by default. Residential proxy use should stay within 5 MB per run.

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

Only events starting on or after this date.

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

Only events starting on or before this date.

## `regionContains` (type: `string`):

Only events whose region or address contains this text.

## `minEventId` (type: `integer`):

Incremental mode: only collect events with an ID greater than this value.

## Actor input object example

```json
{
  "maxItems": 50,
  "maxPages": 200,
  "fetchDetails": true,
  "includeDescription": false,
  "keyword": "",
  "category": "",
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "dateFrom": "",
  "dateTo": "",
  "regionContains": "",
  "minEventId": 0
}
```

# Actor output Schema

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

Scraped items in the default dataset.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("stone_jadex/onoffmix-events").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("stone_jadex/onoffmix-events").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 '{}' |
apify call stone_jadex/onoffmix-events --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,stone_jadex/onoffmix-events"
        }
    }
}
```

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/xdFs95RUMNgkDnXjd/builds/B6Zf8E8waGmAVCU1D/openapi.json
