# Airbnb Scraper: Listing Details & Prices by Room URL (`humble-echidna/airbnb-scraper`) Actor

Get Airbnb listing details and prices from room URLs or ids, no login: title, type, beds, baths, guests, coordinates, rating and 6 sub-ratings, host, every amenity, house rules, photos. Add dates for availability, total, nightly rate and fee breakdown. One section missing never fails a listing.

- **URL**: https://apify.com/humble-echidna/airbnb-scraper.md
- **Developed by:** [Michael Costa](https://apify.com/humble-echidna) (community)
- **Categories:** Travel, Real estate
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.85 / 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.
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 does Airbnb Scraper do?

**Airbnb Scraper** turns **Airbnb listing URLs or ids** into one clean record per listing: the host's title, property
and room type, **bedrooms, beds, bathrooms** and guests, coordinates, **rating and the six category ratings**, the
host, **every amenity**, house rules, sleeping arrangements and all photos. Add check-in and check-out dates and each
listing also gets its **availability and price for that stay**: total before taxes, nightly rate and Airbnb's full
breakdown (discounts, fees). No login, no cookies, no Airbnb account. Unofficial; not affiliated with Airbnb.

It is **not** a search tool: Airbnb's robots.txt disallows its search pages for every crawler, so this actor reads
listings by their own link. Give it the listings you track (yours, your competitors', a market you study).

[Input fields](https://apify.com/humble-echidna/airbnb-scraper/input-schema) ·
[API](https://apify.com/humble-echidna/airbnb-scraper/api) ·
[Use it from Claude, ChatGPT or Cursor (MCP)](#can-i-use-airbnb-scraper-from-an-ai-agent-mcp)

**Jump to:** [Fields](#what-data-does-airbnb-scraper-return) ·
[Price](#how-much-does-it-cost-to-scrape-airbnb-listings) ·
[How to use](#how-to-scrape-airbnb-listings-and-prices) ·
[Input](#input) · [Output](#output) · [Switching](#switching-from-another-airbnb-actor) ·
[AI agents (MCP)](#can-i-use-airbnb-scraper-from-an-ai-agent-mcp) · [Limits](#limits) · [FAQ](#faq)

**Try it in one click:** the input comes pre-filled with two listings (a cabin in the Cotswolds and a flat in Paris).
That's 2 listings, or about $0.0096 (2 × $4.75/1,000, plus $0.00005 for the run start). **Then replace them with
the listings you want, and add dates for prices.**

### What data does Airbnb Scraper return?

| Field | Example | Notes |
|---|---|---|
| `title` | `cozy full renewed 2 Bdr Paris heart` | The host's own name for the listing |
| `propertyType`, `roomType` | `Entire rental unit`, `Entire home/apt` | |
| `bedrooms`, `beds`, `bathrooms` | `2`, `3`, `1.0` | Numbers; a studio is 0 bedrooms, half baths are `.5` |
| `personCapacity` | `6` | |
| `latitude`, `longitude` | `48.86301`, `2.34911` | Approximate unless `isExactLocation` |
| `rating`, `reviewCount`, `ratings` | `4.9`, `667`, `{"cleanliness": 4.89, ...}` | Six categories: accuracy, check-in, cleanliness, communication, location, value |
| `host` | `{"name": "Stéphane", "isSuperhost": true, "yearsHosting": 12, "responseRate": 100, ...}` | As the listing shows the host |
| `amenities`, `notIncluded` | `["Kitchen", "Wifi", ...]` | Also grouped in `amenityGroups` |
| `houseRules`, `safety` | `[{"rule": "No pets", ...}]` | With the host's own text (check-in times, quiet hours) |
| `photos` | `[{"url": "...", "room": "Living room"}]` | Every photo, with the room it shows |
| `available`, `unavailableReason` | `true`, `null` | Only with dates |
| `priceTotal`, `pricePerNight`, `nightlyRate` | `1254.39`, `418.13`, `428.85` | Only with dates; before taxes, in `currency` |
| `priceLines` | `[{"description": "Discount from Airbnb", "amount": -32.16}]` | Airbnb's breakdown |
| `missing` | `[]` | Fields Airbnb didn't show for this listing (left `null`) |

Every result has the same fields; the full list is under [Output](#output).

### How much does it cost to scrape Airbnb listings?

You pay per listing returned: **$4.75 per 1,000 listings** on Apify's Free plan, **$2.85** on Starter, **$2.35** on
Scale and **$1.85** on Business, plus $0.00005 each time a run starts. The price for your dates is included; there's
no extra charge for it or for host details.

- **The example below:** 2 listings × $4.75/1,000 = $0.0095, plus the start fee.
- **A month, for example:** a property manager checking 200 competitor listings with next weekend's dates every day
  is 6,000 listings ≈ **$17** on Starter.
- **Caps:** **Max results per run** in the input, and **Maximum cost per run** in the run options. The run stops
  cleanly at whichever comes first, and stops fetching as soon as the limit is covered.

**Never charged:** removed listings, search links and other lines that aren't a listing, requests Airbnb refuses, and
the same listing pasted twice (it's read once).

### How to scrape Airbnb listings and prices

1. Open Airbnb Scraper and click **Try for free** (or **Start** if you're signed in).
2. In **Airbnb listings**, paste one listing link per line (`https://www.airbnb.com/rooms/...`, any country's Airbnb
   domain) or just the ids.
3. Optional: set **Check-in date** and **Check-out date** (and guests) for availability and prices, and a currency.
4. Click **Start**, then open the **Output** tab and export as JSON, CSV or Excel.

### Example: a Paris flat for three nights

Input:

```json
{"listings": ["https://www.airbnb.com/rooms/2005815"], "checkIn": "2027-02-15", "checkOut": "2027-02-18", "adults": 2}
```

Output (real, from a live run on 2026-11-04; long lists shortened):

```json
{
  "id": "2005815",
  "url": "https://www.airbnb.com/rooms/2005815",
  "title": "cozy full renewed 2 Bdr Paris heart",
  "propertyType": "Entire rental unit",
  "roomType": "Entire home/apt",
  "summary": "Entire rental unit in Paris, France",
  "personCapacity": 6,
  "bedrooms": 2,
  "beds": 3,
  "bathrooms": 1.0,
  "locationName": "Paris, Île-de-France, France",
  "latitude": 48.86301,
  "longitude": 2.34911,
  "rating": 4.9,
  "reviewCount": 667,
  "ratings": {"accuracy": 4.91, "checkIn": 4.97, "communication": 5.0, "value": 4.82, "cleanliness": 4.89, "location": 4.92},
  "isGuestFavorite": true,
  "isSuperhost": true,
  "host": {"name": "Stéphane", "id": "10326336", "isSuperhost": true, "isVerified": true, "yearsHosting": 12,
           "monthsHosting": 11, "rating": 4.88, "reviewCount": 724, "responseRate": 100,
           "responseTime": "within a few hours"},
  "highlights": ["In the 1st, near Les Halles", "Quiet inside with a full kitchen", "Stéphane goes above and beyond"],
  "amenities": ["City skyline view", "Bathtub", "Hair dryer", "..."],
  "sleepingArrangements": [{"room": "Bedroom 1", "beds": "1 queen bed"}, {"room": "Bedroom 2", "beds": "1 double bed"}],
  "houseRules": [{"group": "House rules", "rule": "Up to 6 overnight guests", "details": null}, "..."],
  "photoCount": 20,
  "missing": [],
  "checkIn": "2027-02-15",
  "checkOut": "2027-02-18",
  "nights": 3,
  "adults": 2,
  "currency": "USD",
  "available": true,
  "priceTotal": 1254.39,
  "pricePerNight": 418.13,
  "nightlyRate": 428.85,
  "priceLabel": "$1,255 for 3 nights",
  "priceLines": [{"description": "3 nights x $428.85", "amount": 1286.55, "originalAmount": null},
                 {"description": "Discount from Airbnb", "amount": -32.16, "originalAmount": null}],
  "canInstantBook": false,
  "cancellationNote": "$0 today · Free cancellation before February 10",
  "maxGuests": 6
}
```

### Input

| Field | What it does |
|---|---|
| **Airbnb listings** (`listings`) | One listing link or id per line. `startUrls` (strings or `{"url": ...}`) is read too. |
| Check-in date (`checkIn`), Check-out date (`checkOut`) | YYYY-MM-DD. With both, every listing gets availability and price for the stay. Dates in a pasted link are used for that line when these are empty. |
| Adults, Children, Infants, Pets (`adults`, `children`, `infants`, `pets`) | Guests for the price. Adults default to 1. |
| Currency (`currency`) | 3-letter code, default `USD`. |
| Max results per run (`maxResults`) | Cap the number of listings (`maxItems` is read too). |

```json
{
  "listings": ["https://www.airbnb.com/rooms/20669368", "2005815"],
  "checkIn": "2027-02-15",
  "checkOut": "2027-02-18",
  "adults": 2,
  "currency": "EUR",
  "maxResults": 100
}
```

### Output

One record per listing, every field present on every record. Fields Airbnb doesn't show for a listing are `null` and
named in `missing`; without dates the price fields are `null`. The full field list with descriptions is on the
**Output** tab (dataset schema). `id` is Airbnb's listing id and stable across runs, so you can use it to
deduplicate or join runs. The run's `RUN_STATS` record lists every input line, what it returned and anything that
failed, with the reason.

### Switching from another Airbnb actor?

Most Airbnb actors take the same things under similar names. Here's where yours go:

| What you had | Put it here |
|---|---|
| Room links in `startUrls` (strings or `{"url": ...}` objects) | **Airbnb listings** (`listings`), one per line; `startUrls` itself is read too |
| `checkIn` / `checkOut`, `adults`, `children`, `infants`, `pets`, `currency` | The same names here |
| A cap like `maxItems` | **Max results per run** (`maxResults`); `maxItems` is read too |
| Search URLs or location queries ("London") | Not available: Airbnb's robots.txt disallows search pages. Paste the listings' own links |
| "Enrich host profiles" | Not needed for the listing's host card: name, Superhost, years hosting, rating and response rate are in `host`. Full profile pages aren't read |

The output is flat JSON with the usual names (`title`, `roomType`, `personCapacity`, `rating`, `reviewCount`,
`amenities`, `photos`), and price fields are plain numbers in your currency.

### Run it on a schedule, or from your own code

1. Save your input as a [task](https://docs.apify.com/platform/actors/running/tasks) (**Save as a new task**, top right
   of the actor page) and add it to a [schedule](https://docs.apify.com/platform/schedules) (Console → Schedules →
   **Create new**). Prices change daily, so a daily task with fixed dates tracks a stay's price over time.
2. Collect results: download the dataset as JSON, CSV or Excel; fetch the latest run's results from the
   [API](https://apify.com/humble-echidna/airbnb-scraper/api)
   (`GET https://api.apify.com/v2/actor-tasks/<task id>/runs/last/dataset/items?status=SUCCEEDED&format=csv`, with
   your API token); let a [webhook](https://docs.apify.com/platform/integrations/webhooks) tell your system when a
   run succeeds; or connect it to Make, Zapier or n8n through
   [Apify's integrations](https://docs.apify.com/platform/integrations).

#### Can I use Airbnb Scraper from an AI agent (MCP)?

Yes, through [Apify's MCP server](https://docs.apify.com/platform/integrations/mcp), from Claude, ChatGPT, Cursor or
any other MCP client. Add this to your client's MCP configuration (or let the agent find it with the server's actor
search); your client signs you in to Apify:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=humble-echidna/airbnb-scraper"
    }
  }
}
```

To use an [Apify API token](https://console.apify.com/settings/integrations) instead of signing in, add
`"headers": {"Authorization": "Bearer <APIFY_TOKEN>"}` next to `url`.

The agent passes the listing links someone gave it, with dates when price matters:
`{"listings": ["https://www.airbnb.com/rooms/20669368"], "checkIn": "2027-02-15", "checkOut": "2027-02-18"}`.

### Who it's for

Short-term rental hosts and property managers pricing against the listings around them; investors and analysts
comparing specific properties (beds, ratings, amenities, nightly rates); travel and relocation teams pricing a stay
across a shortlist; and AI agents that need to read an Airbnb link someone pasted.

### Why this one?

- **One changed section never fails a listing.** Each field is read on its own: if Airbnb renames a section, that
  field is `null` and named in `missing`, and everything else still comes back. A failed price lookup keeps the
  listing too.
- **The fields people ask for.** The host's real title (not a summary line), beds, bedrooms and bathrooms as numbers,
  the full description, the nightly rate and every line of the price breakdown, house rules with the host's own text.
- **Dates are honoured.** From the input, or from the link itself when you paste one with `check_in`/`check_out`.
- **Honest failures, never charged.** A removed listing, a search link or a refused request is named in the log and
  `RUN_STATS` with the reason, costs nothing, and never stops the rest of the run.
- **Polite.** It identifies itself honestly (User-Agent `HumbleEchidnaApify`), follows Airbnb's robots.txt, and reads
  at most 4 listings at a time.

### Limits

- **No search.** Airbnb's robots.txt disallows search pages (`/s/...`) for every crawler. Search, destination and
  short (`/h/...`) links fail with that reason; paste the listings' full links.
- **No reviews text, no availability calendar.** Review pages are disallowed by robots.txt; the listing's rating,
  review count and category ratings are included. For availability, ask for specific dates.
- **Prices are what a logged-out visitor sees**: before taxes, in the currency you choose, for the guests you set.
  Airbnb may show different prices to signed-in guests (member discounts) and changes them daily.
- **Location** is Airbnb's approximate point unless `isExactLocation` is `true`; the street address isn't public.
- **Host data** is what the listing's host card shows. Full host profiles and host photos aren't read.

### FAQ

#### Is it legal to scrape Airbnb?

This actor reads only what www.airbnb.com shows a visitor who isn't logged in, on a listing's own page and its booking
box. It never logs in, uses no account, cookie or session, follows Airbnb's robots.txt, and never tries to get past a
bot check (a refused request is reported, not retried around). Two things you should know before using the data:

- Airbnb's Terms of Service (section 11.1, [airbnb.com/help/article/2908](https://www.airbnb.com/help/article/2908))
  say: "Do not use bots, crawlers, scrapers, or other automated means to access or collect data or other content
  from or otherwise interact with the Airbnb Platform."
- Listing pages carry the host's first name and some host details. That can be personal data where you are: collect
  only what you have a lawful reason for.

Courts have treated reading public, logged-out pages differently from breaking into accounts, but the law depends on
where you are and what you do with the data; get your own legal advice for anything beyond personal research. If
you're Airbnb and want something changed or taken down, open an issue and it will be handled quickly.

#### Why did a line return nothing?

The run log and `RUN_STATS` say why, per line: the listing was removed (Airbnb answers "gone" or sends visitors to a
search page), the line is a search or short link, or Airbnb refused the request. Every other line in the run is
unaffected, and failed lines aren't charged. If a listing that opens fine in your browser fails with "Airbnb has
probably changed its listing pages", please open an issue with the input you used.

#### Why is the price empty for some listings?

The dates are booked or break the listing's rules (minimum stay, check-in days, pets): `available` is `false` and
`unavailableReason` gives Airbnb's message. Without dates, the price fields are always empty.

#### How is this different from Airbnb's official API?

Airbnb's API is only for approved partners (hosts' software and channel managers) and covers their own listings.
This actor reads any public listing by its link and needs no partnership.

### Related actors

| Actor | Use it when |
|---|---|
| [Dataset Diff](https://apify.com/humble-echidna/dataset-diff) | You re-check the same listings on a schedule and want what changed (prices, ratings) since the last run. |
| [Dataset Transform](https://apify.com/humble-echidna/dataset-transform) | You want a CSV with just the columns you need. |

### Feedback and support

Found a bug, or need a field that isn't here? Open an issue on the **Issues** tab with the input you used.

### Versions

Current version: **0.1**. See the Changelog tab for what changed in each version.

# Changelog

This Actor's version history is a separate document: https://apify.com/humble-echidna/airbnb-scraper/changelog.md

# Actor input Schema

## `listings` (type: `array`):

One listing per line: its link (https://www.airbnb.com/rooms/20669368; any Airbnb country domain and links with check_in/check_out work) or its id (20669368). Each line returns one listing. Search pages (/s/...) aren't read: Airbnb's robots.txt disallows them for every crawler, so paste the listings' own links. A line that isn't a listing, or a removed listing, is reported and not charged. Duplicates are read once.

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

Optional, YYYY-MM-DD (e.g. 2027-02-15), together with a check-out date. With dates, every listing also gets its availability and price for that stay: total before taxes, nightly rate, each line of Airbnb's price breakdown (discounts, cleaning and service fees) and the free-cancellation note. Without dates, you get the listing details only (and dates written in a pasted link are used for that line). Must be today or later.

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

Optional, YYYY-MM-DD (e.g. 2027-02-18), after the check-in date; stays of up to 365 nights.

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

Guests aged 13 or over, for the price (1-16). Leave empty for 1. Only used with dates.

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

Children aged 2-12, for the price (0-15). Only used with dates.

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

Infants under 2 (0-5). Only used with dates.

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

Pets (0-5). Only used with dates; a listing that doesn't allow pets then shows as unavailable.

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

3-letter code for prices, e.g. USD (the default), EUR, GBP, CAD, AUD, JPY, MXN or BRL. Airbnb converts the host's price itself.

## `maxResults` (type: `integer`):

Stop after this many listings, e.g. 20. Minimum 1; leave empty (the default) for no limit. The run also stops cleanly at the maximum cost per run you set in the run options, whichever comes first.

## Actor input object example

```json
{
  "listings": [
    "https://www.airbnb.com/rooms/20669368",
    "https://www.airbnb.com/rooms/2005815"
  ],
  "currency": "USD"
}
```

# Actor output Schema

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

No description

## `runStats` (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 = {
    "listings": [
        "https://www.airbnb.com/rooms/20669368",
        "https://www.airbnb.com/rooms/2005815"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("humble-echidna/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 = { "listings": [
        "https://www.airbnb.com/rooms/20669368",
        "https://www.airbnb.com/rooms/2005815",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("humble-echidna/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 '{
  "listings": [
    "https://www.airbnb.com/rooms/20669368",
    "https://www.airbnb.com/rooms/2005815"
  ]
}' |
apify call humble-echidna/airbnb-scraper --silent --output-dataset

```

## MCP server setup

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