Airbnb Listings Scraper - Prices, Ratings & Photos
Pricing
from $0.38 / 1,000 listings
Airbnb Listings Scraper - Prices, Ratings & Photos
Airbnb listings scraper: type a city, add dates and guests, and get up to 20 listings per place with name, type, star rating, review count, the price Airbnb shows and what it covers, map coordinates and photos. $0.40 per 1,000 listings.
Pricing
from $0.38 / 1,000 listings
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
0
Monthly active users
8 days ago
Last modified
Categories
Share
Name a city or a destination, optionally give your dates and who is coming, and get one row per Airbnb listing from its search: the listing id, the name, the property type, the star rating, the review count, the price Airbnb showed, the map coordinates and up to five photos.
This reads Airbnb's public search results, so it gives you a sample of a destination rather than its whole inventory. Twenty listings per location, five locations per run, and no paging past that.
| Input | City or destination names, up to 5 per run, with optional dates and guests |
| Output | One row per listing: id, name, type, rating, review count, the price shown and what it covers, coordinates, up to five photos |
| Ceiling | 20 listings per location, 5 locations per run |
| Account needed | None, and no Airbnb key |
| Price | $0.40 per 1,000 listings on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 12,500 |
🔍 What Airbnb Listings Scraper does
Each location string goes into Airbnb's own stays search the way you would type it: Toronto, Ontario, Canada, Lisbon, Big Sur, California.
Give it both dates and the prices come back for your actual stay. Give it neither and you get Airbnb's default view. One date on its own is rejected before any request goes out, because a half-specified search silently returns something else.
Every row carries the search that found it: searchLocation, checkIn, checkOut and adults, plus children and pets when you set them, so a multi-city run stays joinable back to your own list.
Children and pets narrow the search the way they do on Airbnb itself: only homes that hold everyone, or allow pets, come back.
There is a wall-clock budget on the whole run. When it runs out, the locations still waiting get a DEADLINE row rather than being dropped in silence.
📋 What data you get from each Airbnb listing
| What you get | Field |
|---|---|
| Airbnb's listing id and the link | listingId, listingUrl |
| The name and the card's heading, which carries the type and the place | name, propertyType |
| Star rating and number of reviews | rating, reviewCount |
| The price as Airbnb shows it, the number in it, the currency and what it covers | price, priceAmount, currency, priceQualifier, priceAccessibilityLabel |
| Airbnb's badges and the space line: bedrooms, beds, baths | badges, spaceDetails |
| Approximate map position | latitude, longitude |
| Up to five photos | photoUrls |
| The search that found it | searchLocation, checkIn, checkOut, adults, children, pets |
▶️ How to scrape Airbnb listings
- Open Airbnb Listings Scraper and click Try for free.
- Type your destinations into Locations, one per line, up to five.
- Fill in Check-in date and Check-out date together if you want prices for real dates.
- Set Adults, and Children or Pets if they are coming, then click Start.
- Download the dataset as JSON, CSV or Excel, or read it from the Apify API.
Leave Locations empty and you get one labelled sample row instead of a real run, not charged.
💰 How much does it cost to scrape Airbnb?
$0.40 per 1,000 listings on the Free plan. Paid plans pay a little less: $0.395 on Starter, $0.39 on Scale and $0.385 on Business. On the free plan, the $5 Apify gives you each month covers about 12,500 listings.
You pay per listing row delivered. The sample row, diagnostic rows and listings already seen in the same run are all free, and a run that returns no listings is not charged.
📥 What you give it
{"locations": ["Toronto, Ontario, Canada", "Montreal, Quebec, Canada"],"checkIn": "2026-11-10","checkOut": "2026-11-14","adults": 2,"children": 1,"maxItemsPerLocation": 20}
| Field | Default | What it is |
|---|---|---|
locations | none, the form starts at Toronto, Ontario, Canada | City, region or destination names. Up to 5 are used and the rest are ignored. Leave it empty and you get one labelled sample row instead of a real run. |
checkIn, checkOut | none | YYYY-MM-DD. Supply both or neither, with check-out after check-in. |
adults | 2 | Guests sent to the search, 1 to 16. |
children | 0 | Children aged 2 to 12, 0 to 16. They count as guests, so only homes that hold everyone come back. |
pets | 0 | 0 to 5. Only homes that allow pets come back, and some add a pet fee to the price. |
currency | none | USD, EUR, GBP, CAD, AUD, JPY, CHF, MXN, BRL or INR. Empty lets Airbnb pick. |
locale | none | The language the cards come back in: en, fr, de, es, it, pt, nl or ja. Listing names can come back machine-translated. |
maxItemsPerLocation | 20 | Listings kept per location. 20 is both the default and the ceiling. |
deadlineSecs | 90 | Wall-clock budget for the whole run, 15 to 180 seconds. |
Give it both dates or neither. One on its own stops the run with a single BAD_INPUT row, and no locations are searched.
A location string that is empty or longer than 160 characters stops the whole run, not just that one entry. Check the list before a long batch.
📤 What you get back
A real row, a four-night search with one pet, with the photo list cut short:
{"ok": true,"recordType": "listing","listingId": "1002992424634465181","name": "Lower penthouse with free parking downtown","propertyType": "Condo in Downtown Toronto","rating": 4.96,"reviewCount": 114,"price": "$772","priceAmount": 772,"currency": null,"priceQualifier": "for 4 nights","priceAccessibilityLabel": "$772 for 4 nights","badges": ["Guest favorite"],"spaceDetails": ["1 bedroom", "1 queen bed", "1 bath"],"latitude": 43.6522,"longitude": -79.3708,"photoUrls": ["https://a0.muscache.com/im/pictures/airflow/Hosting-1002992424634465181/original/d2d7f1d2-...jpg", "..."],"listingUrl": "https://www.airbnb.com/rooms/1002992424634465181","searchLocation": "Toronto, Ontario, Canada","checkIn": "2026-11-10","checkOut": "2026-11-14","adults": 2,"pets": 1,"source": "airbnb_public_search_html"}
| Field | How to read it |
|---|---|
price, priceAmount | The card's display text, and the first number pulled out of it. |
priceQualifier | Airbnb's own wording for what that price covers. Read it before you treat priceAmount as a nightly rate: on the row above it is a four-night total. |
priceAccessibilityLabel | The longer label Airbnb writes for screen readers. It is where a struck-through original price shows up. |
currency | Filled when the price text carries a three-letter code, or a symbol only one currency uses (€, £, R$, ₹, Fr.). A bare $ leaves it null. Set currency in the input if you need to know. |
children, pets | On rows from a search that set them. |
propertyType | The card's heading, such as Condo in Downtown Toronto. It carries the place as well as the type. |
latitude, longitude | Airbnb's approximate pin. It is deliberately fuzzy until a booking is made. |
listingId | Airbnb's numeric id. Use it to dedupe across runs. |
🧾 Reading the output
Three kinds of row can land in your dataset.
| Row | How to spot it | Charged |
|---|---|---|
| A listing | recordType: "listing" and no _sample | yes |
| The sample row | _sample: true | no |
| A diagnostic | recordType: "diagnostic" and a code | no |
Filter on _sample being absent, not on recordType. The free sample row also carries recordType: "listing". Note the diagnostic field is code, not errorCode.
| Code | What it means |
|---|---|
BAD_INPUT | One date without the other, check-out not after check-in, a location string that was empty or far too long, or a children, pets, currency or language value Airbnb does not take. The run stops there, before any search. |
NO_RESULTS | The search page loaded and held no new listings for that location. One more comes at the end when the whole run saved nothing. |
TARGET_ERROR | The search page came back without listings the run could read. A place with no homes at all can end up here too; if it should have homes, report it. |
NOT_SERVED | This listing was not served this run. Re-run it later. Until 12 October 2026 this code was called BLOCKED. |
NOT_FOUND | The search URL answered 404. |
NETWORK | Airbnb could not be reached, or the request ran out of time. |
DEADLINE | The run's wall-clock budget ran out before this location. Raise deadlineSecs or search fewer places. |
One failed location does not stop the others, and a diagnostic row never fails the run.
💡 What people use it for
- Checking what a city is charging for your dates before setting your own price.
- Sampling several neighbourhoods or nearby towns in one run and comparing the rating spread.
- Pulling coordinates and ratings for a map of where the well-reviewed stays cluster.
- Watching a destination on a schedule, with the same dates each time, to see the price move.
- Giving a model a small clean table of real listings instead of a page of search HTML.
🚧 What it does not do
- No host details. Host name, superhost status and response rate are not on the search cards and are not in these rows.
- No amenities, no availability calendar, no house rules, no per-listing reviews.
- No infants setting. Airbnb's search takes it, but in our tests it changed neither which homes came back nor their prices, so it would only look like filtering.
- No paging. Twenty per location is the ceiling, so this is a sample of a destination, not its inventory.
- Five locations per run. Anything after the fifth is dropped without a warning.
priceAmountis not always a nightly rate. It is whatever number leads the card text, andpriceQualifiersays what that covers.- Prices are the card's display value, before Airbnb's checkout adds fees and taxes.
- Coordinates are approximate. Airbnb fuzzes the pin until a stay is booked.
- Past dates are accepted and sent as given, which returns whatever Airbnb makes of them.
- Rows are a snapshot, and Airbnb search results move constantly.
- It is not an official Airbnb tool. Dami's Studio is independent and is not affiliated with or endorsed by Airbnb, or by any other company named on this page.
🧭 Which travel scraper do you need?
| If you want | Use |
|---|---|
| Airbnb listings with prices, ratings and coordinates for a place | This one |
| Hotels on Booking.com with live prices and scores for your dates | Booking.com Hotels Scraper |
| Live hotel prices for your dates, as Google Hotels shows them | Google Hotels Scraper |
❓ Questions people ask
Do I need an Airbnb account or API key?
No. It reads the public search pages.
Why is currency empty?
A bare $ does not say which dollar, so the field stays empty rather than being guessed. Set currency in the input when you need to be sure.
Can I get more than 20 listings for a city?
Not in one run. Search neighbourhoods separately, or vary the dates and guest count, and dedupe on listingId.
Why did my run stop after one row?
Almost always one date without the other, or a stray blank line in the locations list. The BAD_INPUT row says which.
Can I get the host's name?
Not from search results. Airbnb does not put it on the cards.
Can I call it from code or connect it to an AI assistant?
Yes. The API tab has ready-made code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/airbnb-listings-scraper. Either way the run happens on your Apify account at the same price.
Is scraping Airbnb listings legal?
These are public search results. Listings can carry personal data, which GDPR and similar laws cover, so have a reason for collecting it. Apify's write-up on the legality of web scraping is a good starting point, and we are not lawyers.
🆘 If something breaks
Open the Issues tab on the actor page. Send the run ID, the location and the dates you used. The code on the diagnostic row usually names the problem on its own.
