# Asunnot Oikotie.fi Real Estate Scraper (`datascrapers/asunnot-oikotie-fi`) Actor

Scrape Finnish property listings from asunnot.oikotie.fi by location, filters, or search/listing URLs. Optionally enrich each result with full listing details.

- **URL**: https://apify.com/datascrapers/asunnot-oikotie-fi.md
- **Developed by:** [Data Scrapers](https://apify.com/datascrapers) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 dataset items

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

**Asunnot Oikotie.fi Real Estate Scraper** creates a structured dataset of Finnish property listings collected from asunnot.oikotie.fi. Each dataset item is one listing card and can include the listing URL, address, city, district, price in euros, living area, rooms, building type, construction year, and image. Query by location, listing type, or a search or listing URL, optionally enrich each card from the listing page, limit results with `maxItems`, and retrieve records through the Apify Dataset API or export them as JSON, CSV, Excel, XML, or another supported format.

[![Asunnot Oikotie.fi Real Estate Scraper — input to structured data](https://raw.githubusercontent.com/faizanalii/apify-actor-assets/main/asunnot-oikotie-fi/asunnot-oikotie-fi-value-demo.gif)](https://apify.com/datascrapers/asunnot-oikotie-fi)

### Dataset at a glance

| Property | Value |
|---|---|
| Source | asunnot.oikotie.fi |
| Record unit | One listing card, optionally enriched from the listing page |
| Input methods | `startUrls`, or `searchQueries` plus filters |
| Main identifiers | `cardId` and `id` |
| Delivery | Apify Dataset and API |
| Export formats | JSON, CSV, Excel, XML, and other Apify dataset exports |
| Update model | Fresh records per Actor run |
| Pricing | $0.001 per listing card. $0.002 extra per listing when detail enrichment succeeds. |

### Coverage and available records

Start URLs take priority. A start URL may be a search results URL, such as `https://asunnot.oikotie.fi/myytavat-asunnot?cardType=100&locations[]=helsinki`, or a single listing URL. Query filters already on a search URL are kept. `searchQueries` is used when `startUrls` is empty. An empty location list with no start URL searches nationwide using the filters.

Supported listing types: homes for sale, homes for rent, holiday homes for sale or rent, plots, commercial for sale or rent, farms and forest estates, garages, and new developments.

Supported filters on searches that do not already set the same keys: building type, room count, minimum and maximum price in euros, living area in square meters, construction year, and sort order.

`maxItems` defaults to 100. `0` means no item cap. The saved sample used Helsinki, homes for sale, and `maxItems` 5, with detail extraction off.

Card records include address, district, city, postal code, price, price per square meter, living area, rooms, room layout, floor, building floor count, maintenance fee, construction year, coordinates, image, publication time, vendor ad id, and visit counts. `officeName` and `officeId` were null on the saved cards.

`extractDetails` fetches the listing page and sets `detailsScraped` to true. That path can add energy class, heating, sauna and kitchen text, contact name, phone, and email, office contact fields, an image list, viewings, and extra price fields. Those fields are absent on card-only records. Detail enrichment charges the separate `listing-details` event after a successful detail fetch.

Not currently collected:

- A guaranteed office name on every card. The saved Helsinki cards left `officeName` null
- Historical sold-price series
- Media files. `imageUrl` is a link

### Data dictionary

Types and examples are from a saved Helsinki for-sale card with `detailsScraped` false. The description in that file is longer than the text shown in the example below.

| Field | Type | Nullable | Description | Example |
|---|---|---:|---|---|
| `id` | integer | No | Numeric listing id. Same value as `cardId` on this card. | `24609013` |
| `cardId` | string | No | Listing id as a string. Best join key when you mix card and detail records. | `24609013` |
| `url` | string | No | Public listing URL. | `https://asunnot.oikotie.fi/myytavat-asunnot/helsinki/24609013` |
| `cardType` | integer | No | Listing category code. | `100` |
| `cardTypeLabel` | string or null | Yes | Category label. | `For sale (homes)` |
| `buildingType` | integer or null | Yes | Building type code. | `1` |
| `buildingTypeLabel` | string or null | Yes | Building type label. | `Apartment building` |
| `status` | integer or null | Yes | Source status code. | `1` |
| `description` | string or null | Yes | Card description text. | Finnish listing text |
| `rooms` | number or null | Yes | Room count. | `2` |
| `roomConfiguration` | string or null | Yes | Layout label. | `2h + kk` |
| `price` | number or null | Yes | Price in euros. | `215000.0` |
| `priceText` | string or null | Yes | Formatted euro price. | `215 000 €` |
| `pricePerSqm` | number or null | Yes | Euros per square meter. | `5000` |
| `size` | number or null | Yes | Living area in square meters. | `43` |
| `sizeText` | string or null | Yes | Formatted area. | `43 m²` |
| `sizeLot` | number or null | Yes | Lot size. Null on some cards. | `1118.9` |
| `buildYear` | integer or null | Yes | Construction year. | `1961` |
| `floor` | integer or null | Yes | Floor number. | `4` |
| `buildingFloorCount` | integer or null | Yes | Floors in the building. | `8` |
| `maintenanceFee` | number or null | Yes | Maintenance fee in euros. | `245.1` |
| `newDevelopment` | boolean or null | Yes | New-development flag. | `false` |
| `nextViewing` | object or null | Yes | Next viewing. Null when none is listed. | See below |
| `visits` | integer or null | Yes | Visit count from the card. | `0` |
| `visitsWeekly` | integer or null | Yes | Weekly visit count. | `0` |
| `address` | string or null | Yes | Street, postal code, and city. | `Suvilahdenkatu 1, 00500, Helsinki` |
| `streetAddress` | string or null | Yes | Street address. | `Suvilahdenkatu 1` |
| `district` | string or null | Yes | District. | `Sörnäinen` |
| `city` | string or null | Yes | City. | `Helsinki` |
| `zipCode` | string or null | Yes | Postal code. | `00500` |
| `country` | string or null | Yes | Country label from the source. | `Suomi` |
| `latitude` | number or null | Yes | Latitude. | `60.1871` |
| `longitude` | number or null | Yes | Longitude. | `24.9669` |
| `published` | string or null | Yes | Published timestamp, `YYYY-MM-DD HH:MM:SS`. | `2026-07-25 11:15:17` |
| `publishedSort` | string or null | Yes | Sort timestamp from the source. | `2026-07-25 11:15:18` |
| `vendorAdId` | string or null | Yes | Vendor advertisement id. | UUID string |
| `officeName` | string or null | Yes | Office name. Null on the saved card. | `null` |
| `officeId` | string or null | Yes | Office id. Null on the saved card. | `null` |
| `imageUrl` | string or null | Yes | Card image URL. | `https://cdn.asunnot.oikotie.fi/...` |
| `detailsScraped` | boolean | No | True only after a successful listing-page enrichment. | `false` |
| `sourceQuery` | string or null | Yes | Location or URL query that produced the card. | `Helsinki` |

`nextViewing`, when present:

| Field | Type | Description | Example |
|---|---|---|---|
| `date` | string | Viewing date | `2026-07-26` |
| `start` | string | Start time | `13:00` |
| `end` | string | End time | `13:30` |
| `live` | boolean | Live-viewing flag | `false` |
| `first` | boolean | First-viewing flag | `true` |

Detail-only fields, present when `detailsScraped` is true, and otherwise omitted:

`descriptionSupplementary`, `priceSell`, `shareOfLiabilities`, `rentPerMonth`, `sizeTotal`, `energyClass`, `heating`, `sauna`, `saunaInfo`, `kitchenInfo`, `bathroomInfo`, `availability`, `servicesInfo`, `otherFeesInfo`, `estateTax`, `realEstateId`, `created`, `lastModified`, `expires`, `officeEmail`, `officePhone`, `officeUrl`, `officeStreetAddress`, `officeCity`, `officeZipCode`, `contactName`, `contactPhone`, `contactEmail`, `images`, `viewings`, and `sellStatus`.

No detail-enriched sample was saved in this folder, so those fields are named from the parser and are not given example values here.

### Example dataset record

This card is a Helsinki for-sale apartment from `searchQueries: ["Helsinki"]` with `extractDetails` false. The stored `description` is longer. The text below is the opening of that same description.

```json
{
  "id": 24609013,
  "cardId": "24609013",
  "url": "https://asunnot.oikotie.fi/myytavat-asunnot/helsinki/24609013",
  "cardType": 100,
  "cardTypeLabel": "For sale (homes)",
  "buildingType": 1,
  "buildingTypeLabel": "Apartment building",
  "status": 1,
  "description": "Raikasta merituulta, urbaania asumista parhaimmillaan Vilhonvuoren rauhaisilla ja viihtyisillä kaduilla.",
  "rooms": 2,
  "roomConfiguration": "2h + kk",
  "price": 215000.0,
  "priceText": "215 000 €",
  "pricePerSqm": 5000,
  "size": 43,
  "sizeText": "43 m²",
  "sizeLot": 1118.9,
  "buildYear": 1961,
  "floor": 4,
  "buildingFloorCount": 8,
  "maintenanceFee": 245.1,
  "newDevelopment": false,
  "nextViewing": {
    "date": "2026-07-26",
    "start": "13:00",
    "end": "13:30",
    "live": false,
    "first": true
  },
  "visits": 0,
  "visitsWeekly": 0,
  "address": "Suvilahdenkatu 1, 00500, Helsinki",
  "streetAddress": "Suvilahdenkatu 1",
  "district": "Sörnäinen",
  "city": "Helsinki",
  "zipCode": "00500",
  "country": "Suomi",
  "latitude": 60.1871,
  "longitude": 24.9669,
  "published": "2026-07-25 11:15:17",
  "publishedSort": "2026-07-25 11:15:18",
  "vendorAdId": "75485a34-132f-43b2-a38e-c37b1e1e7f9c",
  "officeName": null,
  "officeId": null,
  "imageUrl": "https://cdn.asunnot.oikotie.fi/C763kBNcZy05qAuNvn9lfE21dH4=/full-fit-in/708x444/filters:background_color(white):format(jpeg):quality(60)/ot-real-estate-mediabank-prod/281/886/source/231688182",
  "detailsScraped": false,
  "sourceQuery": "Helsinki"
}
```

### Query and input reference

| Input | Type | Required | Default | Accepted values | Description |
|---|---|---:|---|---|---|
| `startUrls` | URL array | No | None | Search or listing URLs | Priority source. Prefill is a Helsinki for-sale search. |
| `searchQueries` | string array | No | None | City, district, or postal code | Ignored when `startUrls` is set. Prefill: `Helsinki`. |
| `listingType` | string | No | `FOR_SALE` | `FOR_SALE`, `FOR_RENT`, `HOLIDAY_FOR_SALE`, `HOLIDAY_FOR_RENT`, `PLOTS`, `COMMERCIAL_FOR_SALE`, `COMMERCIAL_FOR_RENT`, `FARMS`, `GARAGES`, `NEW_DEVELOPMENT` | Listing category. |
| `buildingTypes` | string array | No | Empty | `APARTMENT`, `ROW_HOUSE`, `DETACHED_HOUSE`, `HOLIDAY_HOME`, `SEMI_DETACHED_SEPARATE`, `SEMI_DETACHED`, `OTHER`, `WALK_UP`, `WOODEN_APARTMENT` | Empty means all types. |
| `roomCounts` | string array | No | Empty | `1`, `2`, `3`, `4`, `5` | `5` means five or more rooms. |
| `priceMin` | integer | No | None | Euros, minimum 0 | Minimum sale price or rent. |
| `priceMax` | integer | No | None | Euros, minimum 0 | Maximum price. |
| `sizeMin` | integer | No | None | Square meters, minimum 0 | Minimum living area. |
| `sizeMax` | integer | No | None | Square meters, minimum 0 | Maximum living area. |
| `yearMin` | integer | No | None | Year, minimum 1800 | Minimum construction year. |
| `yearMax` | integer | No | None | Year, minimum 1800 | Maximum construction year. |
| `sortBy` | string | No | `publishedDesc` | `publishedDesc`, `publishedAsc`, `priceAsc`, `priceDesc`, `sizeAsc`, `sizeDesc` | Search sort. |
| `extractDetails` | boolean | No | `false` | `true` or `false` | Fetch each listing page and charge `listing-details`. |
| `detailConcurrency` | integer | No | `5` | 1–50 | Parallel detail requests. |
| `maxItems` | integer | No | `100` | `0` or a positive integer | Maximum listings. `0` means no cap. Prefill `20`. |
| `proxyConfiguration` | object | No | Apify residential proxy | Apify proxy editor | Proxy for search and detail requests. |

Filters are ignored for keys already present on a start URL.

Minimal request:

```json
{
  "searchQueries": ["Helsinki"],
  "listingType": "FOR_SALE",
  "maxItems": 5,
  "extractDetails": false
}
```

Detail request:

```json
{
  "startUrls": [
    { "url": "https://asunnot.oikotie.fi/myytavat-asunnot?cardType=100&locations[]=helsinki" }
  ],
  "maxItems": 5,
  "extractDetails": true,
  "detailConcurrency": 3
}
```

### Retrieve the data through the API

1. Start `datascrapers/asunnot-oikotie-fi` with the JSON input.
2. Wait until the run finishes, or call the synchronous dataset endpoint.
3. Read items from the run's default dataset.
4. Paginate with dataset `offset` and `limit`, or export from the Apify console.

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("datascrapers/asunnot-oikotie-fi").call(
    run_input={
        "searchQueries": ["Helsinki"],
        "listingType": "FOR_SALE",
        "maxItems": 5,
        "extractDetails": False,
    }
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["cardId"], item["city"], item["price"])
```

Other languages are listed on the Actor's API tab. This is the Apify Actor API, not an Oikotie API.

### Data quality and record handling

- Card records always include `detailsScraped`. It is false until a listing page is merged in.
- Deduplicate on `cardId`. `id` is the same listing number when it is numeric.
- `vendorAdId` is a second identifier from the source. It was present on the saved Helsinki cards.
- Price is euros. `pricePerSqm` is euros per square meter. `size` is square meters. `maintenanceFee` is euros.
- `published` is a source timestamp string, not a timezone-aware ISO value.
- Overlapping locations can return the same `cardId`. Compare that field before merging runs.
- A failed detail request leaves the card record and does not set `detailsScraped` to true.
- The `listing-details` charge runs only after a successful enrichment. A card-only run charges `dataset-item` only.
- Contact email and phone exist only on enriched records and only when the listing page includes them.

### Pricing and cost examples

The price file in the Actor folder sets **$1 per 1,000 listings** and **$2 per 1,000 listing details**. Registered event prices, the same on every plan:

| Event | When it is charged | Price |
|---|---|---:|
| `dataset-item` | Each listing pushed to the dataset | $0.001 |
| `listing-details` | Each successful detail enrichment | $0.002 |

Platform usage, including compute and residential proxy, is billed separately by Apify. Estimates below assume every selected listing is pushed, and, in the enriched column, every one of those listings is enriched.

| Listings | Cards only | Cards plus details |
|---:|---:|---:|
| 1,000 | $1.00 | $3.00 |
| 10,000 | $10.00 | $30.00 |

### Limitations and responsible data use

- Results follow the public search you request. An empty location list is a nationwide search and can be large.
- Filters do not override query keys already present on a start URL.
- Office and contact fields are often missing on card-only records.
- Detail fields depend on the listing page. A missing energy class or email stays absent.
- Viewings and prices change on the source. This dataset is not a historical archive.
- Contact details are personal data when they identify a person. Use them in line with the privacy rules that apply to your project.
- You are responsible for complying with the site's terms and applicable law.

### Dataset questions

#### What does one dataset item represent?

One Oikotie Asunnot listing. With `extractDetails` enabled and a successful fetch, the same record also contains listing-page fields and `detailsScraped` true.

#### Which field should I use as a unique identifier?

Use `cardId`. `id` repeats that number as an integer on saved cards.

#### Are fields nullable or conditional?

Yes. Lot size, office name, and the next viewing are null on some cards. Energy class, heating, and contact fields are only added when `detailsScraped` is true.

#### Can I retrieve the records as CSV or JSON?

Yes. Export the default dataset as JSON, CSV, Excel, XML, or another Apify format.

#### How do I paginate large datasets?

Set `maxItems` on the run. Read items with dataset `limit` and `offset`. `0` removes the Actor's item cap.

#### Does the Actor return historical data?

No. `published` is the listing's published time, not a history of price changes.

#### What counts as a billable result?

Each pushed listing charges `dataset-item` at $0.001. Each successful detail enrichment also charges `listing-details` at $0.002.

### Related datasets from Data Scrapers

- [Apartments Scraper](https://apify.com/datascrapers/apartments-scraper) collects apartment listings with price, size, and location fields.
- [Aqar.fm Scraper](https://apify.com/datascrapers/aqar-fm-scraper) collects Saudi listing cards you can compare on price, area, and city.
- [Aengevelt Scraper](https://apify.com/datascrapers/aengevelt-scraper) collects property records from a commercial brokerage site.
- [99acres Scraper](https://apify.com/datascrapers/99acres-scraper) is a listings dataset with price and area fields.
- [99.co Scraper](https://apify.com/datascrapers/99-co-scraper) collects portal listings for the same kind of market comparison.

### Data Scrapers support

Need an additional field, record type, or export workflow? Contact Data Scrapers at stardustspotlight@gmail.com. Include a sample source URL, required fields, expected record volume, and preferred delivery format.

# Actor input Schema

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

Paste Oikotie search result URLs (e.g. https://asunnot.oikotie.fi/myytavat-asunnot?cardType=100\&locations\[]=helsinki) or listing URLs (e.g. https://asunnot.oikotie.fi/myytavat-asunnot/helsinki/24600052). When provided, these take priority over Search Locations. Query filters on search URLs are preserved.

## `searchQueries` (type: `array`):

Cities, districts, or postal codes (e.g. Helsinki, Tampere, 00100). Ignored when Start URLs are provided. Leave empty with no Start URLs to search nationwide using the filters below.

## `listingType` (type: `string`):

Main listing category on Oikotie Asunnot.

## `buildingTypes` (type: `array`):

Leave empty for all building types. Applies mainly to residential for-sale/rent searches.

## `roomCounts` (type: `array`):

Leave empty for any room count. Use 5 for five or more rooms.

## `priceMin` (type: `integer`):

Minimum price in euros (sale price or rent depending on listing type).

## `priceMax` (type: `integer`):

Maximum price in euros.

## `sizeMin` (type: `integer`):

Minimum living area in square meters.

## `sizeMax` (type: `integer`):

Maximum living area in square meters.

## `yearMin` (type: `integer`):

Minimum construction year.

## `yearMax` (type: `integer`):

Maximum construction year.

## `sortBy` (type: `string`):

Sort order for search results.

## `extractDetails` (type: `boolean`):

When enabled, fetches the full listing for each result (long description, energy class, heating, contact emails/phones, image gallery, etc.) and charges the separate listing-details event.

## `detailConcurrency` (type: `integer`):

Maximum parallel detail requests when Extract Listing Details is enabled.

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

Maximum number of listings to scrape (0 = unlimited).

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

Proxy settings. Residential proxy is recommended for reliable runs on Apify Cloud.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://asunnot.oikotie.fi/myytavat-asunnot?cardType=100&locations[]=helsinki"
    }
  ],
  "searchQueries": [
    "Helsinki"
  ],
  "listingType": "FOR_SALE",
  "sortBy": "publishedDesc",
  "extractDetails": false,
  "detailConcurrency": 5,
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Dataset containing scraped asunnot.oikotie.fi listings

## `runStats` (type: `string`):

Aggregate scrape statistics for this run

# 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 = {
    "startUrls": [
        {
            "url": "https://asunnot.oikotie.fi/myytavat-asunnot?cardType=100&locations[]=helsinki"
        }
    ],
    "searchQueries": [
        "Helsinki"
    ],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascrapers/asunnot-oikotie-fi").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 = {
    "startUrls": [{ "url": "https://asunnot.oikotie.fi/myytavat-asunnot?cardType=100&locations[]=helsinki" }],
    "searchQueries": ["Helsinki"],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("datascrapers/asunnot-oikotie-fi").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 '{
  "startUrls": [
    {
      "url": "https://asunnot.oikotie.fi/myytavat-asunnot?cardType=100&locations[]=helsinki"
    }
  ],
  "searchQueries": [
    "Helsinki"
  ],
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call datascrapers/asunnot-oikotie-fi --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datascrapers/asunnot-oikotie-fi"
        }
    }
}
```

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/rwPSaDTiEHnR1kLqv/builds/pkmqtJeXqsPnpWHrb/openapi.json
