# Airbnb & Booking Toronto STR Registration Checker (`nice_dev/airbnb-toronto-license-checker`) Actor

Check the short-term rental registration number (STR-YYMM-XXXXXX) of Airbnb listings and Booking.com properties in Toronto against the City's open register: verdict, exact registered address with the unit number, property type, ward — plus listing and host details.

- **URL**: https://apify.com/nice_dev/airbnb-toronto-license-checker.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** Travel, Real estate, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### 🏠 What is Airbnb & Booking Toronto STR Registration Checker?

**Airbnb & Booking Toronto STR Registration Checker** checks the **short-term rental registration number** (`STR-YYMM-XXXXXX`) that each Airbnb listing and each Booking.com property in Toronto displays against the **City of Toronto's open register**, and tells you whether it is **valid, never issued, not an active registration, or the number of another property**. Each result also gives what the register knows — the **exact registered address with the unit number** (which Airbnb hides), the property type, the ward, the month of issue — the **official point of that address on the City's map** with its distance to the listing, and the listing's own details (host, capacity, rating, amenities, price).

Type a **place** (`Toronto, Ontario, Canada`) and choose where to search it — **Airbnb, Booking.com or both** — draw a **map area**, paste **Airbnb URLs**, **listing IDs** or **Booking.com URLs**, give **registration numbers** alone — or list the **register itself, ward by ward** — click **Start**, and download the results in JSON, CSV or Excel. No login, nothing to set up. Built for the City and its inspectors, condo boards and property managers, neighbours' associations, insurers, investors and journalists.

### 📋 What data can you extract from Airbnb, Booking.com and Toronto's short-term rental register?

One item per listing checked (or per registration number given alone, or per record of the register), 133 fields:

| Category | What you get |
| --- | --- |
| ✅ **Verdict** | valid, never issued, not in the register, other property, unknown format, no number, exempt claimed, outside Toronto… with the reasons and one plain sentence |
| 🪪 **Registration number** | the number shown on the listing and its register spelling, the other numbers shown (a building on Booking.com, a neighbouring city's licence), the exemption claimed, other listings of the run showing the same number — on Airbnb or on Booking.com |
| 🏛️ **Official register** | the exact registered address with its unit (`251 Jarvis St, Unit 315`), postal code (3 characters), property type, ward, month of issue, the other numbers of the same unit, the registrations at the same address, a link to the record, the date of the register |
| 📍 **On the map** | the official point of the registered address (the City's address points) and its distance to the listing's point on Airbnb |
| 🏠 **Listing** | title, type of place, city, position, whether Airbnb pins it exactly, guests, bedrooms, beds, bathrooms, rating and sub-ratings, badges, highlights, house rules and the host's additional rules, where you'll sleep, description, amenities, photos; on Booking.com: street address, every licence number and sentence shown, professional or private host |
| 👤 **Host** | name, profile link, business or individual, verified, years hosting, response rate and time, rating, reviews, co-hosts, how many listings they manage |
| 📅 **Availability calendar** (option) | nights open and nights booked or blocked over 12 months, per month and per day, and whether the listing is open more than the 180 nights a year Toronto allows for an entire home |
| 🎯 **Risk score** (option) | a score from 0 to 100 per listing and the short codes of the rules behind it: the verdict, a number shown twice, a registered address far from the listing, a host with several listings, a calendar open past 180 nights… |
| 🏢 **Professional host contact** (option) | business email and phone of professional Airbnb hosts, from publicly available sources |
| ☎️ **Business contact** (option) | the business e-mail and phone Booking.com shows for a professional host |
| 📷 **Photos** (option) | the first photos of each listing kept in the run's storage, with their public links, their SHA-256 and the time of the download — a dated copy; the photo links stay free |
| ⚡ **Cards only** (option) | the card of each Airbnb search result — link, title, type, price, rating, position, bedrooms — without opening the listing, so without a number or a verdict |
| 🏘️ **Comparables** (option) | the nearest Airbnb listings of the same type and size around each Airbnb listing, with their price per night, rating and distance, and their median price |
| 💰 **Revenue estimate** (option) | an estimate of the nights blocked in the calendar, the revenue they would make at the price per night searched, and the share of the calendar blocked |
| 🏷️ **AI labels** (option) | five yes / no labels read in the description of an Airbnb listing — managed by a company, self check-in, monthly stays, host not living there, licence mentioned — with their scores |
| 💵 **Price** | total price of the stay, price per night, price breakdown, dates (from the search results) |

Every field, with an example, is listed in the **Output** section below.

### ✅ Why use Airbnb & Booking Toronto STR Registration Checker?

- 🏛️ **The City's own register, not a format check**: each number is looked up in the City of Toronto's open data (Short Term Rentals Registration), downloaded fresh at each run — 8,700+ active registrations.
- 📍 **The exact address Airbnb hides**: the registered street address with its unit number, placed on the City's own address map — not an address guessed from Airbnb's blurred point.
- 🔎 **Finds what a glance cannot**: numbers of a month the City never issued in, numbers that are no longer active (expired or cancelled), numbers registered far from the listing, the same number on several listings, the same flat registered twice.
- 🗂️ **Eight ways in, in one run**: places (on Airbnb, Booking.com or both), map areas, search URLs, listing URLs, listing IDs, Booking.com URLs, registration numbers alone — and the register itself, ward by ward.
- 🏨 **Airbnb and Booking.com side by side**: the same register and the same verdicts for both sites; a number shown by listings of both sites is flagged in `numberSharedWith`.
- 🗺️ **Whole city**: Airbnb shows 270 listings per search; a full area is cut into smaller ones automatically to reach the others. Listings of neighbouring cities (Mississauga, Vaughan, Markham) are told apart by their point on the map.
- 🔔 **Monitoring built in**: tick **Only new listings**, schedule the Actor, and each run returns (and charges) only the listings it has never delivered before.
- 🔌 API, scheduling, integrations (Make, Zapier, n8n, Google Sheets…) and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to check Airbnb registration numbers in Toronto

1. Create a free Apify account.
2. Open **Airbnb & Booking Toronto STR Registration Checker** and type a **Place** (e.g. `Toronto, Ontario, Canada`).
3. Choose the **Sites searched** for your places: Airbnb (default), Booking.com, or both.
4. Or paste **Airbnb URLs** (search results or single listings), **listing IDs**, **Booking.com URLs**, **map areas**, **registration numbers to check** without any listing, or pick **wards of the register**.
5. Set **Max results** (100 by default, 0 = no limit) — and keep only the suspicious listings with **Keep only these verdicts** — then click **Start**.
6. Download the dataset in JSON, CSV, Excel or via API.

### 💰 How much does it cost to check Airbnb registration numbers?

This Actor uses **pay per event** pricing: a price per result — one for an **Airbnb listing** checked (`airbnb-listing`), one for a **Booking.com property** checked (`booking-listing`), one for a **registration number** given alone or a **record of the register** (`register-record`), one for a **card alone** (`listing-card`, the only price of a run with **Cards only (fast)**), one for a **photo downloaded** (`photo-download`, one per photo delivered, charged only once the **Pricing** tab lists it), one for a **business contact** (`business-contact`, one per Booking.com property whose row carries an e-mail or a phone, charged only once the **Pricing** tab lists it), one for a **professional host contact** (`pro-host-contact`, one per Airbnb listing whose row carries an e-mail or a phone of the host's company, charged only once the **Pricing** tab lists it) — a small fee per run start, a fee for the **official address** of a listing found in the register (`register-match`, on top of its result, charged only once the **Pricing** tab lists it), a fee per **host profile** (**Host's listing count**, one per host whose profile reaches your results, not per listing), a fee per **availability calendar** (`listing-calendar`, charged only once the **Pricing** tab lists it), a fee per **risk score** (`risk-score`, one per listing whose row carries a score, charged only once the **Pricing** tab lists it), a fee per listing given its **AI labels** (`ai-labels`, charged only once the **Pricing** tab lists it), a fee per listing given its **comparables** (`comparables`, charged only once the **Pricing** tab lists it), a fee per listing given its **revenue estimate** (`revenue-estimate`, charged only once the **Pricing** tab lists it, on top of the calendar it reads) and a lower fee for each listing a filter of the Actor drops — `filter-check` when the search results are enough to drop it (minimum rating, host type, excluded words), `detail-filter-check` when its page and the register had to be read (verdicts, wards, property types; also a number or a register record these filters drop). A listing you keep costs its normal price: filtering never costs more than taking everything. With a maximum cost per run, the listings already kept are paid first: the filter checks only spend what they leave. The prices are shown on the **Pricing** tab of this page. Platform usage (compute, proxy) is included in the price.

### ⚙️ Input

A place, only the listings whose number does not match the register:

```json
{
    "location": "Toronto, Ontario, Canada",
    "maxItems": 200,
    "onlyVerdicts": ["never_issued", "not_in_register", "other_property", "unknown_format", "no_number"]
}
```

Several places and a map area, a cap per search, only the listings not delivered before:

```json
{
    "locations": ["Scarborough, Toronto", "Etobicoke, Toronto"],
    "boundingBoxes": ["43.63, -79.41, 43.66, -79.37"],
    "maxItems": 300,
    "maxItemsPerQuery": 100,
    "onlyNew": true,
    "memoryName": "toronto-weekly"
}
```

Both sites for the same places, Booking.com apartments and holiday homes only:

```json
{
    "locations": ["Toronto", "North York, Toronto"],
    "sources": ["airbnb", "booking"],
    "bookingPropertyTypes": ["apartment", "holiday_home"],
    "maxItems": 400,
    "maxItemsPerQuery": 100
}
```

Your own URLs, listing IDs, Booking.com URLs, and registration numbers alone:

```json
{
    "startUrls": [
        { "url": "https://www.airbnb.com/s/Toronto--Ontario--Canada/homes?adults=2" },
        { "url": "https://www.airbnb.ca/rooms/1776209588793137546" }
    ],
    "listingIds": ["1756004805350768453"],
    "bookingUrls": ["https://www.booking.com/hotel/ca/urban-nest-toronto.html"],
    "licenseNumbers": ["STR-2608-JGXPVZ", "STR-2301-GHRRVS", "str 2607 grwhvt"],
    "maxItems": 500
}
```

The register itself: the condominiums registered since January 2026 in two downtown wards, each placed on the map:

```json
{
    "registerWards": ["spadina-fort-york", "toronto-centre"],
    "registeredAfter": "2026-01-01",
    "registerPropertyTypes": ["condominium"],
    "maxItems": 1000
}
```

| Field | Notes |
| --- | --- |
| `startUrls` | Airbnb search results pages (filters kept, pagination and map splitting automatic) or single listing pages, any Airbnb domain. |
| `listingIds` | Airbnb listing IDs alone (the digits after `/rooms/`). Checked in the order given and before any search: with `maxItems`, the first ones are the ones saved. |
| `bookingUrls` | Booking.com property pages (e.g. `https://www.booking.com/hotel/ca/urban-nest-toronto.html`, any language version), checked in the order given, like listing IDs. |
| `location`, `locations` | Places as typed in the site's search box (e.g. `Toronto, Ontario, Canada`, `Scarborough, Toronto`); one search each and per site. |
| `sources` | Sites the places are searched on: `airbnb` (default), `booking`, or both. Airbnb URLs, IDs and map areas always go to Airbnb, Booking.com URLs to Booking.com. |
| `boundingBoxes` | Map rectangles `south, west, north, east` (e.g. `43.63, -79.41, 43.66, -79.37`): the surest way to cover a whole area. |
| `licenseNumbers` | Registration numbers checked against the register without any listing (e.g. `STR-2608-JGXPVZ`; spaces, lower case and missing dashes are accepted). One result per registration: two spellings of the same number are checked once. |
| `registerWards` | Records of the register itself for these wards (`spadina-fort-york`, `toronto-centre`… or `all`): address with unit, property type, month of issue, point on the map — no Airbnb search. Newest first. |
| `registeredAfter` | For `registerWards`: registrations issued in this month or later (e.g. `2026-01-01`: January 2026 onward; the month is read in the number). |
| `registerPropertyTypes` | Only these property types of the register: `condominium`, `house`, `apartment`, `townhouse`, `multiplex` (register records and listings; a listing not found in the register has no type and is dropped). |
| `maxItems` | Stop after this many results for the whole run (`0` = unlimited). |
| `maxItemsPerQuery` | Cap for EACH search (place and site, map area or search URL) and each ward named in `registerWards` (with all, one cap for the whole register, newest first). 0 = no per-search cap — except when the run searches both sites: `maxItems` (less the numbers checked alone) is then shared evenly between the searches. |
| `splitMap` | Cut a full Airbnb search (270 listings) into smaller map areas, and read a Booking.com search over 1,000 properties district by district, to reach the others (default on). |
| `checkIn`, `checkOut`, `adults`, `children`, `infants`, `pets` | Travel dates and guests sent to Airbnb's search (e.g. `2027-07-12`, today or later in Toronto); the price of the stay then follows them, and `checkIn` / `checkOut` of each listing are these dates. |
| `currency`, `priceMin`, `priceMax` | Currency of the prices (`CAD` by default, also `USD`, `EUR`, `GBP`; a pasted search URL keeps its own currency, and each row names it) and price per night bounds. |
| `roomTypes` | Airbnb's type of place: `entire_home`, `private_room`, `shared_room`, `hotel_room`. |
| `propertyTypes` | Airbnb's property type: `house`, `apartment`, `guesthouse`, `hotel`. |
| `minBedrooms`, `minBeds`, `minBathrooms`, `superhostOnly` | Airbnb's own filters: at least this many rooms, Superhosts only. |
| `bookingPropertyTypes` | Kinds of Booking.com properties searched: `apartment`, `holiday_home`, `villa` (default), also `chalet`, `country_house`, `farm_stay`, `guesthouse`, `homestay`, `bed_and_breakfast`, `condo_hotel`, `hotel`, `hostel`. |
| `onlyVerdicts` | Keep only the listings with these verdicts (e.g. `never_issued`, `not_in_register`, `other_property`). |
| `wards` | Keep only the listings of these wards (`spadina-fort-york`, `toronto-centre`…; `other` = outside Toronto; a listing whose ward is unknown is dropped). |
| `hostType` | `any`, `business` or `individual` hosts (Booking.com: professional or private, as the host declared). |
| `minRating`, `excludeKeywords` | Minimum rating out of 5 (Booking.com scores out of 10 are halved); words that drop a listing whose title contains them. |
| `gpsToleranceKm` | Distance above which the registered address is another property (`0.5` km by default: Airbnb blurs positions by about 150 m). |
| `includeHostProfile` | Read each Airbnb host's profile once for the number of listings they manage (default off: charged per host profile). |
| `includeCalendar` | Read each Airbnb listing's availability calendar, 12 months (default off: charged per listing with its calendar). |
| `includeRiskScore` | Give each listing a risk score from 0 to 100 and its reasons (default off: charged per listing whose row carries a score). |
| `includeProHostContact` | Add the business e-mail and phone of professional Airbnb hosts, from publicly available sources (default off: charged per listing given a contact; never a private person). |
| `includeBusinessContact` | Add the business e-mail and phone Booking.com shows for a professional host (default off: charged per property given a contact; Airbnb and the register give none). |
| `downloadPhotos`, `maxPhotosPerListing` | Download the first photos of each listing into the run's storage and give their links, hashes and date (default off: charged per photo delivered; the second field is the number of photos per listing, 5 by default). |
| `cardsOnly` | Deliver only the card of each Airbnb search result and open no listing (default off: no number, no verdict; a price per card, nothing else charged). |
| `includeComparables`, `maxComparablesPerListing` | Add the neighbouring Airbnb listings of each Airbnb listing and their median price per night (default off: charged per listing given comparables; the second field is the most kept per listing, 10 by default). |
| `includeRevenueEstimate` | Estimate each Airbnb listing's revenue from its calendar and its price per night (default off: needs `checkIn` and `checkOut`, reads the calendar too; charged per listing given an estimate). |
| `includeAiLabels` | Label the description of each Airbnb listing with five AI labels (default off: charged per listing given its labels; needs 2 GB of memory, otherwise skipped and not charged). |
| `onlyNew`, `memoryName`, `resetState` | Monitoring: only the listings never delivered under this memory name; `resetState` forgets the memory. |
| Advanced | `proxyConfiguration` (Apify proxy by default, included in the price; the residential proxy is not available), `maxConcurrency`, `maxRequestsPerMinute`, `minRequestIntervalMs`, `maxRequestRetries`, `debugLog`. |

### 📦 Output

A real result (shortened: some fields and list entries left out):

```json
{
    "id": "1776209588793137546",
    "source": "airbnb_listing",
    "url": "https://www.airbnb.com/rooms/1776209588793137546",
    "title": "Spacious 3-bedroom in Heart of Downtown Toronto",
    "verdict": "valid",
    "verdictReasons": [],
    "verdictNote": "STR-2608-JGXPVZ is registered at 251 Jarvis St, Unit 315, Toronto, ON M5B.",
    "isSuspicious": false,
    "region": "toronto-centre",
    "registrationText": "STR-2608-JGXPVZ",
    "licenseNumber": "STR-2608-JGXPVZ",
    "licenseNumberNormalized": "STR-2608-JGXPVZ",
    "otherLicenseNumbers": [],
    "licensePhrases": [],
    "numberSharedWith": [],
    "registerFound": true,
    "registerNumber": "STR-2608-JGXPVZ",
    "registerAddress": "251 Jarvis St, Unit 315, Toronto, ON M5B",
    "registerStreetAddress": "251 Jarvis St",
    "registerUnit": "315",
    "registerPostalCode": "M5B",
    "registerPropertyType": "Condominium",
    "registerWardNumber": 13,
    "registerWardName": "Toronto Centre",
    "registerIssuedMonth": "2026-08",
    "registerLatitude": 43.6573245563455,
    "registerLongitude": -79.3743321100694,
    "distanceKm": 0.02,
    "registerSameUnitNumbers": [],
    "registerNumbersAtAddress": 4,
    "registerSource": "City of Toronto Open Data — Short Term Rentals Registration",
    "registerUpdatedAt": "2026-09-27",
    "registerAttribution": "Contains information licensed under the Open Government Licence – Toronto.",
    "propertyType": "Entire apartment",
    "roomType": "Entire home/apt",
    "city": "Toronto",
    "latitude": 43.6574,
    "longitude": -79.3745,
    "isExactLocation": true,
    "personCapacity": 7,
    "bedrooms": 3,
    "rating": 5,
    "reviewsCount": 2,
    "badges": [],
    "highlights": ["Self check-in"],
    "houseRules": ["Check-in after 16:00", "Checkout before 11:00", "7 guests maximum"],
    "sleepingArrangements": ["Bedroom 1: 1 queen bed", "Bedroom 2: 1 queen bed"],
    "amenities": ["Free washer – In unit", "Dishwasher"],
    "images": [
        "https://a0.muscache.com/im/pictures/hosting/Hosting-1776209588793137546/original/ec361e41-ffc7-419c-9694-0f72e9f7d361.jpeg"
    ],
    "hostName": "Allen",
    "hostType": "individual",
    "coHosts": ["Will"],
    "hostListingIds": [],
    "calendarMonths": [],
    "calendarDays": [],
    "priceDetails": [],
    "riskReasons": [],
    "riskChecksSkipped": [],
    "comparables": [],
    "photoFiles": [],
    "photoSha256": [],
    "proHostEmails": [],
    "proHostPhones": [],
    "scrapedAt": "2026-09-28T08:14:05.512Z"
}
```

A Booking.com property (shortened: the Airbnb-only fields are `null` or empty):

```json
{
    "id": "booking-16731727",
    "source": "booking_listing",
    "url": "https://www.booking.com/hotel/ca/urban-nest-toronto.html",
    "title": "Urban Nest",
    "verdict": "valid",
    "verdictReasons": [],
    "verdictNote": "STR-2509-HZYFBZ is registered at 270 Wellington St W, Unit 1102, Toronto, ON M5V.",
    "isSuspicious": false,
    "region": "spadina-fort-york",
    "registrationText": "License number: STR-2509-HZYFBZ",
    "licenseNumber": "STR-2509-HZYFBZ",
    "licenseNumberNormalized": "STR-2509-HZYFBZ",
    "otherLicenseNumbers": [],
    "licensePhrases": ["License number: STR-2509-HZYFBZ"],
    "numberSharedWith": [],
    "registerFound": true,
    "registerNumber": "STR-2509-HZYFBZ",
    "registerAddress": "270 Wellington St W, Unit 1102, Toronto, ON M5V",
    "registerUnit": "1102",
    "registerPropertyType": "Condominium",
    "registerWardName": "Spadina-Fort York",
    "registerIssuedMonth": "2025-09",
    "distanceKm": 0.1,
    "registerNumbersAtAddress": 2,
    "propertyType": "Apartment",
    "city": "Toronto",
    "address": "270 Wellington St W",
    "rating": 3.4,
    "reviewsCount": 18,
    "hostType": "individual",
    "isTrader": false,
    "bookingId": "16731727",
    "bookingPageName": "urban-nest-toronto",
    "searchUrl": "https://www.booking.com/searchresults.html?ss=Toronto&nflt=ht_id%3D201%3Bht_id%3D220%3Bht_id%3D213&page=1",
    "scrapedAt": "2026-09-28T08:14:05.512Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel. The **Overview**, **Register record** and **Hosts and business details** views of the Output tab show the main columns.

#### All 133 fields

| Fields | What you get |
| --- | --- |
| `id`, `source`, `url`, `title` | **Result**: Airbnb id, `booking-` + the Booking.com property id, the number given alone, or `register-` + the number of a register record; `airbnb_listing` / `booking_listing` / `license_number` / `register_list`; link; title (for a number or a record: its registered address) |
| `verdict`, `verdictReasons`, `verdictNote`, `isSuspicious`, `region` | **Verdict**: see the table of verdicts below; the reasons found; one sentence; the ward (`other` = outside Toronto) |
| `registrationText`, `licenseNumber`, `licenseNumberNormalized`, `otherLicenseNumbers`, `exemption`, `licensePhrases`, `numberSharedWith` | **Registration number**: the block as shown, the number as written and in the register's spelling (`STR-YYMM-XXXXXX`, the key of the check), the other numbers shown, the exemption claimed, the Booking.com sentences, the other listings of the run with the same number |
| `registerFound`, `registerNumber`, `registerAddress`, `registerStreetAddress`, `registerUnit`, `registerPostalCode` | **Register**: found or not, the number, the full address, the street address, the unit (`315`, `Upper Unit`, `BSMT`), the postal code's 3 characters |
| `registerPropertyType`, `registerWardNumber`, `registerWardName`, `registerIssuedMonth` | property type as registered, ward, month of issue read in the number |
| `registerLatitude`, `registerLongitude`, `distanceKm` | the official point of the registered address (the City's address points) and its distance to the listing |
| `registerSameUnitNumbers`, `registerNumbersAtAddress` | other numbers registered at the same address and unit; registrations at the same address, all units |
| `registerUrl`, `registerSource`, `registerUpdatedAt`, `registerCheckedAt`, `registerAttribution` | link to the record in the City's open data, source, date of the register, time of its download, the attribution the City's licence asks for |
| `propertyType`, `roomType`, `city`, `address`, `latitude`, `longitude`, `isExactLocation`, `locationText`, `locationDescription` | **Listing**: `Entire apartment`, `Entire home/apt`, city, street address (Booking.com), position (blurred by Airbnb), whether Airbnb pins the exact place, area, the host's text about the neighbourhood |
| `personCapacity`, `bedrooms`, `beds`, `bathrooms`, `sleepingArrangements` | guests, rooms, where you'll sleep |
| `rating`, `reviewsCount`, `ratingAccuracy`, `ratingCheckin`, `ratingCleanliness`, `ratingCommunication`, `ratingLocation`, `ratingValue` | ratings out of 5 (Booking.com's score out of 10, halved) and number of reviews |
| `isSuperhost`, `isGuestFavorite`, `isNewListing`, `homeTier`, `badges`, `highlights` | Superhost, Guest favourite, new listing, tier, search badges, highlights |
| `description`, `descriptionLanguage`, `houseRules`, `houseRulesAdditional`, `amenities`, `images` | full description, its language, house rules, the host's additional rules, amenities, photo links |
| `hostId`, `hostName`, `hostUrl`, `hostType`, `isTrader`, `hostIsVerified`, `hostYearsHosting` | **Host**: id, name, profile link, `business` / `individual`, professional host on Booking.com, verified, years hosting |
| `hostResponseRate`, `hostResponseTime`, `hostRating`, `hostReviewsCount`, `hostAbout`, `hostPictureUrl`, `hostLocation`, `coHosts` | response rate and time, rating and reviews over all their listings, presentation, photo, where they live, co-hosts |
| `hostListingsCount`, `hostListingIds` | how many listings they manage, the IDs their profile shows (10 at most) |
| `calendarFrom`, `calendarTo`, `calendarNightsOpen`, `calendarNightsBlocked`, `calendarOver180Nights`, `calendarMinNights`, `calendarMonths`, `calendarDays` | **Availability calendar** (option): the 12 months read, nights open and not, more than 180 open nights, minimum stay, by month and by day |
| `businessName`, `businessRegistry`, `businessTaxId`, `businessEmail`, `businessPhone`, `businessAddress` | **Business host details**, when the host shows them; the e-mail and the phone of a Booking.com professional host are the **Business contact** option |
| `price`, `currency`, `pricePerNight`, `priceText`, `priceDetails`, `priceNights`, `checkIn`, `checkOut` | **Price** from the search results: total, currency, per night, as shown, breakdown, nights, dates |
| `bookingId`, `bookingPageName` | **Booking.com**: the property id and the name of its page |
| `riskScore`, `riskReasons`, `riskChecksSkipped` | **Risk score** (option): 0 to 100, the codes of the rules that gave it, the rules that could not play for lack of data |
| `photoFiles`, `photoSha256`, `photosDownloadedAt` | **Photos** (option): the public links of the photos kept in the run's storage, their SHA-256, the time of the download |
| `proHostCompany`, `proHostWebsite`, `proHostEmails`, `proHostPhones`, `proHostContactSourceUrl`, `proHostContactConfidence` | **Professional host contact** (option): the company of a professional Airbnb host, its website, its business e-mails and phones, the page they come from, how sure the contact is |
| `comparables`, `comparablesMedianPrice` | **Comparables** (option): the nearest Airbnb listings of the same type within one bedroom (id, link, price per night, currency, bedrooms, rating, distance) and their median price per night |
| `estimatedNightsBooked12m`, `estimatedRevenue12m`, `estimatedOccupancy`, `revenueCurrency` | **Revenue estimate** (option): nights blocked in the calendar, their revenue at the price per night searched, the share of the calendar blocked, the currency |
| `aiLabels`, `aiLabelScores` | **AI labels** (option): five yes / no labels read in the description and the confidence behind each |
| `searchUrl`, `scrapedAt` | the search the listing was found by, time of the check |

### 💡 Tips

#### What each verdict means

When a listing has several problems, its verdict is the highest one in this table, and `verdictReasons` lists them all.

| Verdict | Meaning |
| --- | --- |
| `valid` | The number is an active registration of the register, and the registered address is near the listing's point (when both are known: otherwise `verdictNote` says what could not be checked). |
| `never_issued` | The number carries a month the City never issued in: month 00 or over 12, before the register opened (September 2020), or still to come. An invented number. |
| `not_in_register` | Well-formed but not an active registration: expired, cancelled, or never registered (the open register lists active registrations only, and does not say which). |
| `other_property` | The registered address is farther from the listing than **Distance tolerance**: the number of another home. |
| `unknown_format` | The text shown is not a City of Toronto registration number (another city's licence, free text). |
| `no_number` | The listing shows no registration number. |
| `exempt_claimed` | The listing says it is exempt (a hotel; on Booking.com, that it needs no short-term rental licence). |
| `region_not_covered` | In another country, or outside the City of Toronto (Mississauga, Vaughan, Markham…) without a Toronto number: given, not checked (a Toronto number shown just outside the City is checked). |
| `register_unavailable` | The register could not be downloaded in this run (or what came back was not the register). |

#### How to cover the whole city

Airbnb shows at most 270 listings per search. With **Split full areas** on (default), a full search is cut into 4 smaller map areas, again and again, until each shows everything. A place's area is Airbnb's own map of it: add **Map areas** (`boundingBoxes`) to be sure, and check the ward of each result (`region`): a listing outside the City's 25 wards is given `region_not_covered`.

Booking.com shows at most 1,000 properties per search. With **Split full areas** on, a bigger search is also read district by district.

#### Airbnb and Booking.com

Tick both sites in **Sites searched** to check the same places on both: every place gives one Airbnb search and one Booking.com search, each with its own **Max listings per search** — left at 0, **Max results** (less the numbers checked alone) is shared evenly between them. A Booking.com property goes through the same register and verdicts as an Airbnb listing:

- **Several numbers**: a building of flats may show one registration per flat. The first is checked; all are in `otherLicenseNumbers`, and `verdictNote` says so.
- **No licence needed**: a property that says it needs no short-term rental licence gets `exempt_claimed`.
- **No host profile**: the host's name and profile are Airbnb's; Booking.com gives only whether the host is a professional (`isTrader`).

In September 2026, all 30 Booking.com properties read in Toronto showed a registration number, and all 33 numbers were in the register; 68 of 80 Airbnb listings showed one, all in the register.

#### Risk score (option)

Tick **Risk score (0-100)** to get, for each Airbnb listing and Booking.com property, one number from 0 (nothing wrong) to 100 and the codes of the rules behind it. The rules add their weights up, 100 at most, the verdict first:

| Rule (code in `riskReasons`) | Points |
| --- | --- |
| Verdict `never_issued` (`verdict_never_issued`) | 80 |
| Verdict `not_in_register` (`verdict_not_in_register`) | 65 |
| Verdict `other_property` (`verdict_other_property`) | 55 |
| Verdict `no_number` (`verdict_no_number`) | 50 |
| Verdict `unknown_format` (`verdict_unknown_format`) | 40 |
| Verdict `exempt_claimed` (`verdict_exempt_claimed`) | 20 |
| Verdict `region_not_covered` (`verdict_region_not_covered`) | 10 |
| The same number shown by another listing of the run (`number_shared`) | 20 |
| The registered address is more than 0.3 km from the listing (`distance_over_300m`) | 10 |
| An entire home (`entire_home`) | 5 |
| The listing says an apartment where the register says a house, or the other way round (`property_type_mismatch`) | 10 |
| The host manages 3 listings or more (`host_3_or_more_listings`) / 2 listings (`host_2_listings`) | 25 / 10 |
| Open more than 180 nights (`over_180_nights`) | 25 |
| A professional host (`trader_host`) | 20 |

The host's listings count only with **Host's listing count** ticked, the 180 nights only with **Availability calendar** ticked: a rule whose data is not read is skipped, named in `riskChecksSkipped`, and never counted as a risk. A property type or a distance the register cannot give (number not found) is skipped the same way. When the City's register could not be read in the run (`register_unavailable`) there is nothing to score: no score, nothing charged. It is a guide to which listings to look at first, not a finding of fault.

#### Business contact (option)

A professional Booking.com host (`isTrader`: a company, as Booking.com labels it) shows a business e-mail and phone on its property page. Tick **Business contact (Booking.com)** to get them in `businessEmail` and `businessPhone` — for the professional hosts only: a private host's contact is not given, and neither Airbnb nor the City's register give one (*"Operator names and contact information are not included"*). Hotels are professional hosts and nearly all show both; the homes searched by default are mostly private: in September 2026 about 7 properties in 100 were professional (2 of 30 Toronto homes, apartments, holiday homes and villas), against 29 of 40 once hotels and guest houses are searched too. A property is charged `business-contact` once, when its row carries an e-mail or a phone; a row without either costs nothing extra. These are professional contact details published by the host on Booking.com; you are responsible for using them in compliance with the applicable law (see the FAQ). Not available with **Cards only (fast)**.

#### Professional host contact (option)

Airbnb shows no e-mail or phone for most hosts, and the City's register gives none. Tick **Professional host contact** to get the **business email and phone of professional hosts, from publicly available sources**: `proHostEmails` and `proHostPhones` (3 each at most, phones as `+1 416 555 0100`), with `proHostContactSourceUrl` (the page they were read from), `proHostCompany` and `proHostWebsite`, and `proHostContactConfidence` (`high` when an e-mail is on the company's own domain, `medium` otherwise). A host is looked up only when a company name is known: the business name Airbnb gives, or a host or co-host whose name is a company's. A host with a person's name only is never looked up, whatever the type of host or the number of listings. A company is looked up once per run, however many listings it has. When no contact is found, the listing is delivered as it is and not charged; you pay `pro-host-contact` once per listing whose row carries an e-mail or a phone. Not available with **Cards only (fast)**; for Booking.com properties see **Business contact**.

#### Photos (option)

The links of a listing's photos are in `images` in every run, for free. Tick **Download photos** to also keep the photos themselves: the first **Max photos per listing** (5 by default) of each Airbnb listing — a Booking.com property has its main photo — are downloaded into the key-value store of your run, and the row gets `photoFiles` (the public link of each, in the order of the listing's photos), `photoSha256` (the SHA-256 of each) and `photosDownloadedAt` (the time of the download). It is a dated copy of what the listing showed that day, and the hash shows that a file is the one that was downloaded. A photo that cannot be had — gone, not an image, too big — is left out and not charged; you pay `photo-download` for each photo delivered. Photos are the sites' own files, kept as they are: your storage grows by their weight (a few hundred KB each), and the records follow the retention of your run's storage. Not available with **Cards only (fast)**.

#### Cards only (option)

Tick **Cards only (fast)** to get just what Airbnb shows in its search results, without opening the listings: the link, title, type of place (`propertyType`: Apartment, Room…), price, rating, position, bedrooms and the dates of the search. It is faster and cheaper than a full check, and the right choice to list or monitor what is offered; the rows have `source` set to `airbnb_card` and `verdict` set to `unchecked` — **no registration number, no verdict, nothing from the register**. A run in this mode is charged one `listing-card` per card, and nothing else (no check fee for a card your filters drop: minimum rating, excluded words and the dates and prices of the search still apply).

It needs a place, a map area or an Airbnb search URL. It cannot be mixed with what needs the listing page or the register — host profile, calendar, risk score, revenue estimate, comparables, AI labels, listing URLs and IDs, Booking.com, registration numbers, register wards, the host type filter (Airbnb's search results do not say it) and the filters on verdicts, wards and register property types: the run is refused at the start, naming each one.

#### Comparables (option)

Tick **Comparable listings** to get, for each Airbnb listing, `comparables`: the Airbnb listings around it that are of the same type of place (entire home, private room…) and within one bedroom of it, the nearest first, up to **Max comparables per listing** (10 by default) — each with its link, `pricePerNight`, `bedrooms`, `rating` and `distanceKm` — and `comparablesMedianPrice`, their median price per night. Give **Check-in** and **Check-out** to get the prices (the nightly rate of those dates, before taxes and fees, in the currency of the run); without dates the neighbours carry no price and there is no median.

The neighbours are read from the search results around the listing, not from their own pages, and one search serves all the listings of the same area (about 500 m), type of place and size: a run over a whole district costs a few searches, not one per listing (a district with every size of home costs one search per type of place and size). Airbnb shows the 18 best results of an area, so the neighbours are those of that page that fit: a quiet area may give fewer than the maximum; a listing whose type or position is unknown, or an entire home whose bedrooms are unknown, gets none. A listing is charged `comparables` only when its row carries at least one neighbour.

#### Revenue estimate (option)

Tick **Revenue estimate (12 months)** and give **Check-in** and **Check-out** to get, for each Airbnb listing found by a search, an estimate of what its calendar says it earns: `estimatedNightsBooked12m` (the nights of the calendar that are not open), `estimatedRevenue12m` (those nights × the `pricePerNight` of the dates searched, in `revenueCurrency`) and `estimatedOccupancy` (the share of the calendar blocked, 0 to 1). The option reads the listing's calendar (the same one as **Availability calendar**, charged as such) — but only when the run has dates: without them no card has a price per night and nothing would be estimated.

It is an **estimate**: a night the calendar shows as not open may be rented or simply closed by the host, Airbnb does not tell them apart (the figure is an upper bound of the nights rented), and the price is the average nightly rate of the dates you searched, not of the year. A listing given by URL or ID has no price per night: it gets no estimate and is not charged for one. The log counts the listings estimated and those left without.

#### AI labels (option)

Tick **AI labels** to have the description of each Airbnb listing read for five things, each a yes / no in `aiLabels` with its confidence (0 to 1) in `aiLabelScores`:

| Label (key) | What it says | True from |
| --- | --- | --- |
| `managed_by_company` | The listing is run by a company or a property manager | 0.50 |
| `self_check_in` | Guests check in by themselves (lockbox, keypad, code) | 0.60 |
| `long_stay` | Monthly or long stays (28 nights or more) | 0.50 |
| `not_principal_residence` | The host does not live in the home | 0.75 |
| `mentions_licence` | The text mentions a licence or a permit (not the registration block Airbnb adds) | 0.50 |

The labels are read in the host's own text and are **indications, not facts**: the cut-offs are set high so that a label marked true is rarely wrong, and a host who does not write it down gets `false` (a long description is read to its end, up to about 6,000 characters). Checked on 40 Toronto descriptions read by hand, in September 2026 — a small sample: expect some misses and some false alarms. Only English descriptions are read: another language, a Booking.com property or a listing without a description gets `null` and is not charged. The option needs **2 GB of memory** (Run options → Memory): on a smaller run it is skipped, the log says so, and nothing is charged. The descriptions are read one at a time, so a run with the option is slower and costs more compute; it is charged once per listing given its labels (`ai-labels`).

#### How to reduce costs

The levers are `maxItems`, `maxItemsPerQuery`, **Keep only these verdicts** (a listing dropped costs only the filter fee), using **Cards only (fast)** when you do not need the number, leaving **Host's listing count**, **Availability calendar**, **Risk score (0-100)**, **Revenue estimate (12 months)**, **Comparable listings**, **Download photos**, **Business contact (Booking.com)**, **Professional host contact** and **AI labels** off (the default), `onlyNew` for recurring runs (you never pay twice for the same listing), and searching only the site you need.

#### Several searches in one run

Fill `locations` and / or `boundingBoxes`, or paste several search URLs: one search each (up to 100 places, 100 map areas and 1,000 URLs per run). A listing found by several searches is saved — and charged — once. Set `maxItemsPerQuery` to give every search its own cap.

#### Monitoring: only the new listings

Tick **Only new listings** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the listings already delivered: they are not saved, not charged, and their page is not even opened. The memory lives in a named key-value store of your account (`airbnb-toronto-license-checker-seen`, up to 150,000 listings per memory name) and is only updated with listings that really reached the dataset, plus, apart, the ones your filters dropped: a listing your filters drop is checked (and charged) once; the next runs with the same filters skip it for free. Change a filter, or tick `resetState`, to check them again. Give each schedule its own `memoryName` (**Memory name**), and tick `resetState` once to start over. With `registerWards`, the new registrations of a ward come the same way. A listing saved while the City's register could not be read (`register_unavailable`) is not remembered, saved or dropped: the next run checks its number, and charges it, again.

#### What the register can and cannot say

The City's open register lists the **active** registrations only, refreshed every day: a number that is absent is expired, cancelled or was never registered, and the register does not say which (`not_in_register`). It gives the address, the unit (for 2 registrations in 3), the first 3 characters of the postal code, the property type and the ward — never the operator's name or contact (*"Operator names and contact information are not included"*). Airbnb blurs a listing's point by about 150 m (92 m median in Toronto, September 2026): `other_property` is only raised past **Distance tolerance**, measured from the registered address's official point. A few registered addresses are written in a way the City's address map does not know: their distance is not checked, and `verdictNote` says so.

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per Airbnb listing or Booking.com property checked (or per registration number, or per register record). Actor id: `nice_dev/airbnb-toronto-license-checker`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/airbnb-toronto-license-checker`.

Smallest input, for a cheap first call:

```json
{
    "licenseNumbers": ["STR-2608-JGXPVZ"],
    "location": "Toronto, Ontario, Canada",
    "maxItems": 5
}
```

Key output fields: `url`, `verdict`, `verdictNote`, `licenseNumber`, `registerAddress`, `registerUnit`, `distanceKm`, `hostName`.

Cost: see the prices on the Pricing tab. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape Airbnb and Booking.com and use the register?

The Actor only reads what Airbnb and Booking.com show publicly to any anonymous visitor, and the open data the City of Toronto publishes for reuse under the Open Government Licence – Toronto, which allows commercial use and asks for the source: each result carries it (*Contains information licensed under the Open Government Licence – Toronto.*). It logs in to nothing. The registered addresses are homes of private people (Toronto allows short-term rentals in the operator's principal residence only), without names; host names come from the listings. Personal information is protected by Canadian privacy law (PIPEDA) and, for EU residents, by GDPR: do not store it without a legitimate reason. The business e-mail and phone of the **Business contact (Booking.com)** option are professional contact details that a professional host publishes on its own property page; sending commercial messages to them is governed by the law of the recipient's country (in Canada, the anti-spam law, CASL): you answer for how you use them. The **Professional host contact** option returns business contact details of companies, taken from publicly available sources, with the page each one comes from; it never looks up a private person, and the same duties apply to how you use them. You are responsible for using the data in compliance with Airbnb's and Booking.com's Terms of Service and applicable law. This Actor is not affiliated with Airbnb, Booking.com or the City of Toronto.

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request the site turns away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 150 seconds).

#### Is the data safe to open in Excel or to show on a web page?

Titles and descriptions are the hosts' own words, copied as they are; the register fields are copied as the City writes them. A text can begin with `-`, `+`, `=` or `@` (a phone number starts with `+`): Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. On a web page, escape every field like any text written by a stranger.

#### Known limitations

- The price comes from Airbnb's search results: listings given by URL or ID, and Booking.com properties, have none.
- A Booking.com property pasted by URL gets its position, address and photo from one more request: if it fails, the property is still checked, and `verdictNote` says the distance could not be.
- A host profile shows 10 of its listings at most: `hostListingsCount` is the full count, `hostListingIds` the first ones.
- `onlyNew` remembers listing ids, not their content: a listing whose number changed is not returned again.
- The ward of a listing comes from its point on the map, read against the City's ward limits (simplified to about 20 m); an Airbnb point within 300 m outside the City is given the nearest ward (Airbnb's blur); a Booking.com property, whose point is its own, only within 50 m.

**A run that reaches its timeout** stops itself about 45 seconds before it: no new page is asked, what it read is saved and, with `onlyNew`, remembered, and the run ends *Succeeded* with "Stopped before the run's timeout". Resurrect it to go on from there, or give the next run a longer timeout (Run options).

**A run the platform stops without warning** (out of memory)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the listings already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved after each write (at most once every 2 seconds): resurrect the stopped run and the listings it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the listings of its last 2 seconds once more.

#### Something doesn't work?

The last line of the log counts the results saved, filtered out and no longer on Airbnb or Booking.com (removed while the run was reading them), and the requests that failed after every retry. Those requests and the removed listings are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause. A register that cannot be downloaded does not fail the run: its listings and numbers get `register_unavailable`. Register wards alone then list nothing, and that run fails with the cause.

If Airbnb or Booking.com changes its pages, you are told instead of paying for blank rows. A results page that gives no listing the Actor can read is an error (listed in `FAILED_REQUESTS`), never a quiet "No listings found". If the first 20 listings read all lack their title, position, guests, room type, host, photos or registration block (hotels aside) — on Booking.com: their title, position, registration block (hotels and guest houses aside), property type or host type — the run saves nothing more, stops and fails, and its last message names the missing field: at most those first listings are charged. A listing a filter drops because such a field is missing counts among those 20. If Booking.com's API no longer accepts the Actor's request (a field it renamed), or no longer answers at its address, the run stops at once and fails with that reason, instead of trying every property again.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which URLs failed and why.

# Actor input Schema

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

Airbnb listing URLs (`https://www.airbnb.com/rooms/12345`, any Airbnb domain such as airbnb.ca) and/or Airbnb search URLs (`https://www.airbnb.com/s/Toronto--Ontario--Canada/homes`, map searches included: their filters are kept, pagination and map splitting are automatic). Max 1 000 URLs.

## `listingIds` (type: `array`):

Airbnb listing IDs alone (the digits after `/rooms/`), one per line — checked in this order, before any search: with a result limit, the first ones are the ones saved. Max 1 000.

## `bookingUrls` (type: `array`):

Booking.com property pages to check, e.g. `https://www.booking.com/hotel/ca/urban-nest-toronto.html` (any language version). Read whatever Sites searched says.

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

A place in Toronto, as typed in Airbnb's or Booking.com's search box (e.g. `Toronto, Ontario, Canada`, `Scarborough, Toronto`, `Etobicoke`), searched on the **Sites searched**. Each listing found is opened and its registration checked. Listings outside the City of Toronto (Mississauga, Vaughan…) are saved with the verdict `region_not_covered`, except one that shows a Toronto number: that number is checked.

## `locations` (type: `array`):

Several places in one run (one search each and per site, max 100). Added to **Place**; a listing found by several searches is saved once.

## `sources` (type: `array`):

The sites each place (Place, More places) is searched on: Airbnb, Booking.com, or both (one search per place and site, each with its own Max listings per search). Airbnb URLs, listing IDs and map areas always go to Airbnb, Booking.com URLs to Booking.com.

## `boundingBoxes` (type: `array`):

Map rectangles to search, one per line as `south latitude, west longitude, north latitude, east longitude` (e.g. `43.63, -79.41, 43.66, -79.37` for downtown Toronto). The surest way to cover a whole city: Airbnb returns at most 270 listings per search, and a full area is split into smaller ones automatically.

## `licenseNumbers` (type: `array`):

Toronto short-term rental registration numbers checked against the register without any listing (`STR-2608-JGXPVZ`; spaces, missing dashes and lower case are accepted). One result per number. Max 1 000.

## `registerWards` (type: `array`):

Every active registration of these wards, straight from the City's register — address with the unit, property type, month of issue, position of the address — without any Airbnb search. Newest first (month of issue read in the number). Filtered by **Issued in or after** and **Property types**. All wards = the whole register (≈ 8 700 records).

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

Maximum number of results (listings checked, registration numbers and register records) to save for the whole run, after filters. 0 = no limit.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH search (place and site, map area or search URL), so that the first search cannot use up the whole **Max results** budget. 0 = no per-search cap — except when the run searches both sites (places on both, or a Booking.com place next to an Airbnb map area or search URL): **Max results** is then shared evenly between the searches (a Booking.com page brings 100 properties at once and would take every slot) — and per ward named in **Register records of these wards** (`all` = one cap for the whole register, newest first).

## `splitMap` (type: `boolean`):

Airbnb shows at most 270 listings (15 pages) per search: a full search has its map area cut into 4 smaller areas, again and again. Booking.com shows at most 1 000 properties per search: a bigger one is also read district by district. Off = the first 270 (Airbnb) or 1 000 (Booking.com) of each search only.

## `cardsOnly` (type: `boolean`):

Deliver the card of each Airbnb search result — link, title, type of place, price, rating, position, bedrooms — without opening the listing: faster and cheaper, but no registration number, no verdict, nothing from the register. Charged per card (see Pricing), nothing else is charged in this mode. Needs a place, a map area or an Airbnb search URL. Not compatible with the options that read the listing (host profile, calendar, risk score, revenue estimate, comparables, AI labels), with Airbnb listing URLs and IDs, Booking.com, registration numbers and register wards, nor with the host type filter and the filters on verdicts, wards and register property types.

## `checkIn` (type: `string`):

Travel dates of the search (`2027-07-12`). Airbnb then shows the listings free on those dates and their price for the stay; empty = Airbnb's own flexible dates. Today or later (the day in Toronto): Airbnb shows nothing for a stay that has begun.

## `checkOut` (type: `string`):

End of the stay (`2027-07-15`), after the check-in date.

## `adults` (type: `integer`):

Number of guests: only the listings that can host them. 0 = any.

## `children` (type: `integer`):

Children aged 2-12 travelling (Airbnb filter). 0 = none.

## `infants` (type: `integer`):

Infants under 2 travelling (Airbnb filter). 0 = none.

## `pets` (type: `integer`):

Pets travelling: only listings that allow pets. 0 = none.

## `currency` (type: `string`):

Currency of the prices shown on the search results.

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

Lowest price per night, in the currency above. 0 = no minimum.

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

Highest price per night, in the currency above. 0 = no maximum.

## `roomTypes` (type: `array`):

Only these kinds of place. Empty = all.

## `propertyTypes` (type: `array`):

Only these kinds of property (Airbnb filter). Empty = all.

## `minBedrooms` (type: `integer`):

Only listings with at least this many bedrooms. 0 = any.

## `minBeds` (type: `integer`):

Only listings with at least this many beds. 0 = any.

## `minBathrooms` (type: `integer`):

Only listings with at least this many bathrooms. 0 = any.

## `superhostOnly` (type: `boolean`):

Only listings of Superhosts (Airbnb filter).

## `bookingPropertyTypes` (type: `array`):

Kinds of properties a Booking.com search lists. Default: apartments, holiday homes and villas — the homes a short-term rental registration is for (hotels and inns are not registered).

## `registeredAfter` (type: `string`):

Only registrations issued in this month or later (`2026-01-01`; the month is read in the number, a number STR-2601-… was issued in January 2026): the new operators of the ward. Empty = all.

## `registerPropertyTypes` (type: `array`):

Only these property types, as the register gives them. Also applied to listings: one not found in the register has no type and is dropped. Empty = all.

## `onlyVerdicts` (type: `array`):

Save only the listings whose verdict is one of these — e.g. `never_issued`, `not_in_register`, `other_property`, `unknown_format` and `no_number` to get the suspicious listings only (the verdicts marked isSuspicious). Empty = every listing.

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

Only listings in these wards (the listing's position on the map; the register's ward when the position is unknown). Outside Toronto (`other`) keeps the listings of neighbouring cities; a listing whose ward is unknown is dropped. Empty = all.

## `hostType` (type: `string`):

Only listings of business hosts (companies and professionals, who must show their business details) or of individual hosts, as Airbnb labels them on the search results (on the listing page for listing URLs and IDs) — on Booking.com, as the host declared itself (professional or private).

## `minRating` (type: `number`):

Only listings rated at least this much out of 5 (Booking.com's score out of 10 is halved; listings without a rating are dropped). 0 = any.

## `excludeKeywords` (type: `array`):

Drop the listings whose title contains one of these words (case and accents ignored).

## `gpsToleranceKm` (type: `number`):

Airbnb blurs a listing's position by about 150 m (measured in Toronto: 92 m median, 160 m at most). A registered address (placed with the City's address points) farther than this from the listing — or from the Booking.com property — gives the verdict `other_property`.

## `includeHostProfile` (type: `boolean`):

Airbnb: open the host's public profile (1 extra request per host, not per listing) for the number of listings they manage and their IDs. Charged per host profile (see Pricing). Booking.com shows no host profile.

## `includeCalendar` (type: `boolean`):

Read each Airbnb listing's calendar (1 extra request per listing): nights open and nights booked or blocked from today to the end of the 11th month after this one (Airbnb's 12 calendar months), per month and per day, and whether it is open more than the 180 nights a year Toronto allows for renting an entire home. Charged per listing whose calendar reaches your results (see Pricing).

## `includeRiskScore` (type: `boolean`):

Give each Airbnb listing and Booking.com property a risk score from 0 to 100 and the short codes of the rules behind it: the verdict first, then a number shown by several listings, a registered address far from the listing, an entire home, a type of home that differs from the register's, a host who manages several listings (needs **Host's listing count**), a calendar open past 180 nights (needs **Availability calendar**) and a professional host. A rule whose data is not read is skipped and named, never counted as a risk. No extra request. Charged per listing whose row carries a score (see Pricing); a row whose register could not be read gets none and is not charged for it.

## `includeComparables` (type: `boolean`):

Add, to each Airbnb listing, the Airbnb listings around it: the nearest ones of the same type of place and within one bedroom of it (up to **Max comparables per listing**), each with its price per night, rating, bedrooms and distance, and the median price per night of them. Read from the cards of a search around the listing: no listing page is opened, and one search serves every listing of the same area. Give **Check-in** and **Check-out** to get prices: without dates the comparables have no price and there is no median. Charged per listing whose row carries comparables (see Pricing).

## `maxComparablesPerListing` (type: `integer`):

Most comparable listings kept for each listing (**Comparable listings**): the nearest ones.

## `downloadPhotos` (type: `boolean`):

Download the first photos of each listing into this run's key-value store and give their public links, their SHA-256 and the time of the download: a dated copy of what the listing showed that day. The links in **Photos** (`images`) stay in every run for free. A photo that cannot be had (gone, too big, not an image) is left out and not charged. Charged per photo delivered (see Pricing). Not available with **Cards only (fast)**.

## `maxPhotosPerListing` (type: `integer`):

Photos downloaded for each listing (**Download photos**): the first ones of the listing.

## `includeBusinessContact` (type: `boolean`):

For a Booking.com property run by a professional host (a company), add the business e-mail and phone its page shows: `businessEmail` and `businessPhone`. Only professional hosts have them, a private host's contact is not given. Airbnb and the City's register give no contact (the register says: *Operator names and contact information are not included*). Charged per property whose row carries an e-mail or a phone (see Pricing). Not available with **Cards only (fast)**.

## `includeProHostContact` (type: `boolean`):

Add the business e-mail and phone of professional Airbnb hosts, from publicly available sources, with the page each comes from and a confidence: `proHostEmails`, `proHostPhones`, `proHostContactSourceUrl`, `proHostContactConfidence`. A host is looked up only when a company name is known (the business name Airbnb gives, or a host or co-host whose name is a company's), never a private person. Charged per listing whose row carries a contact (see Pricing); a listing with none is delivered as it is, not charged. Not available with **Cards only (fast)**.

## `includeAiLabels` (type: `boolean`):

Label each Airbnb listing's description with five yes / no AI labels and their scores: managed by a company or a property manager, self check-in with a lockbox or a keypad, monthly or long stays (28 nights or more), host does not live in the home, mentions a licence or a permit. English descriptions only: a description in another language, a Booking.com property and a listing without a description get none. The labels are read in the text of the description, they are indications, not facts. Needs 2 GB of memory (Run options → Memory): with less, the AI labels are skipped, said in the log, and nothing is charged. The descriptions are read one at a time, so a run with this option is slower. Charged per listing whose row carries its labels (see Pricing).

## `includeRevenueEstimate` (type: `boolean`):

Estimate the revenue of each Airbnb listing from its availability calendar: the nights the calendar shows as not open (booked, or closed by the host — Airbnb does not tell them apart) × the price per night of the dates searched, with the share of the calendar that is blocked. An estimate, not what the host earned. Needs **Check-in** and **Check-out** (the price per night comes from a search with dates; a listing given by URL or ID has none) and reads the calendar too, charged as **Availability calendar**. A listing without a price per night gets no estimate and is not charged for one. Charged per listing whose row carries its estimate (see Pricing).

## `onlyNew` (type: `boolean`):

Skip the listings (and registration numbers) that a previous run (same **Memory name**) already delivered: they are not saved and not charged, and their page is not even opened. First run = everything is new.

## `memoryName` (type: `string`):

Name of the memory used by **Only new listings**. Give each schedule / task its own name (e.g. `toronto-weekly`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory name** before the run: this run returns (and charges) every listing again. Untick it afterwards.

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

Apify Proxy or your own proxies, for the Airbnb and Booking.com pages. Keep the default: it is included in the price. The residential Apify proxy is not available in this Actor. The official registers are downloaded directly.

## `maxConcurrency` (type: `integer`):

Maximum number of Airbnb pages processed in parallel.

## `maxRequestsPerMinute` (type: `integer`):

Most requests to Airbnb and Booking.com in any 60 seconds, all of them counted: search pages, listing pages and host profiles. A budget, not an even pace: up to this many can leave at once when the minute starts (spread them with the minimum delay below). Lower it if Airbnb or Booking.com answers HTTP 429 / 403 in the log.

## `minRequestIntervalMs` (type: `integer`):

Smallest gap between two requests to Airbnb, in milliseconds. Unlike the per-minute rate, this spreads the requests evenly instead of letting them go out in a burst. 0 = no gap.

## `maxRequestRetries` (type: `integer`):

Retries per request before it is marked as failed. Behind a proxy, a request Airbnb turns away is also retried on a new proxy session up to 10 times without using up these retries.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "startUrls": [],
  "listingIds": [],
  "bookingUrls": [],
  "location": "Toronto, Ontario, Canada",
  "locations": [],
  "sources": [
    "airbnb"
  ],
  "boundingBoxes": [],
  "licenseNumbers": [],
  "registerWards": [],
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "splitMap": true,
  "cardsOnly": false,
  "adults": 0,
  "children": 0,
  "infants": 0,
  "pets": 0,
  "currency": "CAD",
  "priceMin": 0,
  "priceMax": 0,
  "roomTypes": [],
  "propertyTypes": [],
  "minBedrooms": 0,
  "minBeds": 0,
  "minBathrooms": 0,
  "superhostOnly": false,
  "bookingPropertyTypes": [
    "apartment",
    "holiday_home",
    "villa"
  ],
  "registerPropertyTypes": [],
  "onlyVerdicts": [],
  "wards": [],
  "hostType": "any",
  "minRating": 0,
  "excludeKeywords": [],
  "gpsToleranceKm": 0.5,
  "includeHostProfile": false,
  "includeCalendar": false,
  "includeRiskScore": false,
  "includeComparables": false,
  "maxComparablesPerListing": 10,
  "downloadPhotos": false,
  "maxPhotosPerListing": 5,
  "includeBusinessContact": false,
  "includeProHostContact": false,
  "includeAiLabels": false,
  "includeRevenueEstimate": false,
  "onlyNew": false,
  "memoryName": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 8,
  "maxRequestsPerMinute": 120,
  "minRequestIntervalMs": 0,
  "maxRequestRetries": 5,
  "debugLog": false
}
```

# Actor output Schema

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

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

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

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "location": "Toronto, Ontario, Canada",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/airbnb-toronto-license-checker").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": "Toronto, Ontario, Canada",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/airbnb-toronto-license-checker").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": "Toronto, Ontario, Canada",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/airbnb-toronto-license-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/airbnb-toronto-license-checker"
        }
    }
}
```

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/sxhgMZTY6o7C2oasP/builds/NftPsTEWMGRuVS7dh/openapi.json
