Airbnb Images Scraper With Room Labels & True Location
Pricing
from $3.99 / 1,000 results
Airbnb Images Scraper With Room Labels & True Location
Pricing
from $3.99 / 1,000 results
Rating
0.0
(0)
Developer
Scraply
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
0
Monthly active users
9 days ago
Last modified
Categories
Share
Scrape the full Airbnb photo tour — not just the 8 preview images most Airbnb scrapers return — with every photo labeled by room (bedroom, kitchen, bathroom, exterior...), plus the listing's real country, region, city and GPS coordinates. Give it Airbnb room URLs, get a photo-by-photo, room-by-room breakdown of the listing back as structured JSON/CSV/Excel.
This actor is a superset of the base airbnb-images-scraper: every base input and every base output field (url, title, location, rating, reviews, images) still works exactly as before — this variant only adds new fields and inputs alongside them.
What does this Airbnb photo scraper do?
Most Airbnb scrapers stop at the handful of images embedded in the listing page's structured-data block — usually just 8, regardless of how many photos the host actually uploaded. This actor instead reads the listing's own photo-tour data and returns:
- Every photo in the tour (measured 22–126 photos per listing, vs. 8 from the base actor), each with its own direct image URL, id, orientation, aspect ratio and accessibility label.
- The room each photo belongs to —
roomNamefrom Airbnb's own room-tour breakdown (living room, bedroom 1, kitchen, pool, etc.), backed by Airbnb's own machine-generatedairbnbTagsas a fallback signal. - A per-room roll-up (
rooms[]) — how many photos exist for each room, so you can spot "1 photo of the bathroom, 27 of the exterior" at a glance. - The listing's true location — country, region, city, the exact location line Airbnb prints on the page, and latitude/longitude — independent of the base actor's
locationfield (which is preserved unchanged for backward compatibility, including its known limitation, see Honest caveats below). - Host captions where the host wrote one, plus their machine translation when Airbnb auto-translated it.
- Property type and overview facts (bedrooms/beds/baths/guests) as the denominator for judging how much photo coverage a listing has.
Use it for reshoot audits (which rooms are under-photographed), portfolio mapping (real coordinates instead of a hardcoded region), photo-tour QA for property managers, or building a room-labeled Airbnb photo dataset for research or ML training data.
Key features
- 📷 Full photo tour, not a fixed preview set — every photo the listing's photo-tour section serves, in one HTTP round-trip (no extra requests per photo).
- 🚪 Photo-to-room labeling —
roomName+ Airbnb's own room tags (airbnbTags), something no competing Airbnb photo/image scraper on Apify currently ships. - 🌍 Real location data — true country/region/city/breadcrumbs + coordinates, fixing the base actor's location field without breaking it.
- 🔎 Room filter — keep only photos matching a room keyword (e.g.
bedroom,kitchen,exterior,pool). - 🔢 Minimum-photos filter — drop thin listings (or surface only the richest ones) before you even look at the dataset.
- 🧾 Derived counts —
photoCount,captionedPhotoCount,roomCount,roomNames,isRoomBreakdownAvailable,photosMissingRoomLabelfor quick dataset scanning. - 🛡️ Automatic proxy fallback — starts without a proxy, switches to Apify Residential proxy on a detected block, and follows Airbnb's geo-redirect ("domain switch") page automatically so runs succeed from non-US egress too.
- ↩️ Backward compatible — a base-actor input (just
urls) still runs and returns the base's own 6 fields with identical values.
How to use
- Add one or more Airbnb room URLs (e.g.
https://www.airbnb.com/rooms/782682596976136912) to theurlsinput — one per line. - Leave
includePhotoDetailsandincludeTrueLocationon (both default totrue) to get the full photo tour, room labels and true location. Turn either off to get a lighter, base-only payload. - Optionally set
roomFilter(e.g.["bedroom", "pool"]) to keep only matching photos, and/orminPhotosto skip thin listings entirely. - Run the actor. Each input URL produces one dataset row; export it as JSON, CSV, or Excel from the Apify dataset UI.
This actor scrapes individual listing (room) pages — it does not accept a city/search query and does not paginate search results; each row corresponds to one Airbnb room URL you provide.
Input
{"urls": ["https://www.airbnb.com/rooms/782682596976136912"],"includePhotoDetails": true,"includeTrueLocation": true,"roomFilter": [],"minPhotos": 0}
| Input | Type | Default | Description |
|---|---|---|---|
urls | array (stringList) | — (required) | Airbnb room URLs, one per line. Must match https://www.airbnb.com/rooms/.... |
includePhotoDetails | boolean | true | Full photo tour + room labels + propertyType/overviewFacts/photo & room counts. Turn off for base-only (8-image) behavior. |
includeTrueLocation | boolean | true | True locationLine, country, region, city, breadcrumbs, latitude/longitude. |
roomFilter | array (stringList) | [] | Keep only photos whose room name or Airbnb room tag contains any of these words (case-insensitive substring match). Empty = keep all. Only applies when includePhotoDetails is on. |
minPhotos | integer | 0 | Drop the whole listing if its raw photo count (before roomFilter) is below this number. 0 = keep every listing. Only applies when includePhotoDetails is on. |
proxyConfiguration | object (proxy) | Apify Proxy off by default | Same as the base actor — proxy is only engaged automatically after a detected block. |
requestTimeoutSecs | integer | 30 | Per-request timeout in seconds (5–120). |
Output
[{"url": "https://www.airbnb.com/rooms/782682596976136912","title": "\"Perfect Getaway\" 2 Miles from MIA & 8To UR Cruise","locationLine": "Hialeah, Florida, United States","locationCountry": "United States","locationRegion": "Florida","locationCity": "Hialeah","locationBreadcrumbs": ["Homes", "United States", "Florida", "Hialeah"],"latitude": 25.857,"longitude": -80.278,"location": "Hialeah, Florida, United States","propertyType": "Entire guest suite","overviewFacts": ["4 guests", "1 bedroom", "2 beds", "1 bath"],"rating": 4.95,"reviews": 168,"photoCount": 44,"captionedPhotoCount": 15,"roomCount": 6,"roomNames": ["Bedroom", "Kitchen", "Bathroom", "Living room", "Exterior", "Pool"],"isRoomBreakdownAvailable": true,"photosMissingRoomLabel": 3,"images": ["https://a0.muscache.com/im/pictures/c6cbda16-164d-481c-99d4-9d3c6344986c.jpg"],"photos": [{"id": "1620294495","url": "https://a0.muscache.com/im/pictures/...jpg","roomName": "Bedroom","airbnbTags": ["Bedroom"],"caption": "Queen bed with garden view","captionTranslated": null,"accessibilityLabel": "Bedroom","orientation": "LANDSCAPE","aspectRatio": 1.5}],"rooms": [{ "roomName": "Bedroom", "photoCount": 8, "photoIds": ["1620294495", "..."], "roomFeatures": ["Queen bed"] }],"scrapedAt": "2026-07-30T12:00:00Z"}]
Output fields
| Field | Description |
|---|---|
url, title, location, rating, reviews, images | Base actor fields, unchanged — location keeps the base actor's own hardcoded region suffix (see caveats below), and images stays capped at the ~8 URLs from the page's structured-data block. |
locationLine | The location line Airbnb itself prints on the listing page (e.g. "Rome, Lazio, Italy"). |
locationCountry / locationRegion / locationCity | Parsed from the listing's own breadcrumb trail and location block. |
locationBreadcrumbs | The full breadcrumb trail as Airbnb structures it. |
latitude / longitude | The listing's coordinates. |
propertyType | e.g. "Entire apartment", "Entire guest house". |
overviewFacts | Guest/bedroom/bed/bathroom counts as a plain string list. |
photoCount | Number of photos in the full photo tour (post-filter if roomFilter/minPhotos are set). |
captionedPhotoCount | Number of those photos that have a host caption. |
roomCount / roomNames | Number and names of distinct rooms identified. |
isRoomBreakdownAvailable | true when Airbnb's own room-tour breakdown had real room titles for this listing; false when it didn't (see caveats). |
photosMissingRoomLabel | How many of the returned photos have no roomName (even after the airbnbTags fallback). |
photos[] | One entry per photo: id, url, roomName, airbnbTags, caption, captionTranslated, accessibilityLabel, orientation, aspectRatio. |
rooms[] | One entry per identified room: roomName, photoCount, photoIds, roomFeatures. |
scrapedAt | ISO 8601 UTC timestamp of when the row was scraped. |
Failed URLs are pushed as a 2-key row ({"url", "error"}) instead of the full row above — the same shape the base actor uses.
Honest caveats (measured, not assumed)
location(base field) is preserved as-is, including its known bug: the base actor hardcodes a, Florida, United Statessuffix onto every listing regardless of the real location. This variant keeps that field unchanged for backward compatibility — readlocationLine/locationCountry/locationRegion/locationCityinstead for the real address.images(base field) stays capped at whatever the page's structured-data block ships — measured at 8 URLs regardless of the listing's real photo count. Usephotos[]for the full tour.locationLinecoverage was measured at roughly 70% across a multi-country sample — it can come backnullon some listings.locationCountry/locationBreadcrumbs/locationCitywere present on 100% of the sample;locationRegionis sometimes a shallow value (e.g. a district name rather than a full region) when the listing's breadcrumb trail is short.- Room labels (
roomName) come from Airbnb's own room-tour breakdown, which is not present on every listing — measured present on roughly 3 out of 4 listings sampled; the remaining listings returnisRoomBreakdownAvailable: falseand rely on theairbnbTagsfallback (which covered nearly all photos in testing, but is a coarser, tag-based signal rather than a curated room title). captioncoverage is low by nature — host-written captions were present on roughly a third of photos sampled;captionTranslatedonly appears when Airbnb auto-translated a foreign-language caption, which is rare.- No pricing, availability, or per-category review scores (cleanliness, accuracy, etc.) are collected — this actor is scoped to photos, rooms, and location, not pricing/booking data.
roomFilterfilters photos, not listings — a room "survives" the filter if any of its photos matched byroomNameorairbnbTags, so a room can appear inrooms[]even if only one of its photos matched directly.minPhotosis evaluated on the raw (pre-roomFilter) photo count — a listing is dropped entirely, before any room filtering happens, if its full tour has fewer photos than the threshold.
Use cases
- Reshoot / listing-quality audits — find listings with too few exterior or bathroom photos using
roomFilter+photosMissingRoomLabel. - Portfolio mapping — plot listings on a real map using
latitude/longitudeinstead of a guessed region. - Photo dataset building — a room-labeled Airbnb photo dataset for computer-vision or interior-design research.
- Location correction — cross-check or replace a base Airbnb images dataset's
locationfield with the reallocationLine/locationCountry/locationCity. - Market/property research — combine
propertyType,overviewFacts,ratingandreviewsalongside the photo breakdown for a fuller per-listing picture.
FAQ
Does this replace the base Airbnb Images Scraper? It is a superset of it — every base input and output field still works and returns the same values, with the new photo, room and location fields added alongside.
Can I search by city instead of pasting listing URLs? No. This actor scrapes individual Airbnb room pages by URL; it does not accept a location/search query or paginate search results.
Why is roomName sometimes null?
Not every Airbnb listing has a room-tour breakdown published. When it's missing, isRoomBreakdownAvailable is false for that listing, and photos fall back to Airbnb's own airbnbTags where available.
Does it use a proxy for every request? No — it tries a direct request first and only switches to Apify Residential proxy after detecting a block (or an Airbnb geo-redirect page it can't resolve directly), matching the base actor's proxy behavior.