# Idealista Scraper - Spain, Italy and Portugal Property Listings (`ziomixshot/idealista-scraper`) Actor

Collect Idealista houses and flats for sale or rent in Spain, Italy and Portugal: price, price drops, size, rooms, floor, agency and listing URL.

- **URL**: https://apify.com/ziomixshot/idealista-scraper.md
- **Developed by:** [Amadeusz](https://apify.com/ziomixshot) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 listings

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

## Idealista Scraper

Collect houses and flats for sale or rent from [Idealista](https://www.idealista.com) in Spain (`idealista.com`), Italy (`idealista.it`) and Portugal (`idealista.pt`). Type a province or town name, add the filters of the Idealista search form, or paste a search URL copied from Idealista. Every listing is checked against your filters, de-duplicated and returned as clean JSON, ready for CSV, Excel, the API or AI agents.

[Run Idealista Scraper](https://console.apify.com/actors/UbYrSJ5zprgu6avz7?addFromActorId=UbYrSJ5zprgu6avz7) · [Input schema](https://apify.com/ziomixshot/idealista-scraper/input-schema) · [Output schema](https://apify.com/ziomixshot/idealista-scraper/output-schema)

### What you get

- Three markets: Spain, Italy and Portugal, houses and flats for sale or for rent.
- Place names instead of codes: `location` takes a province, municipality, island, coast or region name (`Madrid`, `Valencia`, `Milano`, `Lisbon`, `Mallorca`, `Costa del Sol`, `Toscana`, `Algarve`, accents optional) or the path from the Idealista address bar (`barcelona/eixample`). A misspelled name ends the run with the closest names. A `listLocations` run (start fee only) lists every name and path.
- Every option of the search form: property type, bedrooms (rooms in Italy), bathrooms, condition, lift, terrace, parking, pool, floor, energy rating, floor plan, virtual tour and more. A `listFilters` run (start fee only) lists every key per country and operation; an unknown key gets the closest keys in the error message.
- Price and size ranges, publication date (`publishedWithin`), 14 sort orders, search URLs copied from Idealista (`startUrls`), several searches in one run with shared de-duplication.
- Verified results: the filters and the sort order are checked against the search Idealista actually applied before anything is charged. A filter Idealista would silently ignore stops the run with an explanation instead of returning wrong data, and a card that contradicts your price, size, bedroom or lift filter is dropped without a charge.
- No duplicates: the same listing is returned once per run, and you are charged once.
- Price drops from the card: `previousPrice` and `priceDropPercent`, plus price per m², floor, lift, parking and the agency.
- Optional details (`enrichDetails`): full description, all features, bathrooms, condition, year built, energy certificate, community costs, address, coordinates, all photos, floor plans, update date and advertiser.
- Monitoring (`mode: monitor`): each run returns only listings not reported by earlier runs, plus a `change` record when the price of a reported listing changed.
- Estimate (`countOnly`): how many listings match your search, without listing charges.
- More than 1,800 results per search: one Idealista search shows at most 1,800 listings, so the Actor splits larger searches by price automatically.
- One date format (UTC, `YYYY-MM-DDTHH:mm:ssZ`) in every field.

### Quick start

1. Choose **Sale or rent** and type a **Location**, for example `Madrid`, `Valencia`, `Milano` or `Lisbon`.
2. Add price, size or filters if you need them.
3. Set **Max items** (the limit of listings returned and charged).
4. Click **Start**. The default input (`location: Madrid`, `operation: sale`, `maxItems: 100`) is a working example.
5. Open the **Overview** table, export JSON, CSV or Excel, or read the data through the API.

Not sure how many listings match? Start with **Count only**.

### Pricing

Pay per event:

| Event | Price | When |
|---|---|---|
| `listing` | $0.50 / 1000 | One per listing returned |
| `listing-details` | $1.00 / 1000 | One per listing when `enrichDetails` is on and the listing page was read |
| `listing-change` | $0.50 / 1000 | One per `change` record in monitor mode |
| Actor start | $0.005 per run | Once per run with the default 1 GB of memory (once more per extra GB) |

Duplicates, rejected cards and listings removed before their page was read are not charged. `countOnly`, `listLocations` and `listFilters` runs, empty runs and runs that end with an input or filter error return no listings and pay only the start. `maxItems` and your maximum cost per run are hard limits: the run stops when either is reached.

Cost of a run = $0.005 + listings × $0.0005 (plus $0.001 per enriched listing and $0.0005 per change record). For example, 1,000 listings with details cost $1.505.

### Ready-to-use recipes

#### 1. Flats for sale in a city

```json
{
  "country": "es",
  "operation": "sale",
  "location": "Valencia",
  "filters": ["flats", "lift", "bedrooms-2", "bedrooms-3"],
  "priceTo": 300000,
  "sizeFrom": 70,
  "maxItems": 200
}
```

Keys of one group (`bedrooms-2`, `bedrooms-3`) mean either; keys of different groups must all apply.

#### 2. Rentals in Milan published this week

```json
{
  "country": "it",
  "operation": "rent",
  "location": "Milano",
  "filters": ["rooms-2", "furnished"],
  "publishedWithin": "week",
  "priceTo": 1800,
  "maxItems": 100
}
```

Italy counts rooms (`rooms-2` is a "bilocale"), Spain and Portugal count bedrooms (`bedrooms-2`).

#### 3. Search URL copied from Idealista

```json
{
  "startUrls": ["https://www.idealista.com/alquiler-viviendas/madrid-madrid/con-precio-hasta_1500,ascensor/"],
  "maxItems": 200
}
```

The country, operation, location, filters and sort come from the URL. A URL part the Actor does not know is rejected instead of ignored.

#### 4. Monitor new listings and price changes

```json
{
  "country": "pt",
  "operation": "sale",
  "location": "Lisbon",
  "filters": ["bedrooms-2"],
  "priceTo": 500000,
  "mode": "monitor",
  "maxItems": 500
}
```

Schedule it in Apify. The first run returns what is there; later runs return only new listings and `change` records.

#### Use it from the API

```bash
curl -X POST "https://api.apify.com/v2/acts/ziomixshot~idealista-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"location":"Madrid","operation":"rent","priceTo":1500,"maxItems":50}'
```

The same Actor is available to AI agents through the [Apify MCP server](https://mcp.apify.com): add `ziomixshot/idealista-scraper` to the tools of the server.

### Input

The full description of every field is in the input form. A field the Actor does not know (for example a typo such as `locaton`) is named in a warning in the run log and ignored.

| Field | Description |
|---|---|
| `country` | `es`, `it` or `pt`. Empty: taken from the location name; a location path without a country searches Spain. |
| `operation` | `sale` (default) or `rent`. |
| `location` | Province, municipality, zone (island, coast, comarca: `Mallorca`, `Tenerife`) or region name (`Costa del Sol`, `Toscana`, `Algarve`) (a municipality wins over a province, a zone or a region with the same name; of several municipalities the provincial capital wins and the log names the others; a country or province after a comma picks one: `Porto, Spain`, `Arroyomolinos, Madrid`), or the path from the Idealista address bar (`madrid-madrid`, `barcelona/eixample`, `geo/costa-del-sol`). A name the catalog does not have ends the run with the closest names, and so does a path Idealista does not know. |
| `filters` | Filter keys of the search form in any letter case, for example `lift`, `terrace`, `flats`, `bedrooms-2` (Spain, Portugal) or `rooms-2` (Italy). `listFilters` shows the keys of each country and operation. |
| `publishedWithin` | `24h`, `48h`, `week` or `month`. |
| `priceFrom`, `priceTo` | Price in EUR, inclusive: sale price, or monthly rent for rent. |
| `sizeFrom`, `sizeTo` | Built area in m², inclusive. |
| `sortBy` | `relevance`, `priceAsc`, `priceDesc`, `newest`, `oldest`, `biggestPriceDrop`, `pricePerM2Asc`, `pricePerM2Desc`, `sizeDesc`, `sizeAsc`, `floorDesc`, `floorAsc`, `privateAdvertisersFirst`, `professionalsFirst`. An order a country or operation does not offer is refused. |
| `startUrls` | Search URLs copied from Idealista. They replace all search, filter and sort fields above. |
| `maxItems` | Hard limit of returned listings and charges, shared by all searches of the run (default 100, up to 100,000). |
| `enrichDetails` | Read the page of each listing; each one also triggers the `listing-details` event. |
| `mode`, `seenStoreName`, `seenIdsKey` | Monitoring, see below. |
| `countOnly` | Return only the number of matching listings. |
| `listLocations` | Return the provinces, municipalities, zones and regions (name, path, search URL) instead of listings; `country` and `location` narrow the list. When both `listLocations` and `listFilters` are set, only locations are listed. |
| `listFilters` | Return the filter keys and sort orders instead of listings; `country` and `operation` narrow the list. |

### Output

Every listing is one dataset item. The dataset has three views: **Overview**, **Details** and **Price changes**.

Fields of every `listing` item: `recordType`, `id`, `url`, `title`, `country`, `operation`, `price`, `currency` (`EUR`), `previousPrice`, `priceDropPercent`, `pricePerM2`, `bedrooms` (Spain, Portugal), `rooms` (Italy), `sizeM2`, `floor`, `hasLift`, `exterior`, `parking`, `parkingPrice`, `publishedLabel`, `otherDetails`, `descriptionSnippet`, `tags`, `ribbon` (for example "Finished new development"), `photoCount`, `thumbnail`, `isProfessional`, `highlight` (`top`, `featured` or `null`), `agency` (`name`, `profileUrl`, `logoUrl`), `publishedAt`, `scrapedAt`. A value Idealista does not show is `null`.

Added by `enrichDetails`: `detailsFetched`, `description`, `descriptionTranslated`, `locationName`, `address` (from street to province), `latitude`, `longitude`, `locationId`, `builtAreaM2`, `usableAreaM2`, `bathrooms`, `condition`, `yearBuilt`, `orientation`, `heating`, `energy` (`rating` A to G, plus A+, A1 to A4 and B- where the country uses them; `consumptionKwhM2Year`, `emissionsKgCo2M2Year`), `communityCosts`, `priceNotes`, `features` (every section of the listing page), `images` (`url`, `tag`), `floorPlans`, `updatedAt`, `reference`, `advertiser` (`type`, `name`, `agencyName`, `agencyProfileUrl`, `agencyLogoUrl`). A listing removed before its page was read is skipped and not charged (`detailsUnavailable` in the run status); a page that could not be read after all retries leaves the card record, charged only as `listing` (`detailsFailed`, run status `PARTIAL`).

Other record types, always free except `change`:

- `status`: the run ended because of your input and returned no listings. Fields: `status`, `message` (what is wrong and how to fix it), `details`, `scrapedAt`.
- `estimate`: result of `countOnly`: `estimatedTotal`, `sources` (one count per search), `note`.
- `location`: result of `listLocations`: `country`, `kind` (`province`, `municipality`, `zone` or `area` for a region), `name`, `path`, `province` (of a municipality or zone), `url`. Put `name` or `path` into `location`.
- `filter` and `sort`: result of `listFilters`: `country`, `operation`, `key`, `inputField` (`filters` or `sortBy`), `group`, `label`, `slug`.
- `change`: see monitoring.

#### Run status

The `OUTPUT` record of the key-value store describes the run: `status` (`OK`, `PARTIAL`, `INVALID_INPUT`, `URL_NOT_FULLY_RESOLVED`, `FILTER_VERIFICATION_FAILED`, `SEEN_STATE_INVALID`, `UPSTREAM_ERROR`), counters (`duplicates`, `detailsUnavailable`, `detailsFailed`, `predicateViolations`) and `jobs[]` per search (`url`, `expectedTotal`, `pagesRead`, `failedPages`, `coverage`, `partitions`, `truncatedPartitions`). Input and filter errors end the run without listings. A valid search Idealista has no listings for ends with `OK` and 0 listings. `UPSTREAM_ERROR` with a first page blocked or failed after all retries charges only the start: run it again later. `PARTIAL` means some pages or details failed after all retries; the returned records are still valid.

### Monitoring new listings and price changes

`mode: monitor` returns only listings whose ID was not reported by earlier runs with the same `seenStoreName` and `seenIdsKey`, and a `change` record for every reported listing whose price changed since: `recordType: "change"`, `metric: "price"`, `id`, `url`, `title`, `country`, `operation`, `currency`, `previous`, `current`, `delta` and `changedAt`.

- Every run reads the whole search, because Idealista in Spain blocks the newest-first order. `sortBy` does not change what a monitor returns.
- The first run returns every listing as new and stores its price. Later runs compare the price of each known card with the stored one, with no extra requests. A price that appears or disappears is stored without a `change` record.
- `maxItems` limits new listings and change records together. New listings or changes beyond the limit are kept for the next run.
- Without `seenStoreName` the Actor uses a store named after the search (`idealista-monitor-...`, shown in the run log), so repeating the same search keeps its history; the sort order and the order of filters do not change the name. Set a new name (letters, digits and hyphens) to share one history between different runs: the Actor creates that store and keeps access to it. A store created outside this Actor cannot be used, because the Actor runs with limited permissions; such a run stops before any listing is charged.
- The state keeps the 500,000 newest listings with their last price. A corrupted state record ends the run with `SEEN_STATE_INVALID` instead of starting over.
- The state is saved when a run ends. Runs on the same store must not overlap (for example a schedule shorter than one run): overlapping runs report the same listings, and an aborted or timed-out run may not save what it reported.

### Estimate (`countOnly`)

Returns one item with `recordType: "estimate"` and `estimatedTotal`, the number Idealista reports for each search. The first page of each search is read, so an unknown location or a filter Idealista ignores still stops the run. With several `startUrls` the result is the sum of the searches (overlapping searches are counted once per search). The monitor state is not touched. No listing is charged.

### Limits and notes

- One search exposes at most 1,800 listings (60 pages of 30). For `maxItems` above that, larger searches are read in price ranges. Sorting then applies only inside each range. `truncatedPartitions` above 0 means more than 1,800 listings with the same price that cannot be separated.
- In Spain Idealista blocks the `newest` sort order; use `publishedWithin` to get recent listings.
- The Actor reads the English version of each site. `descriptionTranslated: true` means Idealista translated the description automatically.
- Phone numbers are not collected: Idealista reveals them only after a click on the listing page.
- Idealista protects its sites with anti-bot systems. Runs use Apify residential proxies in the country of the site (included in the price). A page that cannot be read after all retries is counted in `failedPages` and the run ends `PARTIAL`.
- The Actor uses the public web pages of Idealista, which are unofficial as an interface and can change without notice.
- The Actor reads public pages anonymously. It never logs in, never contacts advertisers, never saves searches and never changes anything on an account.

### Legal notice

This Actor collects data that Idealista shows publicly. Idealista's terms of use restrict automated access to the site and the use of its content; you are responsible for using the data lawfully and in line with those terms. Listings contain personal data of advertisers (names of private advertisers and agents), so GDPR rules apply to how you store and use them. The Actor is not affiliated with Idealista.

### Development

Stack: Node 20+, TypeScript strict (ESM), Apify SDK 3, Impit 0.7.5 (Chrome profile), cheerio 1.0.0-rc.12, Vitest, ESLint, Prettier. Apify RESIDENTIAL proxy of the country of the site. No database and no migrations.

```bash
npm ci
npm run typecheck && npm run lint && npm run format:check && npm test
```

Local run (needs `APIFY_TOKEN` in the environment and RESIDENTIAL proxy on the account):

```bash
mkdir -p storage/key_value_stores/default
echo '{"country":"es","location":"madrid-madrid","maxItems":60}' > storage/key_value_stores/default/INPUT.json
npm run start:dev
```

Results: `storage/datasets/default/*.json` and `storage/key_value_stores/default/OUTPUT.json`.

| Variable | Role |
|---|---|
| `APIFY_TOKEN` | Apify token: locally it fetches the proxy password; in CI a GitHub secret for the deployment |

The location catalog (`src/idealista/locations/*.json`: provinces and municipalities with English names, zones linked from province pages and `/geo/` regions) is built offline by a read-only script, about 190 requests through the RESIDENTIAL proxy:

```bash
npx tsx --env-file=<file with APIFY_TOKEN> scripts/build-locations.ts es it pt
npx prettier --write src/idealista/locations
```

A push to `main` runs `.github/workflows/deploy-apify.yml`: typecheck, lint, format, tests, schema validation and an Actor build tagged `beta`.

Backlog and decisions: [docs/backlog.md](docs/backlog.md), architecture: [docs/diagram.md](docs/diagram.md), routes and `robots.txt`: [docs/ENDPOINTS.md](docs/ENDPOINTS.md), competitors and pricing: [docs/pricing.md](docs/pricing.md).

# Actor input Schema

## `country` (type: `string`):

The Idealista site to search; the run reads it through a residential proxy of the same country. Leave empty to take it from the location name (Madrid is Spain, Milan is Italy); set it when the name exists in several countries. A location path without a country searches Spain.

## `operation` (type: `string`):

Houses and flats for sale or for rent.

## `location` (type: `string`):

A province, municipality, island, coast or region name, for example Madrid, Valencia, Milano, Lisbon, Mallorca, Costa del Sol or Toscana (accents optional), or the location path from the Idealista address bar, for example madrid-madrid or barcelona/eixample for a district. A name used in several places means the provincial capital; a country or province after a comma picks another one, for example Porto, Spain. Show locations lists the names and paths.

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

Copied Idealista search URLs (idealista.com, idealista.it, idealista.pt), one per line, with the filters and sort chosen on Idealista. When set, they replace every field of Search, Filters and Sort.

## `filters` (type: `array`):

Filter keys of the Idealista search form, for example lift, terrace, flats, bedrooms-2 (Spain, Portugal) or rooms-2 (Italy). Show filters lists the keys each country and operation offers. Keys of one group (for example bedrooms-1 and bedrooms-2) mean either; keys of different groups must all apply.

## `publishedWithin` (type: `string`):

Only listings published in this period.

## `priceFrom` (type: `integer`):

Minimum price in EUR, inclusive: sale price, or monthly rent for rent.

## `priceTo` (type: `integer`):

Maximum price in EUR, inclusive.

## `sizeFrom` (type: `integer`):

Minimum built area in m2, inclusive.

## `sizeTo` (type: `integer`):

Maximum built area in m2, inclusive.

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

Order of the results as Idealista sorts them. A run over 1,800 listings reads the search in price ranges, so the order holds within each range.

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

Hard limit of unique listings returned and charged, shared by all Search URLs of the run. Idealista serves 1,800 listings per search; above that the run splits the search into price ranges to read the rest.

## `enrichDetails` (type: `boolean`):

Also open the page of every listing: full description, features, bathrooms, condition, year built, energy certificate, community costs, address, coordinates, all photos, floor plans, update date and advertiser. Charged as listing-details on top of each listing; a listing removed meanwhile is skipped free of charge.

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

Scrape returns every matching listing. Monitor reads the whole search and returns only listings that earlier runs with the same store and key did not report, plus a change record (listing-change) for every reported listing whose price changed since. The first monitor run returns every listing as new. Schedule it to get alerts.

## `seenStoreName` (type: `string`):

Named key-value store that keeps what monitor runs reported. Leave empty to use a store named after the search (idealista-monitor-...; the run log shows it), so repeating the same search keeps its history. Set a new name (letters, digits and hyphens) to share one history between different runs: the Actor creates that store and keeps access to it. A store created outside this Actor cannot be used (the run stops before any listing is charged).

## `seenIdsKey` (type: `string`):

Record in the store that holds the reported listings and their last prices (up to 500000 newest listings are kept).

## `countOnly` (type: `boolean`):

No listing charges, only the run start: return the number of listings Idealista reports for each search. Filters are still verified.

## `listLocations` (type: `boolean`):

No listing charges, only the run start: list the provinces and municipalities (name, path, search URL) instead of collecting listings. Country narrows the list; Location narrows it to names or paths containing that text.

## `listFilters` (type: `boolean`):

No listing charges, only the run start: list the filter keys and sort orders of each country and operation instead of collecting listings. Country and Sale or rent narrow the list.

## Actor input object example

```json
{
  "operation": "sale",
  "location": "Madrid",
  "startUrls": [
    "https://www.idealista.com/en/venta-viviendas/madrid-madrid/"
  ],
  "filters": [
    "lift",
    "bedrooms-2"
  ],
  "sortBy": "relevance",
  "maxItems": 100,
  "enrichDetails": false,
  "mode": "scrape",
  "seenIdsKey": "IDEALISTA_SEEN",
  "countOnly": false,
  "listLocations": false,
  "listFilters": false
}
```

# Actor output Schema

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

Listings found by the run, one dataset item per listing. A run that ended on your input holds one status record with the reason.

## `status` (type: `string`):

Status record with counters (cards read, duplicates, pages read and failed, blocked answers) and the error code when the input was invalid.

# 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 = {
    "location": "Madrid",
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("ziomixshot/idealista-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 = {
    "location": "Madrid",
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("ziomixshot/idealista-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 '{
  "location": "Madrid",
  "maxItems": 100
}' |
apify call ziomixshot/idealista-scraper --silent --output-dataset

```

## MCP server setup

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