# 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
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## 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.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Airbnb Scraper — Listings, Prices, Ratings & Coordinates

Scrape Airbnb search results for any destination. Give it a city and get clean, structured listing rows — no API key, no login, no proxy setup.

**$1.50 per 1,000 listings.** One flat rate on every plan, including free.

### Features

- **Scrape Airbnb listings by destination** — any city, region or country
- **Extract Airbnb nightly prices and total stay prices**
- **Find discounted Airbnb listings** — original price and discount flag captured
- **Get Airbnb ratings and review counts** — split into separate numeric fields
- **Extract Airbnb GPS coordinates** — latitude and longitude per listing
- **Scrape Airbnb room types** — entire home, private room, shared room, hotel room
- **Filter Airbnb listings by price range** — minimum and maximum nightly rate
- **Search Airbnb by check-in and check-out dates** — prices reflect the exact stay
- **Set guest counts** — adults and children
- **Export Airbnb data to JSON, CSV or Excel** — or pull it from the API

### What you get

| Field | Description |
|---|---|
| `listingId` | Airbnb's room ID — stable key for tracking a listing over time |
| `name` | Listing title as the host wrote it |
| `url` | Direct `airbnb.com/rooms/…` link |
| `totalPrice` | Price for the whole stay, as a number |
| `originalPrice` / `isDiscounted` | Strike-through price and discount flag when the host is discounting |
| `pricePerNight` | Nightly rate parsed from the price breakdown |
| `priceDisplay` / `priceQualifier` | `$1,146` and `for 5 nights`, as Airbnb shows them |
| `currency` | Currency symbol detected from the price |
| `rating` / `reviewCount` | Average rating and number of reviews, split into separate numbers |
| `isNew` | True for listings with no reviews yet |
| `latitude` / `longitude` | GPS coordinates |
| `roomType` | "1 bedroom", "Entire home", etc. |
| `badges` | "Guest favourite", "Superhost", … |
| `images` | Photo URLs |
| `checkIn` / `checkOut` | Dates the prices apply to |

Plus `searchLocation`, `sourcePage` and `scrapedAt`.

### Example input

```json
{
  "locations": ["Lisbon, Portugal", "Porto, Portugal"],
  "checkIn": "2026-11-23",
  "checkOut": "2026-11-28",
  "adults": 2,
  "maxItems": 200,
  "minPrice": 50,
  "maxPrice": 400
}
```

`maxItems` applies **per destination**, so two destinations at 200 each returns up to 400 listings.

### What it's good for

- **Short-term rental pricing** — see what comparable listings charge on your dates
- **Market supply analysis** — how many listings, what types, what price bands per city
- **Investment research** — pair coordinates with price to map yield by neighbourhood
- **Competitor tracking** — watch a set of listings' prices and discounts over time

### Things worth knowing

- **Prices only appear when you set dates.** Airbnb shows a total for a specific stay; without `checkIn`/`checkOut` you get listings and ratings but sparse pricing. Set dates if price is what you care about.
- **Airbnb caps a search at roughly 270 listings** (15 pages × 18). Asking for more returns everything available, not an error. To go deeper, split a city into neighbourhoods or use price bands.
- **Duplicates are removed before you are billed.** Airbnb repeats listings across pages; we deduplicate on `listingId` and only charge for unique ones.
- **You are not billed for blocked or redirected pages.** If Airbnb bounces the request to a country domain, it's retried automatically and never charged.
- **Empty destinations cost $0.002.** A destination returning nothing still requires a page fetch, so it carries a small zero-result charge. Destinations that return listings never do.
- **`country` controls currency and language.** It defaults to `us` (USD, English). Set it to match the market you're researching.

### Pricing

| Event | Price |
|---|---|
| Listing returned | **$0.0015** ($1.50 per 1,000) |
| Zero-result destination | $0.002 |
| Actor start | $0.0005 |

Flat across every Apify plan — no tier gating.

### Output example

```json
{
  "listingId": "1739902164963861734",
  "name": "THE miniPENTHOUSE terrace & SPA",
  "url": "https://www.airbnb.com/rooms/1739902164963861734",
  "totalPrice": 1146,
  "originalPrice": 1273,
  "isDiscounted": true,
  "pricePerNight": 254.49,
  "priceDisplay": "$1,146",
  "priceQualifier": "for 5 nights",
  "rating": 5,
  "reviewCount": 243,
  "latitude": 38.7121,
  "longitude": -9.1288,
  "roomType": "1 bedroom",
  "searchLocation": "Lisbon, Portugal"
}
```

### FAQ

**Do I need an Airbnb API key or account?**
No. Nothing to register, no login, no cookies.

**Why are some prices missing?**
Airbnb only shows a price for a specific stay. Set `checkIn` and `checkOut` and every listing returns a price; without dates, pricing is sparse by design.

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

**How many listings can I get per destination?**
Around 270 — Airbnb itself caps a search at roughly 15 pages of 18. To go deeper, split a city into neighbourhoods or use price bands.

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

**Can I get prices in a different currency?**
Yes — the `country` option controls the exit location, which determines the currency and language Airbnb returns.

**Can I run this on a schedule?**
Yes — use Apify's scheduler for recurring rate monitoring, or trigger it from your own pipeline via 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/G6MvUJTBjBxqc4pOa/openapi.json
