Airbnb Search Scraper - Prices, Ratings & Photos avatar

Airbnb Search Scraper - Prices, Ratings & Photos

Pricing

from $0.80 / 1,000 listings

Go to Apify Store
Airbnb Search Scraper - Prices, Ratings & Photos

Airbnb Search Scraper - Prices, Ratings & Photos

Export public Airbnb listings with numeric prices, ratings, photos and map coordinates. Search cities or paste a search URL with your filters. Automatic price splitting reaches beyond one search's page cap. Failed and empty inputs are free.

Pricing

from $0.80 / 1,000 listings

Rating

0.0

(0)

Developer

Sumitr Mardy

Sumitr Mardy

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 hours ago

Last modified

Categories

Share

Airbnb Search Scraper

Export public Airbnb search listings with numeric prices, ratings, photos and map coordinates. Search a city or paste an Airbnb search URL with filters. Automatic price splitting expands coverage beyond a single search's page cap.

This independent actor is not affiliated with or endorsed by Airbnb. It reads public search results only.

Quick start

{
"locations": ["Lisbon"],
"checkIn": "2026-11-28",
"checkOut": "2026-12-01",
"adults": 2,
"currency": "USD",
"maxListings": 100,
"splitByPrice": true
}

Dates are optional; update dated examples before running them. The small daily Store example uses Lisbon without dates and at most 20 listings.

Input

FieldDefaultBehavior
locationsRequiredPlace names or full https://www.airbnb.com/s/ search URLs. Up to 50 effective searches; duplicates removed.
checkIn, checkOutEmptyBoth or neither, YYYY-MM-DD, check-out after check-in.
adults21–16 adults.
currencyUSDThree-letter code; always added when a pasted URL does not specify currency.
minPrice, maxPriceEmptyOptional per-night filters in the effective search currency.
maxListings100Maximum unique listings per location, capped at 5,000.
splitByPricetrueSplit full result sets into narrower nightly price buckets.

Pasted URLs retain their filters, including room types, map bounds, dates, guests and price limits; existing URL values take precedence over the corresponding input defaults. The page cursor is reset so coverage starts on page one. The actor accepts Airbnb.com search URLs, not arbitrary websites or room-detail URLs.

Coverage and price splitting

One Airbnb search exposes up to 15 pages, usually 18 cards per page, with repeated listings. A platform spike on 2026-10-29, Lisbon with a three-night stay on December 10–13, returned 209 unique listings from one 15-page search. Price splitting returned 1,000 unique listings, then stopped at its configured limit; seven buckets remained. This is a measured comparison, not a total inventory count.

For a full search, the actor reads the first and last pages. If page 15 has 18 cards, it splits the price range rather than reading the parent's remaining 13 pages. The shortcut matched a complete 15-page baseline in the spike. It is a heuristic tied to Airbnb's pagination, not a proof of exhaustiveness.

Buckets split until complete, one currency unit wide, or bounded by your listing limit or the internal work guard. Inclusive boundary overlap is deduplicated by listing id. Unbounded searches start with 0–1,000 and a higher-price tail; the tail is expanded as needed, so expensive listings are not silently discarded at 1,000. Small limits up to 36 can be filled directly without probing the last page.

Output

One row per unique listing per input location. All keys are always present, never null; missing strings are "", numbers 0, arrays []. Numeric zero for a missing price or rating does not mean the listing is free.

FieldsMeaning
inputIndex, input, locationOriginal input position/value and search location.
listingId, urlDecoded DemandStayListing id and canonical listing link; propertyId is not used.
name, title, summaryHost listing name, search-card type/area and available room summary.
latitude, longitudeCoordinates exposed in the public card; may be approximate.
rating, reviewsCount, isNewParsed numeric rating/review count; new or unrated cards use 0/0 and isNew=true.
badges, isGuestFavorite, isSuperhostAvailable public badge text and flags.
priceTotal, priceOriginal, pricePerNight, nightsAdvertised search total, original total when supplied, derived average per night, and stay length.
currency, priceLabelEffective requested currency and original public price label.
checkIn, checkOut, adultsEffective explicit search dates and guest count. Dates remain empty when you did not set them.
photos, thumbnailPublic search-card image URLs and first image.
searchUrl, pageNumberExact bucket/page URL and page position within that search.
status, subStatus, error, scrapedAtResult status, machine-readable detail, error and UTC ISO timestamp.

The nightly price is total divided by stay length, rounded to two decimals; it is not a separately verified base rate. Without dates Airbnb can choose a default stay, such as five nights. The actor parses that displayed stay length and total; it does not assume the price is for tonight. Photos, badges and fields depend on the public card. Unidentifiable cards with no usable listing id are skipped to preserve reliable deduplication; if all cards lack ids, the actor emits a free parse_error row.

status / subStatusListing charge
ok / listingCharged
no_results / no_resultsFree empty search
failed / invalid_inputFree
failed / http_CODE, blocked, parse_error, network_errorFree
failed / free_work_limitFree; internal free-work guard stopped the search
failed / cost_limit_reachedFree; your event spending cap was reached

If a later page fails, saved listings remain and a free terminal failure row explains the stop.

Pricing

One listing event per saved unique listing per location, with all available search-card fields included. FREE $0.0015, BRONZE $0.0012, SILVER $0.001, GOLD and above $0.0008 per listing ($1.50 / $1.20 / $1.00 / $0.80 per 1,000). Default Actor start fee: $0.00005 per GB, minimum one event. Failed and empty rows have no listing charge; the start fee still applies. No dataset-item surcharge.

The actor saves one batch per page, then charges for that batch. It honors your maximum charge and bounds unpaid work.

Honest limits

  • Public search only: no host contact data, room-detail extraction, calendar availability or review collection.
  • Prices are what the search page shows for that stay and currency. Fees, taxes, discounts and availability can change; verify booking details on Airbnb.
  • A single search is capped at 15 pages. Splitting improves coverage but cannot guarantee all listings in a city, including dense one-unit buckets or inventory hidden by ranking and availability.
  • Results change by dates, filters, currency, geography, ranking and time. Repeated runs can differ.
  • Public field paths can change. Missing fields use stable sentinels; absent/unparseable embedded state produces a free parse_error and is not retried.
  • No login, API key, residential proxy, browser automation or fingerprint spoofing is used for collection. A 403/429 gets one direct retry after backoff, then at most one Apify datacenter proxy attempt if available.
  • Pages and locations are processed sequentially. Hard request deadlines, a recursion bound and a free-work guard limit unproductive work.

API examples

curl -X POST \
"https://api.apify.com/v2/acts/sumitr_mardy~airbnb-search-scraper/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"locations":["Lisbon"],"maxListings":20,"currency":"USD"}'
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("sumitr_mardy/airbnb-search-scraper").call(
run_input={"locations": ["Lisbon"], "maxListings": 20, "currency": "USD"}
)
for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
print(listing["name"], listing["pricePerNight"], listing["currency"])

Enrich listings with amenities, host fields and category ratings

Pass the listingId values from successful search rows to Airbnb Listing Details. It returns public amenities, photos, host profile fields, six numeric category ratings and star distribution in one stable schema. Join both datasets by listingId. The Details actor does not return prices; keep the search price fields when combining them.

Use it from AI agents (MCP)

Connect through Apify MCP using hosted OAuth sign-in:

{"mcpServers":{"airbnb-search":{"url":"https://mcp.apify.com/?tools=sumitr_mardy/airbnb-search-scraper"}}}

For Bearer-auth clients, configure your own token locally:

{"mcpServers":{"airbnb-search":{"url":"https://mcp.apify.com/?tools=sumitr_mardy/airbnb-search-scraper","headers":{"Authorization":"Bearer <YOUR_APIFY_TOKEN>"}}}}

For stdio clients with Node.js:

{"mcpServers":{"airbnb-search":{"command":"npx","args":["-y","@apify/actors-mcp-server","--actors","sumitr_mardy/airbnb-search-scraper"],"env":{"APIFY_TOKEN":"<YOUR_APIFY_TOKEN>"}}}}

Agent tips: start with 20 listings, inspect status, use future dates, compare prices only for equivalent stays/currencies, and disclose that split coverage is bounded. To export more of the same city, raise maxListings and keep splitByPrice=true.

Support: Actor issues.