# Airbnb Search Scraper (`assuring_team/airbnb-search-scraper`) Actor

Airbnb scraper for prices, ratings, beds, baths, coordinates and real availability. Skips listings that aren't free on your dates, and beats Airbnb's ~270-result limit by searching the map in tiles: 1,596 listings from one town instead of 270. Any city, any country.

- **URL**: https://apify.com/assuring\_team/airbnb-search-scraper.md
- **Developed by:** [Taha El Bahi](https://apify.com/assuring_team) (community)
- **Categories:** Travel, Real estate, E-commerce
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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 — prices, real availability & full-city coverage

Scrape Airbnb search results into clean, structured data: nightly and total prices, ratings and
review counts, bedrooms, beds and baths, coordinates, and property type — for any city in the world.

Two things make this scraper different from the others:

- **Only places that are genuinely free on your dates.** Airbnb pads its results with listings that
  are already booked, quoting them for a *different* stay instead. Ask for 17 nights and you get
  11- and 16-night rows mixed in. This actor removes them.
- **It gets past Airbnb's ~270-listing limit.** Airbnb never returns more than about 270 results for
  a single search, however many properties exist. Turn on **Full coverage** and the actor splits the
  map into tiles and searches each one, then merges and de-duplicates. One small town returned
  **1,596 listings instead of 270**.

It is also fast and cheap: results are read straight from the page, without running a browser, so a
full city costs a fraction of what a browser-based scraper does.

### What you get

| Field | Description |
|---|---|
| `position` | Airbnb's own ranking within that search |
| `name` | The listing's real title |
| `propertyType` | e.g. "Apartment in Martil" |
| `url` | Direct link to the listing |
| `checkIn`, `checkOut`, `nights` | The stay actually priced |
| `price`, `pricePerNight`, `currency` | Total and per-night |
| `rating`, `reviewsCount` | |
| `bedrooms`, `beds`, `baths` | Handles "1 double bed", studios and private rooms |
| `latitude`, `longitude` | |
| `badges` | e.g. "Guest favourite", "Superhost" |
| `searchUrl` | Which search produced the row |

Turn on **Fetch listing details** and each row also gets `maxGuests` (the exact number of guests the
place sleeps), `detailedPropertyType`, `sharedBath`, and the listing page's own price with its full
breakdown.

### How to use it

**By city name** — simplest:

```json
{
  "searchText": "Barcelona",
  "checkIn": "2026-08-02",
  "checkOut": "2026-08-09",
  "adults": 2,
  "maxItems": 100
}
```

**By search URL** — for filters you set on airbnb.com yourself:

```json
{
  "searchUrls": [{ "url": "https://www.airbnb.com/s/Paris--France/homes?room_types%5B%5D=Entire%20home%2Fapt" }],
  "checkIn": "2026-08-02",
  "checkOut": "2026-08-09"
}
```

Paste a URL you copied from Airbnb and **leave the date and guest fields empty** — whatever you
picked on the site is kept. Fill them in only when you want to override the URL; the run log tells
you when that happens.

**Whole city:**

```json
{ "searchText": "Martil", "fullCoverage": true, "maxItems": 0, "maxTiles": 60 }
```

### Useful settings

| Setting | What it does |
|---|---|
| `exactDatesOnly` | Drop listings that aren't free on your dates (on by default) |
| `fullCoverage` + `maxTiles` | Split the map to beat the ~270 cap |
| `minRating`, `minBedrooms`, `minBeds`, `minGuestCapacity` | Filters |
| `propertyType` | Keep only apartments, riads, villas, etc. |
| `proxyCountry` | Airbnb prices and ranks by visitor location — pin one for consistent results |
| `useHttpFastPath` | Fast mode, on by default; falls back to a browser automatically |
| `currency`, `locale` | Keep language English for reliable bed/bath counts |

### Good to know

- **The top of the results is stable; the tail reshuffles.** Four identical requests seven seconds
  apart returned 17 of the same 18 listings with an identical top five, but 10-13 of the lower
  positions moved. Treat high ranks as meaningful and low ranks as approximate. `position` records
  the rank as returned.
- **Results depend on where the request appears to come from.** Rotating proxy IPs change the
  apparent location and produce genuinely different result sets, which is a far bigger effect than
  the reshuffling above. Pin `proxyCountry` if you want runs to be comparable.
- **This is the anonymous view of Airbnb.** Logged-in guests also get personalised results based on
  their booking history - someone who books cheaper places is steered toward cheaper listings. No
  scraper can see that, so treat this data as the baseline every guest starts from, not as what any
  particular guest sees.
- Running the same search twice and de-duplicating on `listingId` still gives slightly better
  coverage than a single run.
- **Listing titles change between runs** for the same property. Always key on `listingId`.
- **Search cards and listing pages sometimes quote different totals.** Enable *Fetch listing details*
  to also get the listing page's own price, which is what a guest would actually pay.
- Set `proxyCountry` to the market you care about — which taxes and fees are included in a displayed
  total depends on where the visitor appears to be.

### Disclaimer

This is an independent tool and is not affiliated with, endorsed by, or connected to Airbnb, Inc.
Only public data is collected. You are responsible for how you use the data and for complying with
applicable terms and laws.

# Actor input Schema

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

Search on airbnb.com with your filters applied, then copy the URL from the address bar and paste it here. This is the most precise way to search.

## `searchText` (type: `string`):

e.g. "Fes Morocco" or "riads in Marrakech". Used only when no Search URL is given — the Airbnb search URL is built automatically.

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

Check-in date (YYYY-MM-DD). Empty = keep the date already in the URL.

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

Check-out date (YYYY-MM-DD). Empty = keep the date already in the URL. Set both dates or neither.

## `defaultNights` (type: `integer`):

Leave the dates above empty and Airbnb quotes every listing for a different window of its own choosing, so the prices cannot be compared. Instead the actor pins one stay this many nights long, about a month out, and prices every listing for it. Set to 0 to let Airbnb choose per listing.

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

Number of adults. 0 = keep whatever the pasted URL already says.

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

Number of children (ages 2-12). 0 = keep whatever the pasted URL already says.

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

Number of infants (under 2). 0 = keep whatever the pasted URL already says.

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

Number of pets. 0 = keep whatever the pasted URL already says.

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

Stop after this many listings, counted across all your search URLs. Set 0 for no limit. Note that with Full coverage on you usually want 0 - a small number here makes the run stop early and defeats the point of covering the whole city.

## `maxPagesPerSearch` (type: `integer`):

Airbnb itself caps search results at about 15 pages / 270 listings.

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

Airbnb never returns more than ~270 listings for one search, however many exist. Switch this on and the run splits the map into tiles and searches each one separately, then merges and de-duplicates — the only way to get a whole city. Set Max listings to 0 for unlimited. Costs one search per tile.

## `maxTiles` (type: `integer`):

Hard ceiling on how many map tiles a full-coverage run may create, so a dense city cannot run away with your budget.

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

Only keep listings with at least this many bedrooms. Guest capacity is already handled by the Adults/Children fields above — Airbnb filters the search itself, so every result fits your party. Use this to additionally demand a certain size. 0 = no filter.

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

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

## `minGuestCapacity` (type: `integer`):

Only keep listings that officially sleep at least this many guests. Airbnb does not put capacity in search results, so switching this on makes the run open every listing's own page — much slower and more expensive, but the number is exact rather than inferred. Note that the Adults/Children fields already make Airbnb filter by capacity on its own, so you usually do not need this. 0 = no filter.

## `exactDatesOnly` (type: `boolean`):

Airbnb pads its results with listings that are already booked on your dates, quoting them for a nearby stay instead — so a 17-night search comes back with 11- or 16-night rows. Leave this on to drop those. Turn it off to also see the alternative-date suggestions. Only applies when both dates are set.

## `fetchListingDetails` (type: `boolean`):

Opens every listing's own page to collect the guest capacity, the exact bedroom/bed/bath counts Airbnb states there, the precise property type (e.g. "Private room in rental unit") and whether the bathroom is shared. Costs one extra page load per listing, so a run takes roughly 10–15× longer. Turned on automatically when a min guest capacity is set.

## `minRating` (type: `number`):

Only keep listings rated at least this (0–5). Listings with no rating yet are excluded when this is set. 0 = no filter.

## `propertyType` (type: `string`):

Only keep listings of this type. Matched against Airbnb's own label, e.g. "Riad in Fes".

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

Currency all prices are returned in.

## `locale` (type: `string`):

Page language. Affects the wording of scraped text fields.

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

Residential proxies are strongly recommended — datacenter IPs get blocked fast.

## `proxyCountry` (type: `string`):

Browse as if from this country. Airbnb ranks results and shows totals differently per country, so pick the one you normally browse from to get the same order and prices you see yourself. Leave empty for a random country (results will drift between runs).

## `useHttpFastPath` (type: `boolean`):

Airbnb puts the search results straight into the page's HTML, so a plain download gets the same data as a full browser — roughly 6x faster and 20x cheaper. Any page this cannot fetch automatically falls back to the browser, so results are unaffected. Turn off only to force the browser for everything.

## `httpConcurrency` (type: `integer`):

How many pages to download at once in fast mode. Plain downloads are light, so this can be far higher than a browser allows. Lower it if Airbnb starts blocking.

## `delayBetweenRequests` (type: `integer`):

Wait time after each page. Higher = slower but less likely to get blocked. 0 = no delay.

## Actor input object example

```json
{
  "searchUrls": [
    {
      "url": "https://www.airbnb.com/s/Fes--Morocco/homes"
    }
  ],
  "defaultNights": 1,
  "adults": 0,
  "children": 0,
  "infants": 0,
  "pets": 0,
  "maxItems": 200,
  "maxPagesPerSearch": 15,
  "fullCoverage": false,
  "maxTiles": 60,
  "minBedrooms": 0,
  "minBeds": 0,
  "minGuestCapacity": 0,
  "exactDatesOnly": true,
  "fetchListingDetails": false,
  "minRating": 0,
  "propertyType": "",
  "currency": "USD",
  "locale": "en",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "proxyCountry": "",
  "useHttpFastPath": true,
  "httpConcurrency": 15,
  "delayBetweenRequests": 0
}
```

# 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 = {
    "searchUrls": [
        {
            "url": "https://www.airbnb.com/s/Fes--Morocco/homes"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("assuring_team/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 = { "searchUrls": [{ "url": "https://www.airbnb.com/s/Fes--Morocco/homes" }] }

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

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

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

```

## CLI example

```bash
echo '{
  "searchUrls": [
    {
      "url": "https://www.airbnb.com/s/Fes--Morocco/homes"
    }
  ]
}' |
apify call assuring_team/airbnb-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=assuring_team/airbnb-search-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/nVW40klDUgS3k82gv/builds/gEuTIas2DiNf9MjlW/openapi.json
