# Chicago Building Permits Scraper (`maximedupre/chicago-building-permits`) Actor

Search the official City of Chicago building-permit dataset by date, status, work type, location, contact, cost, or exact permit ID. Save structured permit details, project scope, fees, contacts, and source links for construction and property research.

- **URL**: https://apify.com/maximedupre/chicago-building-permits.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Business, Real estate, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.01 / 1,000 building permits

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### 🏗️ Find Chicago building permits by location, work, or permit ID

Construction teams, property researchers, and civic-data developers can search the official City of Chicago Building Permits dataset and save matching permits as structured dataset rows. Review permit status, milestone, work type, project cost, job address, fees, source-published contacts, and source links in one place. Use filters for one Chicago search, or look up one exact permit ID.

- Search the city records with **[City of Chicago Building Permits](https://apify.com/maximedupre/chicago-building-permits/examples/city-of-chicago-building-permits)** and review matching permits.
- Review construction work with **[Chicago Construction Permits](https://apify.com/maximedupre/chicago-building-permits/examples/chicago-construction-permits)** and compare each project's scope and cost.
- Find a job by address with **[City of Chicago Permits Search by Address](https://apify.com/maximedupre/chicago-building-permits/examples/city-of-chicago-permits-search-by-address)** and inspect its source-linked details.
- Group matching records with **[Chicago Permits by Ward](https://apify.com/maximedupre/chicago-building-permits/examples/chicago-permits-by-ward)** for ward-level project review.
- Find roofing work with **[Chicago Roof Permits](https://apify.com/maximedupre/chicago-building-permits/examples/chicago-roof-permits)** and compare the published scope and cost.
- Check a published status with **[Chicago Permit Status](https://apify.com/maximedupre/chicago-building-permits/examples/chicago-permit-status)** and review its milestone.
- Open one exact record with **[Chicago Permit Lookup](https://apify.com/maximedupre/chicago-building-permits/examples/chicago-permit-lookup)** using its permit ID.

#### 📋 Structured Chicago permit rows

Every saved row represents one matching source permit. It keeps the published permit ID, status, milestone, classification, dates, job location, project description, reported cost, fee breakdown, contact roles, and source details. Dates, amounts, durations, and coordinates use consistent JSON types where the source provides them. Chicago values that are not published remain unavailable; the Actor does not invent contact or project data.

#### ▶️ Search Chicago permits your way

**Run flow**

1. Choose **Search permits** for a filtered Chicago search, or **Look up a permit** for one exact published permit ID.
2. Add any date, status, classification, location, contact, project-text, or cost filters that fit your question.
3. Choose **All matching permits** or **New permits since prior run** in **Search mode**.
4. Set **Maximum permits** when you want an upper bound on saved permits. Leave it empty to return all available results until the source is exhausted.
5. Start the run and open the default dataset to review the saved rows and their source links.

Search fields narrow one Chicago query. For a repeat search, `newSincePreviousRun` asks for permits newly available since the prior run. A source item is saved on its first eligible match; if it appears again through another submitted value, later matches are ignored and the saved row keeps the first match's source context.

#### ⚙️ Input

**Input fields**

| Field | Type | What it does |
| --- | --- | --- |
| `target` | string | Choose `search` for matching permits or `permit` for one exact permit lookup. Fields for the other target are ignored. |
| `searchMode` | string | Choose `all` for all matching permits or `newSincePreviousRun` for permits newly available since the prior run. If omitted, all matching permits are used. |
| `projectSearch` | string | Optional text to find in the published project description. |
| `issueDateFrom` | date string | Optional first issue date to include, in `YYYY-MM-DD` format. |
| `issueDateTo` | date string | Optional last issue date to include, in `YYYY-MM-DD` format. |
| `permitStatuses` | array of strings | Optional published permit statuses to include. Leave empty to include every status. |
| `permitTypes` | array of strings | Optional published permit types to include. Leave empty to include all permit types. |
| `reviewTypes` | array of strings | Optional published review types to include. Leave empty to include all review types. |
| `workTypes` | array of strings | Optional published work types to include. Leave empty to include all work types. |
| `wards` | array of strings | Optional Chicago ward numbers to include. Leave empty to include all wards. |
| `communityAreas` | array of strings | Optional Chicago community area numbers to include. Leave empty to include all community areas. |
| `street` | string | Optional street text to match in the published job address. |
| `address` | string | Optional full address text to match in the published job address. |
| `owner` | string | Optional owner name text to match in published permit contacts. |
| `applicant` | string | Optional applicant name text to match in published permit contacts. |
| `contractor` | string | Optional contractor name text to match in published permit contacts. |
| `contactName` | string | Optional name text to match in any published contact entry. |
| `contactZip` | string | Optional ZIP code to match in published contact entries. |
| `minProjectCost` | number | Optional lowest reported project cost to include, in USD. |
| `maxProjectCost` | number | Optional highest reported project cost to include, in USD. |
| `maxItems` | integer | Optional stop after this many matching permits. Leave empty to return all available results until the source is exhausted. |
| `permitId` | string | Required when `target` is `permit`; enter one exact published Chicago permit ID. |

Leave optional filters empty when you want the source's full available range. `issueDateFrom` and `issueDateTo` use calendar dates. `permitStatuses`, `permitTypes`, `reviewTypes`, and `workTypes` use the values published by Chicago.

**Successful search input**

This is the public input from a successful current-beta search run:

```json
{
  "target": "search",
  "searchMode": "all",
  "projectSearch": "roof",
  "maxItems": 5
}
```

#### 🧾 Output

**Run output**

| Field | Type | What it does |
| --- | --- | --- |
| `dataset` | URL string | Links to the default Apify dataset that contains the successful Chicago building permit rows. |

Search and exact permit lookup use the same dataset row shape. Fields can be omitted when Chicago does not publish a value for that source row.

**Dataset row fields**

| Field | Type | What it does |
| --- | --- | --- |
| `permitId` | string | Published identifier for the Chicago building permit. |
| `status` | string | Published permit status. |
| `milestone` | string | Published permit milestone. |
| `classification` | object | Published permit, review, and work classifications. |
| `classification.permitType` | string | Published permit type. |
| `classification.reviewType` | string | Published review type. |
| `classification.workType` | string | Published work classification. |
| `timing` | object | Published dates and normalized processing duration. |
| `timing.applicationDate` | date string | Date when the permit application started. |
| `timing.issueDate` | date string | Date when the permit was issued. |
| `timing.processingDurationDays` | number | Normalized days from application to issue. |
| `property` | object | Published job location and property details. |
| `property.address` | object | Published address parts for the job. |
| `property.address.full` | string | Full published job address. |
| `property.address.streetNumber` | string | Published street number, when present. |
| `property.address.streetDirection` | string | Published street direction, when present. |
| `property.address.streetName` | string | Published street name, when present. |
| `property.address.streetSuffix` | string | Published street suffix, when present. |
| `property.address.city` | string | City in the published job address, when present. |
| `property.address.state` | string | State in the published job address, when present. |
| `property.address.zipCode` | string | ZIP code in the published job address, when present. |
| `property.ward` | integer | Published Chicago ward number. |
| `property.communityArea` | integer | Published Chicago community area number. |
| `property.propertyIdentifiers` | array of objects | Published property identifiers. |
| `property.propertyIdentifiers[]` | object | One property identifier. |
| `property.propertyIdentifiers[].type` | string | Source label for the property identifier. |
| `property.propertyIdentifiers[].value` | string | Published property identifier value. |
| `property.censusArea` | object | Published census area details. |
| `property.censusArea.tract` | string | Published census tract, when present. |
| `property.censusArea.blockGroup` | string | Published census block group, when present. |
| `property.censusArea.block` | string | Published census block, when present. |
| `property.coordinates` | object | Normalized published geographic coordinates. |
| `property.coordinates.latitude` | number | Published latitude in decimal degrees. |
| `property.coordinates.longitude` | number | Published longitude in decimal degrees. |
| `project` | object | Published work description and reported project cost. |
| `project.description` | string | Published description of the planned work. |
| `project.reportedCost` | number | Normalized project cost reported by the source. |
| `fees` | object | Published fee amounts and payment states. |
| `fees.total` | object | Total fee breakdown. |
| `fees.total.amount` | number | Total published fee amount. |
| `fees.total.paid` | number | Published amount already paid in the total breakdown. |
| `fees.total.unpaid` | number | Published amount still unpaid in the total breakdown. |
| `fees.total.waived` | number | Published amount waived in the total breakdown. |
| `fees.building` | object | Building fee breakdown. |
| `fees.building.amount` | number | Published building fee amount. |
| `fees.building.paid` | number | Published building amount already paid. |
| `fees.building.unpaid` | number | Published building amount still unpaid. |
| `fees.building.waived` | number | Published building amount waived. |
| `fees.zoning` | object | Zoning fee breakdown. |
| `fees.zoning.amount` | number | Published zoning fee amount. |
| `fees.zoning.paid` | number | Published zoning amount already paid. |
| `fees.zoning.unpaid` | number | Published zoning amount still unpaid. |
| `fees.zoning.waived` | number | Published zoning amount waived. |
| `fees.other` | object | Other fee breakdown. |
| `fees.other.amount` | number | Published other fee amount. |
| `fees.other.paid` | number | Published other amount already paid. |
| `fees.other.unpaid` | number | Published other amount still unpaid. |
| `fees.other.waived` | number | Published other amount waived. |
| `contacts` | array of objects | Source-published people and roles linked to the permit. |
| `contacts[]` | object | One source-published contact entry. |
| `contacts[].role` | string | Source-published role for the contact. |
| `contacts[].name` | string | Source-published contact name, when present. |
| `contacts[].mailingLocation` | object | Source-published mailing locality, when present. |
| `contacts[].mailingLocation.city` | string | Mailing city, when published. |
| `contacts[].mailingLocation.state` | string | Mailing state, when published. |
| `contacts[].mailingLocation.zipCode` | string | Mailing ZIP code, when published. |
| `source` | object | Source record and search details used for verification. |
| `source.provider` | string | Name of the source that published the record. |
| `source.dataset` | string | Name of the official Chicago dataset. |
| `source.datasetUrl` | URL string | Official URL for the Chicago dataset. |
| `source.recordId` | string | Source identifier when it differs from the permit ID. |
| `source.recordUrl` | URL string | Direct URL for the permit in the official source. |
| `source.searchContext` | object | Search settings applied to the result. |
| `source.searchContext.target` | string | Target used for the run: `search` or `permit`. |
| `source.searchContext.projectSearch` | string | Project text used by the search, when present. |
| `source.searchContext.issueDateFrom` | date string | First issue date used by the search, when present. |
| `source.searchContext.issueDateTo` | date string | Last issue date used by the search, when present. |
| `source.searchContext.permitStatuses` | array of strings | Permit status values used by the search. |
| `source.searchContext.permitTypes` | array of strings | Permit type values used by the search. |
| `source.searchContext.reviewTypes` | array of strings | Review type values used by the search. |
| `source.searchContext.workTypes` | array of strings | Work type values used by the search. |
| `source.searchContext.wards` | array of strings | Ward values used by the search. |
| `source.searchContext.communityAreas` | array of strings | Community area values used by the search. |
| `source.searchContext.street` | string | Street text used by the search, when present. |
| `source.searchContext.address` | string | Address text used by the search, when present. |
| `source.searchContext.owner` | string | Owner text used by the search, when present. |
| `source.searchContext.applicant` | string | Applicant text used by the search, when present. |
| `source.searchContext.contractor` | string | Contractor text used by the search, when present. |
| `source.searchContext.contactName` | string | Contact name text used by the search, when present. |
| `source.searchContext.contactZip` | string | Contact ZIP code used by the search, when present. |
| `source.searchContext.minProjectCost` | number | Lowest reported project cost used by the search, when present. |
| `source.searchContext.maxProjectCost` | number | Highest reported project cost used by the search, when present. |
| `source.searchContext.permitId` | string | Exact permit ID used by the lookup, when present. |
| `source.retrievedAt` | date-time string | Time when the source record was retrieved. |

**Successful current-beta search row**

This complete row is from the successful run for the input shown above:

```json
{
  "permitId": "B200481856",
  "status": "ACTIVE",
  "milestone": "INSPECTION ELIGIBLE",
  "classification": {
    "permitType": "PERMIT – EXPRESS PERMIT PROGRAM",
    "reviewType": "EXPRESS PERMIT PROGRAM",
    "workType": "Reroofing"
  },
  "timing": {
    "applicationDate": "2026-08-06",
    "issueDate": "2026-08-06",
    "processingDurationDays": 0
  },
  "property": {
    "address": {
      "full": "3517 N KILPATRICK AVE",
      "streetNumber": "3517",
      "streetDirection": "N",
      "streetName": "KILPATRICK AVE"
    },
    "ward": 30,
    "communityArea": 15,
    "propertyIdentifiers": [
      {
        "type": "PIN",
        "value": "1322302010"
      }
    ],
    "censusArea": {
      "tract": "151000"
    },
    "coordinates": {
      "latitude": 41.94523804406035,
      "longitude": -87.74380597065314
    }
  },
  "project": {
    "description": "SCOPE: ROOF REPLACEMENT. AREA: 2288 SQ. FT. ROOF COVERING: ASPHALT SHINGLES. LOCATION: ROOFING. IL ROOFING CONTRACTOR LICENSE: 104.01959.",
    "reportedCost": 10000
  },
  "fees": {
    "total": {
      "amount": 450,
      "paid": 450,
      "unpaid": 0,
      "waived": 0
    },
    "building": {
      "amount": 450,
      "paid": 450,
      "unpaid": 0,
      "waived": 0
    },
    "zoning": {
      "amount": 0,
      "paid": 0,
      "unpaid": 0,
      "waived": 0
    },
    "other": {
      "amount": 0,
      "paid": 0,
      "unpaid": 0,
      "waived": 0
    }
  },
  "contacts": [
    {
      "role": "OWNER",
      "name": "SILVA JOSÉ",
      "mailingLocation": {
        "city": "CHICAGO",
        "state": "IL",
        "zipCode": "60641"
      }
    },
    {
      "role": "WEB APPLICANT",
      "name": "ALTAMIRANDA SANTIAGO",
      "mailingLocation": {
        "city": "CHICAGO",
        "state": "IL",
        "zipCode": "60007"
      }
    },
    {
      "role": "GENERAL CONTRACTOR",
      "name": "SLOG GROUP LLC",
      "mailingLocation": {
        "city": "ELK GROVE VILLAGE",
        "state": "IL",
        "zipCode": "60007"
      }
    }
  ],
  "source": {
    "provider": "City of Chicago",
    "dataset": "Building Permits",
    "datasetUrl": "https://data.cityofchicago.org/d/ydr8-5enu",
    "recordId": "N2934356",
    "recordUrl": "https://data.cityofchicago.org/resource/ydr8-5enu.json?%24where=id+%3D+%27N2934356%27",
    "searchContext": {
      "target": "search",
      "projectSearch": "roof"
    },
    "retrievedAt": "2026-08-07T20:45:14.352Z"
  }
}
```

#### 💳 Pricing

**How billing works**

This Actor uses pay-per-event pricing. One billing event is tied to each matching building permit saved to the dataset. Set `maxItems` when you want an upper bound on saved permits and their permit events. Check the current event price on the Store page before you run it.

#### 🔌 Integrations

**Dataset and API**

Open the default dataset link after a run to review the saved rows. Standard Apify dataset and API access lets you consume the permit fields and source links in your own workflow.

**Video walkthrough**

https://www.youtube.com/watch?v=bNACk1\_S\_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### What source does this Actor use?

It searches the official City of Chicago Building Permits dataset. Each row keeps the dataset URL and, when available, a direct source record URL for review.

##### Can I search by address or permit ID?

Yes. Use `address` or `street` for a search, or choose `target: "permit"` and enter one exact `permitId`.

##### What does leaving Maximum permits empty do?

It returns all available results until the source is exhausted. Set `maxItems` when you want a smaller upper bound.

##### Can I request only new permits?

Yes. In a search run, set `searchMode` to `newSincePreviousRun` to request permits newly available since the prior run. Use `all` for every permit that matches the current filters.

##### Does this cover Cook County or other cities?

No. This Actor searches the City of Chicago Building Permits dataset only. It does not claim coverage for Cook County, other municipalities, or other source datasets.

##### Are phone numbers or email addresses included?

No. The Actor returns contact roles, names, and mailing locality when Chicago publishes them. It does not add phone, email, or other third-party contact enrichment.

##### What if Chicago does not publish a field?

That field can be omitted from the row. The Actor keeps source-published values and does not invent missing project, property, fee, contact, or coordinate data.

##### What happens if no permit matches?

The dataset may contain no saved permit rows. Broaden a filter, check the date range, or try an exact permit ID when you need to check one known record.

##### Can one run hold several independent searches?

No. One run represents one configured Chicago search or one exact permit lookup. Values inside a filter list are part of that one query.

### 📝 Changelog

**0.0: Initial release**

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~chicago-building-permits/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- [U.S. Census Geocoder](https://apify.com/maximedupre/us-census-geocoder) — match permit addresses and coordinates to Census geography for mapping and area analysis.
- [PropertyShark Scraper](https://apify.com/maximedupre/propertyshark) — add public property, building, and sale-history context to a real estate review.
- [Realtor Scraper](https://apify.com/maximedupre/realtor-scraper) — compare public for-sale, rental, sold, or pending listings for a property search.
- [Chicago Building Permits & Contractor Leads Scraper](https://apify.com/automation-lab/chicago-building-permits-scraper) — compare another Chicago permit search with project and source-published contact details.
- [Chicago Building Permits Scraper (Contractors, Owners)](https://apify.com/scrapers_lat/chicago-building-permits-scraper) — compare another Chicago permit collection with owner, contractor, cost, fee, and address fields.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `target` (type: `string`):

Choose one kind of Chicago permit lookup for this run.

## `searchMode` (type: `string`):

Choose all matching permits or only permits newly available since the prior run. If omitted, this uses all matching permits.

## `projectSearch` (type: `string`):

Optional text to find in the published project description.

## `issueDateFrom` (type: `string`):

Optional first issue date to include.

## `issueDateTo` (type: `string`):

Optional last issue date to include.

## `permitStatuses` (type: `array`):

Optional list of published permit status values to include. Leave empty to include every status.

## `permitTypes` (type: `array`):

Optional list of published permit type values to include. Leave empty to include all permit types.

## `reviewTypes` (type: `array`):

Optional list of published review type values to include. Leave empty to include all review types.

## `workTypes` (type: `array`):

Optional list of published work type values to include. Leave empty to include all work types.

## `wards` (type: `array`):

Optional list of Chicago ward numbers to include. Leave empty to include all wards.

## `communityAreas` (type: `array`):

Optional list of Chicago community area numbers to include. Leave empty to include all community areas.

## `street` (type: `string`):

Optional street text to match in the published job address.

## `address` (type: `string`):

Optional full address text to match in the published job address.

## `owner` (type: `string`):

Optional owner name text to match in published permit contacts.

## `applicant` (type: `string`):

Optional applicant name text to match in published permit contacts.

## `contractor` (type: `string`):

Optional contractor name text to match in published permit contacts.

## `contactName` (type: `string`):

Optional name text to match in any published contact entry.

## `contactZip` (type: `string`):

Optional ZIP code to match in published contact entries.

## `minProjectCost` (type: `number`):

Optional lowest reported project cost to include.

## `maxProjectCost` (type: `number`):

Optional highest reported project cost to include.

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

Optional stop after this many matching permits. Leave empty to return all available results until the source is exhausted.

## `permitId` (type: `string`):

Required when Target is Look up a permit. Enter one exact published Chicago permit ID.

## Actor input object example

```json
{
  "target": "search",
  "searchMode": "all",
  "projectSearch": "roof",
  "maxItems": 5
}
```

# Actor output Schema

## `dataset` (type: `string`):

The default dataset with successful Chicago building permit results.

# 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 = {
    "target": "search",
    "projectSearch": "roof",
    "maxItems": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/chicago-building-permits").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 = {
    "target": "search",
    "projectSearch": "roof",
    "maxItems": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/chicago-building-permits").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 '{
  "target": "search",
  "projectSearch": "roof",
  "maxItems": 5
}' |
apify call maximedupre/chicago-building-permits --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maximedupre/chicago-building-permits"
        }
    }
}

```

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/chGYSD5xpjCEaZKvw/builds/RBA4cYxg4gtiwfgUM/openapi.json
