# Airbnb Scraper (Proxy Included) + Prices & Ratings (`nomad-agent/airbnb-scraper`) Actor

$0.2/1K listings | Extract Airbnb listings in bulk for any city or map area: price, rating, review count, room type, beds and coordinates, with date, guest and price filters. Residential proxy included, no login. Not affiliated with Airbnb.

- **URL**: https://apify.com/nomad-agent/airbnb-scraper.md
- **Developed by:** [Nomad.Devs](https://apify.com/nomad-agent) (community)
- **Categories:** Travel, Real estate
- **Features:** Limited permissions
- **Stats:** 11 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.10 / 1,000 listing results

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

## Airbnb Scraper (No Login) + Prices & Ratings

$0.2/1K listings | Extract Airbnb listings in bulk for any city or map area: price, rating, review count, room type, beds and coordinates, with date, guest and price filters. Residential proxy included, no login. Not affiliated with Airbnb.

### Airbnb Listings Bulk Scraper

Our scraper collects Airbnb listings for a named location or a map area and lets you filter by dates, guests, nightly price, room type and minimum bedrooms, beds or bathrooms. Every row is one flat record with price, rating, review count, room type, bed counts and coordinates. It is ideal for short-term-rental market research, competitive sets for property managers and pricing or investment models.

- Looking at long-term rent and sale listings in Kenya instead of holiday stays? Use [BuyRentKenya Property Scraper](https://apify.com/nomad-agent/buyrentkenya-scraper).
- Browse all our scrapers: https://apify.com/nomad-agent

#### Key Benefits

- No login: it reads only what a logged-out visitor sees, so there is no Airbnb account to connect or put at risk.
- Low pricing: **$0.20 per 1,000 listings**, with lower rates on Scale and Business plans ($0.15 and $0.1 per 1,000), plus a $0.00005 start fee per run. Residential proxy traffic is included, so there is no separate proxy bill.
- Quick to try: a 10-listing test run finished in about 8 seconds. 🚀
- Past the result ceiling: Airbnb serves about 270 results per query, so the Actor splits the price range into sub-searches (up to `maxPriceSplits` times) to reach your `maxItems`.
- Optional depth: detail mode adds host, amenities, an availability calendar and guest reviews.

### How It Works

1. Choose the mode. `search` (the default) lists a location or map area; `detail` resolves specific listing URLs or ids. Both bill the same per listing returned.
2. Provide your search:
   - (required in search mode) `location` (e.g., `Lisbon, Portugal`), or `latitude` and `longitude` for a map area.
   - (optional) `checkIn` and `checkOut` (e.g., `2026-09-23`). With both set, prices are stay totals for those dates.
   - (optional) `priceMin` and `priceMax` per night, `adults`, `children`, `roomType` (e.g., `entire_home`).
   - (optional) `minBedrooms`, `minBeds`, `minBathrooms`. `0` means no filter.
   - (detail mode) `listingUrls`, plus `calendarMonths` (0 to 12) and `includeReviews` for the extras.
3. Click Start. The form opens with `Lisbon, Portugal` and 20 listings, so a first run returns real rows.

Run the same search again and you get only listings you have not received yet; set `dedupe.enabled` to `false` to see everything again.

More settings:

- `maxItems` - Hard cap on listings returned. Default is 100.
- `currency` - ISO code for returned prices. Default is `USD`.
- `maxReviewsPerListing` - Reviews fetched per listing when `includeReviews` is on. Default is 10.
- `maxPriceSplits` - How many times a search may split its price range. Default is 8; lower it to cap cost in dense markets.
- `concurrency` - Parallel fetches in detail mode. Default is 2; keep it low, Airbnb rate-limits hard.

Search rows carry the card fields only. In our test run, `hostName`, `amenitiesCount` and `description` were empty on all 10 search rows; use detail mode when you need them.

With dates set, prices are stay totals, and `pricePer` says which kind you got (for example `for 5 nights`). Divide by the number of nights for a nightly rate.

The calendar and review fetches use internal Airbnb endpoints and are not always available. If Airbnb changes them, the field comes back `null` for that run and the rest of each record is unaffected.

If Airbnb blocks a run, the Actor stops cleanly and keeps the listings it already collected. Lower `concurrency` to 1 and retry.

#### Data You'll Receive

- Listing: id, URL, title, property type, room type, photo count and thumbnail.
- Price: numeric price, currency and the qualifier (`total`, `night` or `for N nights`).
- Reputation: rating and review count.
- Space: beds, bedrooms and baths where Airbnb shows them.
- Location: latitude and longitude.
- Detail mode only: host first name, amenity count, guest capacity, Superhost flag, full description, availability calendar and reviews.

#### Sample output data

Here is an example listing from a search-mode test run of this Actor:

```json
{
  "id": "7743405",
  "url": "https://www.airbnb.com/rooms/7743405",
  "title": "Newly renovated in the heart of Chiado, with a private balcony and A/C",
  "propertyType": "Apartment in Lisbon",
  "price": 2023,
  "currency": "USD",
  "pricePer": "for 5 nights",
  "rating": 4.99,
  "reviewsCount": 502,
  "roomType": "Entire home/apt",
  "beds": 4,
  "bedrooms": 3,
  "baths": 2,
  "lat": 38.7107,
  "lng": -9.1442,
  "hostName": null,
  "thumbnail": "https://a0.muscache.com/im/pictures/hosting/Hosting-U3RheVN1cHBseUxpc3Rpbmc6Nzc0MzQwNQ==/original/ee38447f-2efa-4f82-9a67-bb2b30b23a66.jpeg",
  "imagesCount": 6,
  "amenitiesCount": null,
  "description": null,
  "calendar": null,
  "reviews": null,
  "mode": "search"
}
```

### Airbnb Listings API

Results are stored in a dataset that you can export as CSV, JSON or Excel, or read through the Apify API. Connect it to Make, n8n or Zapier, or let an agent call it through the Apify MCP server.

#### Support and Feedback

We improve these scrapers from your feedback. If something breaks or you need a filter:

- Open an issue on the Actor's Issues tab.
- If this Actor saved you time, a short review on the Store helps other people find it.

### Run evidence

#### Start with one input and output

An Apify account is required. Use your Apify API token when calling the API; Console runs do not need that token pasted into the input. No user API-key field is required by this input schema.

Free-tier event rates checked 2026-10-04: `result` $0.0002; `actor-start` $0.00005.

**Cost:** Total = Actor event charges + platform usage if separately billed + any BYO-provider charges. See “Current costs” for your event rates, plan tiers and a calculation. A sample does not promise future billable volume.

Input and output below were read from the same successful run `VaBJw4FKrs3lJzSfF` (2026-10-04, immutable build `cOrfvuy3Jc6uK5xVs`). This is an observed example, not a guarantee that repeating it returns this row.

**Input JSON**

```json
{
  "mode": "search",
  "maxLocationDeviation": 0.05,
  "priceMin": 0,
  "priceMax": 0,
  "adults": 0,
  "children": 0,
  "roomType": "any",
  "minBedrooms": 0,
  "minBeds": 0,
  "minBathrooms": 0,
  "calendarMonths": 0,
  "includeReviews": false,
  "maxReviewsPerListing": 10,
  "maxItems": 100,
  "currency": "USD",
  "concurrency": 2,
  "maxPriceSplits": 8
}
```

**Matching output excerpt**

Long strings and arrays are shortened for display; this is not a complete dataset fixture.

```json
{
  "id": "1550967010992579703",
  "url": "https://www.airbnb.com/rooms/1550967010992579703",
  "title": "Lofty ceilings with a Tagus River view",
  "propertyType": "Apartment in São Paulo",
  "price": 1201,
  "currency": "USD",
  "pricePer": "for 5 nights",
  "rating": 4.98,
  "reviewsCount": 61,
  "roomType": "Entire home/apt",
  "beds": 3,
  "bedrooms": 2,
  "baths": 2,
  "lat": 38.7069,
  "lng": -9.1422,
  "hostName": null,
  "thumbnail": "https://a0.muscache.com/im/pictures/hosting/Hosting-1550967010992579703/original/c172a896-3844-4c36-a2b2-c87d8633a18c.png",
  "imagesCount": 17,
  "amenitiesCount": null,
  "description": null,
  "calendar": null,
  "reviews": null,
  "mode": "search"
}
```

Scrape Airbnb listings into clean, structured JSON — search any location (or a lat/lng map area) with dates, guests, price, room-type and bedroom/bed filters, or resolve listing URLs to full detail records (optionally including an availability calendar and per-listing reviews). Built for reliability: automatic price-range splitting gets past Airbnb's ~270-result cap, blocks are classified and logged (never crash a run), and every record comes back in one flat, predictable shape.

> **Claude / Codex skill to describe and setup this actor: [SKILL.md](https://github.com/Exdenta/OinkAIJobSearch/blob/main/.agents/skills/public-apify-actors/SKILL.md)**

#### What Airbnb data does this scraper extract?

One flat JSON record per listing:

| Field | Meaning |
|---|---|
| `id` | Airbnb listing id |
| `url` | Direct `airbnb.com/rooms/...` link |
| `title` | Listing name |
| `propertyType` | e.g. "Entire rental unit", "Apartment in Lisbon" |
| `price` / `currency` / `pricePer` | Numeric price, ISO currency, qualifier (`total` / `night`) |
| `rating` / `reviewsCount` | Guest rating and review count |
| `roomType` | Entire home/apt, Private room, Shared room, Hotel room |
| `beds` / `bedrooms` / `baths` | Where Airbnb exposes them |
| `lat` / `lng` | Listing coordinates |
| `hostName` | Host first name (detail mode) |
| `thumbnail` | URL of the primary photo, where exposed |
| `imagesCount` | Number of photos |
| `amenitiesCount` | Number of amenities (detail mode) |
| `personCapacity` / `isSuperhost` / `description` | Detail mode extras |
| `calendar` | `[{month, year, availableDays}, ...]` — only populated when `calendarMonths` > 0 (detail mode); otherwise `null` |
| `reviews` | `[{id, author, date, rating, language, text, response}, ...]` — only populated when `includeReviews` is on (detail mode); otherwise `null` |
| `mode` | `search` or `detail` |

#### Input

| Name | Type | Default | Description |
|---|---|---|---|
| `mode` | string (`search` | `detail`) | `"search"` | Search a location, or resolve specific listing URLs/ids to full detail records. |
| `location` | string | — | Where to search, as typed on airbnb.com (e.g. `"Lisbon, Portugal"`). Required in search mode unless you use `latitude`/`longitude`. |
| `latitude` / `longitude` | number | — | Search mode. Centre of a coordinate/map search that bypasses named-location geocoding. Set both; `location` then becomes optional. Best-effort. |
| `maxLocationDeviation` | number | `0.05` | Search mode. Half-width in degrees of the map box around `latitude`/`longitude` (~0.05° ≈ 5.5 km). |
| `listingUrls` | array of strings | — | Listing URLs or bare numeric ids. Required in detail mode. |
| `checkIn` / `checkOut` | string (`YYYY-MM-DD`) | — | Optional dates. With both set, prices become stay totals. |
| `priceMin` / `priceMax` | integer | `0` | Nightly price filter bounds. `0` = no bound. |
| `adults` / `children` | integer | `0` | Guest counts. |
| `roomType` | string (enum) | `"any"` | `any`, `entire_home`, `private_room`, `shared_room`, `hotel_room`. |
| `minBedrooms` | integer | `0` | Only listings with at least this many bedrooms. `0` = no filter. |
| `minBeds` | integer | `0` | Only listings with at least this many beds. `0` = no filter. |
| `minBathrooms` | integer | `0` | Only listings with at least this many bathrooms. `0` = no filter. |
| `calendarMonths` | integer | `0` | Detail mode only. Fetch this many months (0–12) of availability into the `calendar` output field. `0` = skip. Best-effort (see Known limitations). |
| `includeReviews` | boolean | `false` | Detail mode only. Also fetch per-listing guest reviews into the `reviews` output field. Best-effort, cost-bounded by `maxReviewsPerListing`. |
| `maxReviewsPerListing` | integer | `10` | Cap on reviews fetched per listing when `includeReviews` is on (paged 50 at a time). |
| `maxItems` | integer | `100` | Hard cap on listings returned. |
| `currency` | string | `"USD"` | ISO currency code for returned prices. |
| `concurrency` *(Advanced)* | integer | `2` | Parallel listing fetches in detail mode. Values above `4` (up to `8`) are an aggressive opt-in — faster but more blocks. Keep low — Airbnb rate-limits aggressively. |
| `maxPriceSplits` *(Advanced)* | integer | `8` | How many times a search may auto-split its price range past the ~270-result cap. Lower it to cap cost on dense markets. |
| `proxyConfiguration` | object | Apify Residential | Proxy group. Residential is strongly recommended (its traffic is included in the per-event prices — see Pricing below). |

#### How to scrape Airbnb listings with this Actor

**Search mode** — set `location` (e.g. `"Lisbon, Portugal"`), optionally `checkIn`/`checkOut`, `priceMin`/`priceMax` (per night), `adults`, `roomType`, `minBedrooms`/`minBeds`/`minBathrooms` and `maxItems`. Instead of a named `location`, you can search a **map area** by setting `latitude`/`longitude` (with an optional `maxLocationDeviation` radius in degrees) — handy for programmatic, gridded market scans. With dates set, prices are stay totals for those dates. When a query hits Airbnb's ~270-result ceiling, the Actor automatically splits the price range into sub-ranges (up to `maxPriceSplits` times) and searches each — so large markets still come back complete up to your `maxItems`.

**Detail mode** — set `mode` to `detail` and pass `listingUrls` (full URLs or bare numeric ids). Each listing resolves to a full record including coordinates, per-category ratings source, host, photo and amenity counts, and a complete plain-text description. If the detail API omits its description section, the Actor falls back to the public page's canonical listing description. Set `calendarMonths` for a month-by-month availability summary; turn on `includeReviews` to also pull up to `maxReviewsPerListing` guest reviews per listing into the `reviews` field.

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("nomad-agent/airbnb-scraper").call(run_input={
    "mode": "search",
    "location": "Lisbon, Portugal",
    "checkIn": "2026-09-23",
    "checkOut": "2026-09-28",
    "priceMax": 150,
    "maxItems": 200,
    "proxyConfiguration": {"useApifyProxy": True,
                           "apifyProxyGroups": ["RESIDENTIAL"]},
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["price"], item["currency"], "|", item["title"], item["url"])
```

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/nomad-agent~airbnb-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"mode": "detail", "listingUrls": ["https://www.airbnb.com/rooms/796929"]}'
```

#### Output example

Real `push_data` shape (detail mode, live-fetched 2026-07 — the example description is abbreviated here for readability; emitted detail records retain the complete source body):

```json
{
  "id": "796929",
  "url": "https://www.airbnb.com/rooms/796929",
  "title": "Rental unit in Lisbon",
  "propertyType": "Entire rental unit",
  "price": 465.0,
  "currency": "EUR",
  "pricePer": "total",
  "rating": 4.92,
  "reviewsCount": 463,
  "roomType": "Entire home/apt",
  "beds": 2.0,
  "bedrooms": 1.0,
  "baths": 1.0,
  "lat": 38.71991,
  "lng": -9.13289,
  "hostName": "Bruno",
  "imagesCount": 44,
  "amenitiesCount": 63,
  "personCapacity": 4,
  "isSuperhost": true,
  "description": "A very cool flat in a great location! ...",
  "calendar": null,
  "mode": "detail"
}
```

With `calendarMonths` set (e.g. `2`), `calendar` is populated instead of `null`:

```json
{
"calendar": [
  {"month": 7, "year": 2026, "availableDays": 2},
  {"month": 8, "year": 2026, "availableDays": 8}
]
}
```

With `includeReviews` on, `reviews` is populated (each up to `maxReviewsPerListing`):

```json
{
"reviews": [
  {"id": "1234567890", "author": "Ana", "date": "May 2026", "rating": 5,
   "language": "en", "text": "Great location, spotless flat.", "response": null}
]
}
```

#### Pricing

Pay per event — you pay per listing returned, search results and detail
records alike. Current rates are on this Actor's **Pricing** tab. No subscription — pay only for what you fetch.

**Platform usage is included.** Compute, storage, and proxy traffic — including
the default Residential proxy (`{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}`) — are covered by the per-event prices. You are never billed
separately for this Actor's platform usage.

#### Integrations

Dataset results export straight to JSON, CSV, Excel/XLSX, or a plain HTML table from the Apify Console. Pull them into Make, Zapier or n8n via Apify's native integrations, call `run-sync-get-dataset-items` from any HTTP client (see the `curl` example above), or use the [Apify MCP server](https://apify.com/apify/actors-mcp-server) to let an LLM agent drive this Actor and read results directly.

#### Why this Actor?

Airbnb scrapers are notorious for flaky runs and messy nested output. This one is built around three choices: (1) it reads the same structured payloads Airbnb's own site renders from, not brittle HTML selectors; (2) every record is one flat object with stable field names — no digging through `sections[12].section.cardData`; (3) blocks and rate limits are detected and reported with the partial results you already paid for, instead of a crashed run.

#### Anti-blocking notes

Airbnb aggressively blocks datacenter and shared IPs. **Residential proxies are strongly recommended** — set `proxyConfiguration` to Apify residential (the default prefill). The Actor uses a fixed browser User-Agent, randomized 1–2.5 s delays between requests, and low concurrency (default 2; up to 8 as an aggressive opt-in). A 403/429/challenge response stops the run gracefully and keeps everything collected so far.

#### Use cases

- Market and pricing research for short-term rentals (STR analytics)
- Competitive sets for property managers and revenue managers
- Feeding availability/pricing data into investment models
- Monitoring specific listings (price, rating, review count over time)

#### FAQ

**Is it legal to scrape Airbnb?**
The Actor only reads publicly visible listing data — the same data any logged-out visitor sees. Review Airbnb's terms and your local regulations for your use case; you are responsible for how you use the data.

**Why do I get fewer results than Airbnb claims exist?**
Airbnb itself only serves ~15 pages (~270 listings) per query. The Actor splits price ranges to go past that; extremely dense markets may still need narrower filters (dates, room type).

**Why are prices totals, not per night?**
With `checkIn`/`checkOut` set (or when Airbnb picks default dates), listing cards show stay totals — `pricePer` tells you which one you got. Divide by nights for a nightly rate.

**The run says "blocked" — what now?**
Switch to residential proxies, lower concurrency to 1, and retry. Partial results are kept.

**Can I filter by property type (house, apartment, guesthouse, ...) instead of room type?**
Not currently. `roomType` (entire home / private room / shared room / hotel room) is a confirmed, documented-by-reverse-engineering raw filter on Airbnb's search page. A separate "property type" facet (house vs. apartment vs. guesthouse) does not have a similarly discoverable raw query param on the public search page — Airbnb only exposes that facet through its interactive UI, not a stable URL param we could verify. `propertyType` is still returned per-listing in the output (e.g. `"Entire rental unit"`) — it just isn't a request-side filter.

**How reliable is `calendarMonths`?**
It replays an internal, unauthenticated Airbnb GraphQL persisted query (`PdpAvailabilityCalendar`) using a known-good operation hash — live-verified working as of 2026-07. Unlike the amenities count (whose operation hash is rediscovered from a JS bundle on every run), this hash is not currently re-discoverable at runtime from any bundle we could find referenced by the listing page, so it's a static snapshot. If Airbnb ever rotates it, calendar fetches fail closed (best-effort — the rest of the record is unaffected) and `calendar` comes back `null` for that run until the Actor is updated.

**How reliable are `reviews`?**
Same best-effort footing as `calendarMonths`: reviews come from an internal, unauthenticated Airbnb GraphQL persisted query using a known-good operation hash. If Airbnb rotates that hash the review fetch fails closed (`reviews` comes back `null` for that run) — the rest of each record is unaffected, and the run still succeeds. Reviews are opt-in (`includeReviews`) and capped by `maxReviewsPerListing` to keep runs cost-bounded.

**Something broken or missing?**
Open an issue on the Actor's **Issues** tab — it is monitored and fixes ship fast.

#### Attribution

See `NOTICE`. Price-range-splitting pagination strategy inspired by [digital-engineering/airbnb-scraper](https://github.com/digital-engineering/airbnb-scraper) (GPL-3.0) — **algorithm inspiration only, no code copied, translated or derived**. All code in this Actor was written from scratch against Airbnb's current site (2026) and is MIT-licensed.

#### Fast setup and source code

[Public repository](https://github.com/Exdenta/OinkAIJobSearch) · [Agent setup skill](https://github.com/Exdenta/OinkAIJobSearch/blob/main/.agents/skills/public-apify-actors/SKILL.md).

Use the Actor’s current input form for filters, or start with its documented API example. Select the `latest` build. Read the dataset together with the run summary: a successful status alone does not show that every source was reached.

Restrictive filters or repeat-delivery suppression can produce zero results.

#### Product guides and related tools

- [Product overview and public links](https://jobatlas.dev/actors/directory/property#nomad-agent-airbnb-scraper)
- [Public setup guide](https://github.com/Exdenta/jobatlas/blob/main/docs/public-actors-setup.md)

#### Current costs

Current Actor event rates, checked 2026-10-16. USD; use the **Pricing** tab for your plan and later changes.

| Event | Free | Bronze | Silver | Gold | Platinum | Diamond |
|---|---:|---:|---:|---:|---:|---:|
| Listing result (`result`) | $0.0002 | $0.0002 | $0.00015 | $0.0001 | $0.0001 | $0.0001 |
| Actor start (`actor-start`) | $0.00005 | $0.00005 | $0.00005 | $0.00005 | $0.00005 | $0.00005 |

For example, 100 × `result`, 1 × `actor-start` totals **$0.02005 in Actor event charges on Free**. This is an arithmetic example, before any waiver; actual charged events depend on the run and selected options. It is not a promise of output or a charge for simply setting an item cap.

Your total is the charged Actor events, plus platform usage **only if this Actor’s Pricing tab bills it separately**, plus any external provider you use with your own key. Do not add platform usage twice when it is included. Apify credits and plan discounts affect your invoice. Set a run cost limit in Console before starting.

***

**Independent tool.** We built and run this Actor ourselves. Airbnb does not operate, sponsor or endorse it, and its name is used only to say which service the data comes from.

# Actor input Schema

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

search = scrape listings for a location; detail = resolve listing URLs/ids to full records.

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

Where to search, as you would type it on airbnb.com (e.g. <code>Lisbon, Portugal</code>, <code>Brooklyn, NY</code>). Required in search mode.

## `latitude` (type: `number`):

Optional. Search mode: centre latitude for a coordinate/map search that bypasses named-location geocoding. Set together with <code>longitude</code>; then <code>location</code> is optional. Best-effort — drives Airbnb's map-search bounding box.

## `longitude` (type: `number`):

Optional. Search mode: centre longitude for a coordinate/map search. Set together with <code>latitude</code>.

## `maxLocationDeviation` (type: `number`):

Optional. Search mode: half-width in degrees of the map box around <code>latitude</code>/<code>longitude</code> (~0.05° ≈ 5.5 km). Only used when latitude+longitude are set.

## `listingUrls` (type: `array`):

Listings to fetch in detail mode — full https://www.airbnb.com/rooms/... URLs or bare numeric ids.

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

Optional check-in date (YYYY-MM-DD). With checkOut set, prices become stay totals for those dates.

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

Optional check-out date (YYYY-MM-DD).

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

Lower bound for the nightly price filter. 0 = no bound.

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

Upper bound for the nightly price filter. 0 = no bound.

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

Number of adult guests. 0 = Airbnb default.

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

Number of child guests.

## `roomType` (type: `string`):

Filter by room type.

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

Only show listings with at least this many bedrooms. 0 = no filter.

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

Only show listings with at least this many beds. 0 = no filter.

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

Only show listings with at least this many bathrooms. 0 = no filter.

## `calendarMonths` (type: `integer`):

Detail mode only. Fetch this many months of day-level availability per listing (starting from checkIn's month, or the current month) and summarize it into the <code>calendar</code> output field. 0 = skip (default), up to 12. Best-effort against an internal, unauthenticated Airbnb endpoint — may silently return nothing if Airbnb changes it.

## `includeReviews` (type: `boolean`):

Detail mode only. Also fetch per-listing guest reviews into the <code>reviews</code> output field (author, date, rating, text, host response). Off by default. Best-effort against an internal Airbnb endpoint; cost-bounded by <code>maxReviewsPerListing</code>.

## `maxReviewsPerListing` (type: `integer`):

Cap on reviews fetched per listing when <code>includeReviews</code> is on. Keeps review scraping cost-bounded (reviews are paged 50 at a time).

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

Hard cap on listings returned. Search mode auto-splits price ranges to reach it past Airbnb's ~270-result cap.

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

ISO currency code for returned prices (USD, EUR, GBP, ...).

## `concurrency` (type: `integer`):

Parallel listing fetches in detail mode. Default 2. Values above 4 (up to 8) are an aggressive opt-in — faster, but Airbnb rate-limits hard, so use residential proxies and expect more blocks. Keep low if in doubt.

## `maxPriceSplits` (type: `integer`):

How many times a search is allowed to auto-split its price range to get past Airbnb's ~270-result cap (search mode). Higher = more complete results for huge markets, at the cost of more requests. Lower it to cap cost for dense locations.

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

Airbnb frequently blocks datacenter IPs — residential proxies are strongly recommended.

## `dedupe` (type: `object`):

Suppress confirmed repeat deliveries for the same Apify user and search.

## Actor input object example

```json
{
  "mode": "search",
  "location": "Lisbon, Portugal",
  "maxLocationDeviation": 0.05,
  "priceMin": 0,
  "priceMax": 0,
  "adults": 0,
  "children": 0,
  "roomType": "any",
  "minBedrooms": 0,
  "minBeds": 0,
  "minBathrooms": 0,
  "calendarMonths": 0,
  "includeReviews": false,
  "maxReviewsPerListing": 10,
  "maxItems": 20,
  "currency": "USD",
  "concurrency": 1,
  "maxPriceSplits": 2,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "dedupe": {
    "enabled": true,
    "key": ""
  }
}
```

# Actor output Schema

## `dataset` (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": "Lisbon, Portugal",
    "maxItems": 20,
    "concurrency": 1,
    "maxPriceSplits": 2,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    },
    "dedupe": {
        "enabled": true,
        "key": ""
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nomad-agent/airbnb-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "location": "Lisbon, Portugal",
    "maxItems": 20,
    "concurrency": 1,
    "maxPriceSplits": 2,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
    "dedupe": {
        "enabled": True,
        "key": "",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("nomad-agent/airbnb-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "location": "Lisbon, Portugal",
  "maxItems": 20,
  "concurrency": 1,
  "maxPriceSplits": 2,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "dedupe": {
    "enabled": true,
    "key": ""
  }
}' |
apify call nomad-agent/airbnb-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nomad-agent/airbnb-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/3bs4HXTse68yuJO5a/builds/P7GgQgU8YEkPJv9ff/openapi.json
