# Airbnb Scraper - Listings, Prices & Coordinates (`santhej/airbnb-search-scraper`) Actor

Scrape Airbnb listings for any destination. Extract nightly prices, discounts, ratings, reviews, GPS coordinates and room types. Export JSON/CSV.

- **URL**: https://apify.com/santhej/airbnb-search-scraper.md
- **Developed by:** [Santhej Kallada](https://apify.com/santhej) (community)
- **Categories:** Travel, Real estate
- **Features:** Limited permissions
- **Stats:** 7 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 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 — Listings, Prices, Ratings & Coordinates

**Scrape Airbnb search results for any destination and get clean, structured listing rows with total and nightly prices, discounts, ratings, review counts, GPS coordinates and photos. No API key, no login, no proxy setup. $1.50 per 1,000 listings.**

### What does Airbnb Scraper do?

Give it a city, region or country and it collects the listings Airbnb shows for that search, page by page, removing duplicates as it goes. Add check-in and check-out dates, guest counts, a price range or room types to scrape exactly the search a traveller would see.

- **Airbnb listings by destination**: any city, region or country, up to 30 destinations per run.
- **Total and nightly prices**: the price for the whole stay plus the nightly rate from Airbnb's price breakdown.
- **Discounts**: original (strike-through) price and an `isDiscounted` flag.
- **Ratings and review counts**: split into separate numeric fields.
- **GPS coordinates**: latitude and longitude for every listing.
- **Property details**: property type and area, bedrooms, badges such as "Guest favorite", and photo URLs.
- **Filters**: dates, adults and children, minimum and maximum price, and room type.

### Use cases

- **Short-term rental pricing**: see what comparable listings charge for your dates.
- **Market supply analysis**: count listings, property types and price bands per city.
- **Investment research**: combine coordinates with price to map rates by neighbourhood.
- **Competitor tracking**: watch a set of listings' prices and discounts over time with a scheduled run.

### How to use Airbnb Scraper

1. Enter one or more **Destinations**, e.g. `Lisbon, Portugal` or `Austin, TX`.
2. Set **Check-in date** and **Check-out date** if you want prices for a specific stay, and the number of **Adults** and **Children**.
3. Optionally add a **Minimum price**, **Maximum price** and **Room types**.
4. Set **Max listings per destination** (Airbnb shows about 270 at most per search).
5. Click **Start**, then export the dataset as JSON, CSV or Excel, or read it through the Apify API.

#### Example input

```json
{
  "locations": ["Lisbon, Portugal", "Porto, Portugal"],
  "checkIn": "2027-04-12",
  "checkOut": "2027-04-17",
  "adults": 2,
  "maxItems": 100,
  "minPrice": 50,
  "maxPrice": 400,
  "roomTypes": ["Entire home/apt"]
}
```

#### Input configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `locations` | array of strings | required | Destinations to search, up to 30 per run. |
| `maxItems` | integer | `100` | Unique listings to collect **per destination**, 1 to 1,000. Airbnb caps a search at about 270, so higher values return everything available. |
| `checkIn` | string (YYYY-MM-DD) | empty | Check-in date. |
| `checkOut` | string (YYYY-MM-DD) | empty | Check-out date. |
| `adults` | integer | empty | Adult guests, 1 to 16. |
| `children` | integer | empty | Child guests, 0 to 15. |
| `minPrice` | integer | empty | Minimum price, passed to Airbnb's own price filter. |
| `maxPrice` | integer | empty | Maximum price, passed to Airbnb's own price filter. |
| `roomTypes` | array of strings | all | Any of `Entire home/apt`, `Private room`, `Shared room`, `Hotel room`. |
| `country` | string | `us` | Two-letter country the request is made from. Controls the currency and language Airbnb returns (`us` = USD, English). |
| `concurrency` | integer | `3` | Destinations processed at once, 1 to 6. |
| `pageConcurrency` | integer | `6` | Result pages fetched in parallel per destination, 1 to 10. |

`maxItems` applies per destination, so two destinations at 100 each can return up to 200 listings.

#### Example output

```json
{
  "listingId": "30180055",
  "name": "Guida Mouraria Apartment",
  "title": "Apartment in Santa Maria Maior",
  "url": "https://www.airbnb.com/rooms/30180055",
  "totalPrice": 585,
  "priceDisplay": "$585",
  "originalPrice": null,
  "isDiscounted": false,
  "priceQualifier": "for 5 nights",
  "pricePerNight": 116.9,
  "currency": "$",
  "rating": 4.97,
  "reviewCount": 453,
  "ratingLabel": "4.97 (453)",
  "isNew": false,
  "latitude": 38.71292,
  "longitude": -9.1342,
  "roomType": "1 bedroom",
  "badges": ["Guest favorite"],
  "images": ["https://a0.muscache.com/im/pictures/..."],
  "checkIn": "2027-04-12",
  "checkOut": "2027-04-17",
  "searchLocation": "Lisbon, Portugal",
  "sourcePage": 1,
  "scrapedAt": "2026-09-23T03:34:02.758Z"
}
```

| Field | Description |
|---|---|
| `listingId` | Airbnb's room ID, a stable key for tracking a listing over time. |
| `name` | Listing name as the host wrote it. |
| `title` | Property type and area, e.g. "Apartment in Santa Maria Maior". |
| `url` | Direct `airbnb.com/rooms/…` link. |
| `totalPrice` / `priceDisplay` / `priceQualifier` | Price for the stay as a number, as displayed (`$585`), and what it covers (`for 5 nights`). |
| `originalPrice` / `isDiscounted` | Strike-through price and discount flag when the host is discounting. |
| `pricePerNight` | Nightly rate from Airbnb's price breakdown. |
| `currency` | Currency symbol taken from the displayed price. |
| `rating` / `reviewCount` / `ratingLabel` | Average rating, number of reviews, and the raw label. |
| `isNew` | `true` for listings with no reviews yet. |
| `latitude` / `longitude` | GPS coordinates. |
| `roomType` | First detail line Airbnb shows, usually the bedroom count ("1 bedroom", "2 bedrooms"). |
| `badges` | Labels Airbnb shows on the card, such as "Guest favorite". |
| `images` | Photo URLs. |
| `checkIn` / `checkOut` | The dates the price applies to. |
| `searchLocation` / `sourcePage` / `scrapedAt` | The destination searched, the results page and the collection time. |

A run summary (listings, pages fetched, empty destinations, blocked pages) is saved to the run's key-value store as `OUTPUT`.

### How much does Airbnb Scraper cost?

Pay per event. You pay for unique listings returned.

| Event | Free / Bronze plan | Silver plan | Gold plan and above |
|---|---|---|---|
| Listing returned (unique) | $0.0015 | $0.00135 | $0.0012 |
| Zero-result destination (Airbnb returned no listings at all) | $0.002 | $0.0018 | $0.0016 |
| Actor start (once per run) | $0.0005 | $0.00045 | $0.0004 |

Worked examples at Free/Bronze prices:

- 1 destination, 60 listings: 60 × $0.0015 + $0.0005 = **$0.0905**
- 2 destinations, 200 listings each: 400 × $0.0015 + $0.0005 = **$0.6005**
- 1,000 listings across several destinations: **$1.50** + $0.0005

Duplicates, blocked pages and redirected pages are never billed. There is no subscription.

### Things worth knowing

- **Set dates when you compare prices.** Without dates, Airbnb quotes each listing for dates it picks itself (shown in `checkIn` / `checkOut`), so prices are not like-for-like. With dates, every listing is priced for your stay.
- **Airbnb caps a search at roughly 270 listings** (15 pages of 18). To go deeper, split a city into neighbourhoods or use price bands.
- **Price filters are Airbnb's own.** `minPrice` / `maxPrice` are applied by Airbnb to its nightly price, which can differ slightly from the `pricePerNight` breakdown when a discount applies.
- **`country` controls currency and language.** It defaults to `us` (USD, English). Set it to match the market you're researching.

### FAQ

**Do I need an Airbnb API key or account?**
No. There is nothing to register, no login and no cookies.

**Are duplicate listings billed?**
No. Airbnb repeats listings across pages; results are de-duplicated on `listingId` and only unique listings are charged.

**How many listings can I get per destination?**
Around 270, because Airbnb shows at most 15 pages of 18 per search. Split a city into neighbourhoods or price bands to go further.

**What happens if Airbnb redirects or blocks a request?**
It is retried automatically, and a page that still fails is skipped without charge. Runs report `blocked_pages` in `OUTPUT`.

**Can I get prices in a different currency?**
Yes. The `country` option decides where the request comes from, which determines the currency and language Airbnb returns.

**Can I run this on a schedule?**
Yes. Save your input as a task and add an Apify schedule for recurring rate monitoring, or trigger it from your own pipeline through the API.

### Support

Open an issue on the Actor's Issues tab and I'll take a look.

# Actor input Schema

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

Where to search, e.g. 'Lisbon, Portugal' or 'Austin, TX'. One per line. Up to 30 per run.

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

How many unique listings to collect for EACH destination. Airbnb caps a search at roughly 270 listings, so higher values return everything available rather than erroring.

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

YYYY-MM-DD. Leave empty for undated results. Prices are only shown when dates are set.

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

YYYY-MM-DD. Leave empty for undated results.

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

Number of adult guests.

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

Number of child guests.

## `minPrice` (type: `integer`):

Only return listings at or above this nightly price. Leave empty for no minimum.

## `maxPrice` (type: `integer`):

Only return listings at or below this nightly price. Leave empty for no maximum.

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

Restrict to specific room types. Leave empty for all.

## `country` (type: `string`):

Two-letter country code used when fetching. Controls the currency and language Airbnb returns. Defaults to 'us'.

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

How many destinations to process at once. 3 suits most runs.

## `pageConcurrency` (type: `integer`):

Pages fetched in parallel within one destination. Higher is substantially faster.

## Actor input object example

```json
{
  "locations": [
    "Lisbon, Portugal"
  ],
  "maxItems": 100,
  "country": "us",
  "concurrency": 3,
  "pageConcurrency": 6
}
```

# Actor output Schema

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

All scraped Airbnb listings.

## `summary` (type: `string`):

Destinations, listing counts and pages fetched.

# 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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("santhej/airbnb-search-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"] }

# Run the Actor and wait for it to finish
run = client.actor("santhej/airbnb-search-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"
  ]
}' |
apify call santhej/airbnb-search-scraper --silent --output-dataset

```

## MCP server setup

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