# Airbnb Scraper (`steadyscrape/airbnb-scraper`) Actor

Scrape Airbnb listings by location or search link: prices for your dates, ratings, hosts, amenities, house rules, cancellation policy, coordinates, photos and availability calendar. Reads whole cities past Airbnb's 270-result limit. No login, no browser.

- **URL**: https://apify.com/steadyscrape/airbnb-scraper.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** Travel, Real estate
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

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

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

## How to integrate an Actor?

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

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

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

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

# README

### What does Airbnb Scraper do?

**Airbnb Scraper** extracts **Airbnb listings for any location or search link** — with the **real price for your dates**, ratings, Superhost and Guest favorite badges, coordinates, photos, bedrooms and baths — and, when you want them, **each listing's full page** (description, every amenity, host profile, house rules, cancellation policy, category ratings) and its **availability calendar** with minimum nights. It talks to the same API Airbnb's own site uses: no login, no browser, no proxies, and a page of 18 listings takes about a second.

**It reads whole cities.** Airbnb never pages past 270 results for one search, which is why other scrapers return "243 of 2,000". This one splits the map into cells until each fits, and returns every listing in the area, once.

### Why use it?

- 🏙️ **Market analysis** — every listing of a city or neighborhood with price, rating and occupancy signals, for investors, property managers and revenue managers.
- 💲 **Price monitoring** — schedule it with your dates to track what competitors charge for the same stay; totals include Airbnb's fees.
- 📅 **Availability and minimum-stay tracking** — the calendar tells which days are bookable and the shortest stay each host accepts.
- 🗺️ **Short-term rental research** — density of listings per area, share of entire homes vs rooms, Superhost ratio, hosts with many listings.
- 🤖 **Feed dashboards, sheets and AI agents** — JSON, CSV or Excel, or straight into Google Sheets, Slack or Make through Apify integrations.

### Features

- ✅ **By place or by link** — type `Lisbon, Portugal`, or paste any Airbnb search link with your filters and the map area you dragged to.
- ✅ **Full coverage** — beyond Airbnb's 270-result limit: the whole map area, cell by cell, each listing once.
- ✅ **Prices for your dates** — total, per night, original price before discounts, currency of your choice on every run. Without dates, you get the dates Airbnb priced each listing for.
- ✅ **Filters** — guests, price range, room type, bedrooms, beds, bathrooms.
- ✅ **Listing details** — description, all amenities with availability, host (Superhost, verified, rating, response rate, years hosting, co-hosts), house rules, safety, cancellation policy for your dates, category ratings, rating distribution, review tags, neighborhood notes, all photos with captions, sleeping arrangement, instant book, pets.
- ✅ **Availability calendar** — up to 12 months, day by day, with check-in/check-out rules and minimum/maximum nights.
- ✅ **Honest data** — where Airbnb resolved your search (`resolvedLocation`), listings not available for your dates say so, and nothing is guessed.
- ✅ **Fair billing** — you pay per listing. Searches Airbnb refuses or that return nothing are reported in the run summary and **not charged**; a listing found by two searches is charged once.

### How to scrape Airbnb listings

1. Click **Try for free**.
2. Type **locations** or paste **search links**.
3. Set **check-in and check-out** to get real prices and only available places. Choose your **currency**.
4. Optionally turn on **Include listing details** and set **Availability calendar months**.
5. Click **Start** and download the listings as JSON, CSV or Excel. To monitor, add a [schedule](https://docs.apify.com/platform/schedules).

### Input example

```json
{
    "locations": ["Lisbon, Portugal"],
    "searchUrls": ["https://www.airbnb.com/s/Porto--Portugal/homes?checkin=2026-11-06&checkout=2026-11-09&adults=2&price_max=150"],
    "checkIn": "2026-11-06",
    "checkOut": "2026-11-09",
    "adults": 2,
    "currency": "EUR",
    "roomTypes": ["Entire home/apt"],
    "maxListingsPerSearch": 0,
    "fullCoverage": true,
    "includeDetails": true,
    "calendarMonths": 3
}
```

### Output example

Each listing is one item in the dataset (details, calendar and photos shortened here):

```json
{
    "id": "1427417218567220620",
    "url": "https://www.airbnb.com/rooms/1427417218567220620",
    "title": "The Scenic Perch",
    "placeType": "Apartment in Santa Maria Maior",
    "searchLocation": "Lisbon, Portugal",
    "resolvedLocation": "Lisbon",
    "latitude": 38.713,
    "longitude": -9.1319,
    "rating": 4.86,
    "reviewsCount": 84,
    "isSuperhost": true,
    "isGuestFavorite": true,
    "badges": ["Guest favorite"],
    "bedrooms": 1,
    "beds": 1,
    "bathrooms": 1,
    "roomInfo": ["1 bedroom", "1 double bed", "1 bath"],
    "price": {
        "total": 351,
        "originalTotal": 383,
        "perNight": 127.57,
        "currency": "USD",
        "nights": 3,
        "checkIn": "2026-11-02",
        "checkOut": "2026-11-05",
        "label": "$351 USD for 3 nights"
    },
    "freeCancellation": false,
    "photos": ["https://a0.muscache.com/im/pictures/hosting/Hosting-1427417218567220620/original/d2757cb1-69dd-4a1c-961c-bc79b70b3314.png"],
    "scrapedAt": "2026-09-18T02:21:47.921Z",
    "details": {
        "propertyType": "Entire rental unit",
        "description": "Perched within the historic walls of Castelo São Jorge, this bright apartment offers elevated views over Alfama’s rooftops…",
        "personCapacity": 3,
        "overview": ["3 guests", "1 bedroom", "1 bed", "1 bath"],
        "highlights": ["Self check-in", "Unbeatable location", "At-home coffee"],
        "amenities": [{ "group": "Bathroom", "name": "Hair dryer", "available": true }, { "group": "Not included", "name": "Washer", "available": false }],
        "host": {
            "id": "697089575",
            "name": "Jardim Do Castelo",
            "isSuperhost": true,
            "isVerified": true,
            "reviewsCount": 298,
            "rating": 4.81,
            "yearsHosting": 1,
            "responseRate": "100%",
            "responseTime": "Responds within an hour",
            "about": null,
            "highlights": [],
            "coHosts": []
        },
        "houseRules": ["Check-in after 3:00 PM", "Checkout before 11:00 AM", "Self check-in with smart lock", "3 guests maximum", "No pets", "Quiet hours (10:00 PM - 6:00 AM)", "No smoking"],
        "safety": ["Carbon monoxide alarm installed", "Smoke alarm installed"],
        "cancellationPolicy": "Free cancellation for 24 hours. After that, the reservation is non-refundable.",
        "canInstantBook": false,
        "petsAllowed": false,
        "categoryRatings": { "cleanliness": 4.9, "accuracy": 4.9, "checkin": 4.7, "communication": 4.9, "location": 4.8, "value": 4.8 },
        "ratingDistribution": { "1": 0, "2": 0, "3": 0, "4": 14.3, "5": 85.7 },
        "reviewTags": [{ "name": "VIEW", "count": 37 }, { "name": "LOCATION", "count": 52 }],
        "address": "Lisbon, Portugal",
        "locationDescriptions": [],
        "locationVerified": false,
        "images": [{ "url": "https://a0.muscache.com/im/pictures/hosting/Hosting-1427417218567220620/original/95954831-d6ba-4e10-ae8b-723ad4cbe17b.png", "caption": null }],
        "sleepingArrangement": [{ "room": "Bedroom", "beds": "1 double bed" }],
        "isNewListing": false,
        "availableForDates": true
    },
    "calendar": [{ "date": "2026-11-02", "available": true, "availableForCheckIn": true, "availableForCheckOut": true, "minNights": 2, "maxNights": 90 }],
    "minNights": 2
}
```

### Output fields

| field | meaning |
|---|---|
| `id`, `url`, `title`, `placeType` | The listing, its page, its name and Airbnb's headline ("Apartment in Lisbon"; empty for map-area searches). |
| `searchLocation`, `resolvedLocation` | What you searched, and where Airbnb took it (a misspelled place resolves to some city: check this). |
| `latitude`, `longitude` | Coordinates as the search shows them (approximate until the listing page, which is exact for verified locations). |
| `rating`, `reviewsCount`, `isSuperhost`, `isGuestFavorite`, `badges` | Rating out of 5 (`null` for a new listing) and Airbnb's badges. |
| `bedrooms`, `beds`, `bathrooms`, `roomInfo` | Parsed from the listing summary; `bedrooms` is 0 for a studio and `null` when Airbnb does not say. |
| `price` | `total` for the stay, fees included; `originalTotal` before a host discount; `perNight`; `nights`; the `checkIn`/`checkOut` the price is for; `null` when the listing is not available for the dates. |
| `freeCancellation` | Whether the search advertised free cancellation. |
| `photos` | The search's photos; `details.images` has all of them, with captions. |
| `details` | With **Include listing details**: see the example above. `availableForDates` is `null` without dates. |
| `calendar`, `minNights` | With **Availability calendar months**: every day from the current month, and the smallest stay accepted on any available day. |
| `scrapedAt` | UTC ISO 8601. |

The run's **SUMMARY** record (key-value store) lists, per search, how many listings it produced, how many requests it took, where Airbnb resolved it, and any search that was refused or empty.

### Limits and tips

- Airbnb pages **270 listings per search**. With **Full coverage** on (default), a place beyond that is read by map cells: expect a few hundred search requests for a big city. **Area scale** decides how far around the place's center the cells go (3 covers a city).
- **Dates change everything**: with dates you get real totals and only available listings; without them Airbnb prices each listing for dates it picks, reported per listing.
- Prices are **totals for the stay, fees included**, the way Airbnb shows them; `perNight` is Airbnb's nightly rate from the breakdown when it gives one.
- Details and calendars cost one request each per listing; 40 listings with both took about 30 seconds.
- A misspelled or unknown place is not an error on Airbnb: it answers with some city. `resolvedLocation` tells you which.

### Is it legal to scrape Airbnb?

This Actor reads only data Airbnb shows publicly to anyone, without logging in, and does not collect personal data beyond what hosts publish on their listings. Scraping public data is generally legal; still, make sure your use complies with Airbnb's terms and the laws that apply to you, and use it responsibly. Read Apify's [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) guide.

### Your feedback

Missing a field or a filter? Open an issue on the **Issues** tab: issues are answered, and the Actor is checked against the live site so it keeps working when Airbnb changes.

# Actor input Schema

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

Places to search, as you would type them on Airbnb: <code>Lisbon, Portugal</code>, <code>Brooklyn, NY</code>, <code>Bali</code>.

## `searchUrls` (type: `array`):

Airbnb search links, with every filter they carry (dates, guests, price, room type, amenities, and the map area when you moved the map). A link's own filters win over the fields below.

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

<code>YYYY-MM-DD</code>. With dates, prices are the real totals for that stay and the listings are the available ones. Without dates, Airbnb prices each listing for dates of its own choosing, which the output reports.

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

<code>YYYY-MM-DD</code>, after check-in.

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

Guests aged 13 or more.

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

Guests aged 2 to 12.

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

Guests under 2.

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

Pets travelling with the guests.

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

3-letter code for every price in the output: <code>USD</code>, <code>EUR</code>, <code>GBP</code>…

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

In the currency above; 0 means no minimum.

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

In the currency above; 0 means no maximum.

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

Leave empty for all.

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

0 means no minimum.

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

0 means no minimum.

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

0 means no minimum.

## `maxListingsPerSearch` (type: `integer`):

Stop each location or link after this many listings. 0 means all of them.

## `fullCoverage` (type: `boolean`):

Airbnb pages through at most 270 listings per search. When a place has more, read its whole map area cell by cell instead, so every listing is returned. Costs more search requests; turn off to get only Airbnb's top 270.

## `areaScale` (type: `integer`):

For full coverage of a place: the map area Airbnb centers on the place, with each side multiplied by this. 1 is just the center; 3 (default) covers a city; 5 or more covers its surroundings too. Ignored for links with their own map area.

## `includeDetails` (type: `boolean`):

Read each listing's page too: description, all amenities, host profile, house rules, safety, cancellation policy for your dates, category ratings, rating distribution, review tags, neighborhood notes, all photos with captions, sleeping arrangement. One extra request per listing.

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

Read each listing's availability day by day for this many months from now (0 = none): available, check-in and check-out allowed, minimum and maximum nights. One extra request per listing.

## Actor input object example

```json
{
  "locations": [
    "Lisbon, Portugal"
  ],
  "searchUrls": [],
  "adults": 1,
  "children": 0,
  "infants": 0,
  "pets": 0,
  "currency": "USD",
  "priceMin": 0,
  "priceMax": 0,
  "roomTypes": [],
  "minBedrooms": 0,
  "minBeds": 0,
  "minBathrooms": 0,
  "maxListingsPerSearch": 50,
  "fullCoverage": true,
  "areaScale": 3,
  "includeDetails": false,
  "calendarMonths": 0
}
```

# Actor output Schema

## `listings` (type: `string`):

No description

## `summary` (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 = {
    "locations": [
        "Lisbon, Portugal"
    ],
    "searchUrls": [],
    "maxListingsPerSearch": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/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 = {
    "locations": ["Lisbon, Portugal"],
    "searchUrls": [],
    "maxListingsPerSearch": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/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 '{
  "locations": [
    "Lisbon, Portugal"
  ],
  "searchUrls": [],
  "maxListingsPerSearch": 50
}' |
apify call steadyscrape/airbnb-scraper --silent --output-dataset

```

## MCP server setup

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