Airbnb Listings & Stay Prices — Independent Scraper
Pricing
from $0.90 / 1,000 listing rows
Airbnb Listings & Stay Prices — Independent Scraper
Collect public Airbnb search results with detailed listings, amenities, photos and displayed stay prices. Track observed dates, currency and rounded-total flags. No exact nightly or tax guarantee.
Pricing
from $0.90 / 1,000 listing rows
Rating
0.0
(0)
Developer
tingyou333 zhuang
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
21 hours ago
Last modified
Categories
Share
Collect public Airbnb search results with detailed listing descriptions, amenities, photos, review aggregates and displayed stay prices. Each quote includes observed dates and currency, price precision and source timestamps so you can distinguish a rounded headline from an explicitly itemized total.
Use this Actor for rental inventory research, property comparison and dated price snapshots. It is an independent tool, not affiliated with or endorsed by Airbnb. It does not access guest accounts, private messages or reservations.
Quickstart
Paste this input into the Actor's Input tab, then run with 256 MB memory and a 120-second timeout. Inspect both the dataset and the SUMMARY record in the default key-value store. The overview and prices dataset views make listings and price semantics easier to review.
{"locationQueries": ["London"],"maxResults": 3,"checkIn": "2026-11-10","checkOut": "2026-11-13","adults": 2,"locale": "en-US","currency": "USD","maxPages": 2,"maxConcurrency": 2,"maxRunSeconds": 100}
These are the actual inputs for the recorded cloud example. Replace the fixed dates for your own research. A location or search URL is required; the Console's London prefill is not an API default. Start with a small maxResults, especially when adding locations or enabling profile enrichment.
Supported inputs
| Input | Type / default | Behavior and limits |
|---|---|---|
locationQueries | string array; no runtime default | Up to 100 place queries. Airbnb may return recommendations for an unknown place; check observed location. |
startUrls | object array; [] | Up to 100 objects such as {"url":"https://www.airbnb.com/s/London/homes"}. Search URLs only, not room URLs. Bare strings are supported by the local runtime, not the cloud schema. |
maxResults | integer ≥1; not set | Run-wide row cap across all targets. When omitted, request, page and time limits still apply. Console prefill: 3. |
checkIn, checkOut | YYYY-MM-DD strings; not set | Supply both with checkout after check-in. Selected source dates must match; unconfirmed or substituted dates are rejected. |
adults | integer ≥1; not set | Requested party size. Two adults is verified by the cloud example. |
children, infants, pets | integers ≥0; not set | Forwarded as party filters. Anonymous direct observations on September 30, 2026 confirmed all three at 1 with two adults on two London search pages and one complete detail. Other combinations are not established by this sample. |
locale, currency | strings; en-US, USD | Choose from the input schema enums. Requested and observed currency remain separate. London/USD/en-US, Paris/EUR/fr-FR and Tokyo/JPY/ja-JP have recorded source checks; other combinations are unverified. |
priceMin, priceMax | integers ≥0; not set | Native source price range, currently trip price including fees, not a certified nightly-price filter. Minimum must not exceed maximum. |
minBeds, minBedrooms, minBathrooms | integers ≥0; not set | Native search filters. If a source clamps a value, the Actor reports an unconfirmed filter instead of a false empty result. |
enrichUserProfiles | boolean; false | Requests public primary-host and cohost facts when identity is confirmable. Explicit source ID joins are used first; an image-path candidate must match the returned profile ID and original image path. Adds requests; unavailable/unconfirmed profiles create diagnostics and retain the detailed row. Generic cohost avatars can leave identity unresolved. |
calendarMonths | integer 0–12; 0 | Optional actual daily calendar from the check-in month or run month. One additional request per detailed listing; availability and price coverage are separate. |
includeBookingQuote | boolean; false | Optional separate public BookIt quote for paired dates and the requested party. One additional request per detailed listing; existing search price values remain unchanged. |
maxPages | integer 1–100; 15 | Page cap per target. Actual available pages depend on Airbnb. |
maxRequests | integer 1–10000; 100 | Shared HTTP attempt budget, including details, enrichment and retries. |
maxRunSeconds | integer 1–110; 100 | Collection deadline; reaching it can produce partial results. |
maxConcurrency | integer 1–20; 2 | Concurrent detail requests. Higher values may require more memory. |
requestTimeoutSeconds | integer 1–30; 15 | Timeout per HTTP request. |
maxRetries | integer 0–2; 1 | Bounded retries for transient failures; an HTTP 403 is terminal. |
requestDelaySeconds | number 0.05–10; 0.2 | Minimum spacing between HTTP request starts. |
dnsResolver | system or google-doh; system | Explicit DoH option for local fake-IP networks; public-IP checks and TLS verification remain enforced. |
useProxy, proxyConfiguration | false, {"useApifyProxy":false} | Optional existing Apify Proxy entitlement or user-owned proxyUrls (maximum 20). Explicit proxy settings can enable the proxy; configuration failures are reported. No proxy is needed for the recorded cloud example. Paid live proxy behavior is unverified. |
Explicit top-level fields override the same URL parameters; defaults only fill missing URL values. Unknown input fields and unsupported URL parameters are rejected. There is no general sortBy input. Search order is preserved; requested URL sort/filter values must match selected source state on each page. A September 30, 2026 anonymous direct observation ignored sort=price_asc; the Actor rejects that response as SOURCE_FILTER_NOT_CONFIRMED.
Output fields
The default dataset contains one detailed record per delivered listing/stay/party combination. It never contains error rows. Fields absent from the source remain null; empty source arrays remain [].
| Fields | Output / meaning |
|---|---|
id, url, title | String listing ID, public room URL and source title. |
description, descriptionOriginalLanguage, subDescription | Detailed source text, language and overview facts. |
coordinates | Public latitude/longitude object. _source.isExactLocationReported is a source claim, not independently verified address accuracy. |
roomType, personCapacity, homeTier, isSuperHost | Listing classification, capacity and source status flags. Optional values can be unknown. |
rating | Numeric review aggregates where exposed. guestSatisfaction is the overall score; value is value-for-money. |
amenities, houseRules, highlights, locationDescriptions | Grouped public detail content. Amenity availability is boolean or unknown, not an empty-string flag. |
host, coHosts | Public host information only. Enrichment adds publicProfile and hashed publicProfileSource to each confirmable host/cohost. Legacy coHosts[].id remains unchanged; sourced profile IDs are in publicProfile.id, with the contextual ID kept separate. Complete cohost identity/enrichment is not guaranteed. |
images, thumbnail, androidLink, iosLink | Source image and listing links; images are not downloaded. |
locale, language | Observed source locale and language; the requested locale is recorded separately in _source.requestedLocale. |
price | Original formatted amount, label, qualifier and available base-price breakdown. Promotional labels are preserved. |
_pricing | Stay/nightly basis, observed/requested dates and currency, total precision, explicit price lines, tax knowledge and a labelled derived average. |
_source | Search/detail URLs, observation times, response hashes, page/rank, selected query and missing-field notices. Search provenance also retains verified filter state and price-filter basis. Detail currency and language conflicts cause the row to be skipped and diagnosed. |
calendar | Present when calendarMonths>0; full source days/metadata, separate availability/price coverage and hashed request provenance. Null with a diagnostic on failure. |
bookingQuote | Present when includeBookingQuote=true; source BookIt details, explicit Total when present and hashed provenance. Unavailable stays retain source messages and nullable prices. |
Enriched profile values come from the separate public profile response; its URL, hash, capture time and identity evidence are recorded in publicProfileSource. An unavailable or unconfirmed profile leaves publicProfile absent and produces a summary diagnostic. Image-based candidates support both /im/pictures/user/User-ID/original/... and the observed older /im/users/ID/profile_pic/.../original.jpg format; either requires the returned profile ID and original image path to match before enrichment. host.contextualId is nullable, distinct from its legacy id. _source.profileIdentityMappings contains only unambiguous explicit source joins, and is empty when none exist. _source.detailCurrencyObserved and detailLocaleObserved can be null; they describe the detail response and do not replace the search quote's date/currency evidence. detailQuoteAvailable reports whether the listing's bookIt.structuredDisplayPrice is present, without fabricating a quote.
The selected real output fields below illustrate the nested price object. Export your own run as JSON to retain nested detail fields; the Output fields table explains their meanings.
Read prices correctly
price.amountis a formatted display string. Inspect_pricing.basisbefore treating it as a nightly amount._pricing.stayTotaluses an explicit itemized total when available.totalBasis=itemized_totalandtotalPrecision=itemized_exactidentify that case. A headline-only total isdisplay_headline/display_rounded._pricing.nightlyBaseBeforeDiscountsis an explicitly displayed base rate. It is not the final nightly price._pricing.averagePerNightDerivedis total divided by nights, not an observed nightly quote.- Tax and fee information stays unknown unless the source supplies it. A search filter labelled “includes all fees” does not establish a listing's tax/fee breakdown.
- Original, discounted and “price after discount” lines retain their source labels. A promotional line is not relabelled as an exact, all-inclusive final total.
- Individual calendar-night prices are not filled from a stay average. The optional calendar preserves
price.localPriceFormattedexactly, including null; all 60 daily price fields in the two anonymous calendar observations below were null.
Actual cloud example
On 2026-09-26 UTC, the quickstart returned three London listings with USD 846, 593 and 774 displayed totals for November 10–13, two adults. All were display_rounded; nightly final prices and taxes were unknown. Four HTTP responses were 200, with no diagnostics. This is a dated three-row sample, not current pricing or complete London inventory.
Excerpt of the first real row (selected fields only):
{"id": "1770523688441051954","url": "https://www.airbnb.com/rooms/1770523688441051954","price": {"label": "$846 for 3 nights","amount": "$846","qualifier": "for 3 nights"},"_pricing": {"requestedCurrency": "USD","observedCurrency": "USD","observedCheckIn": "2026-11-10","observedCheckOut": "2026-11-13","basis": "stay","nights": 3,"stayTotal": 846,"totalBasis": "display_headline","totalPrecision": "display_rounded","nightly": null,"nightlyBaseBeforeDiscounts": 281.75,"averagePerNightDerived": 282,"taxAmount": null,"taxStatus": "unknown","feesIncluded": null}}
These selected values are copied from the dated cloud dataset. See Latest acceptance sample for its capture time and result count. Repeating the query can return different listings and prices.
Coverage and limitations
Pagination follows source cursors and suppresses duplicates while preserving source order. Collection stops at source exhaustion, an empty page, a repeated page/cursor, no new listings or a configured limit. Distinct stay dates, party sizes, locales and currencies are kept as distinct quotes.
SUMMARY.status distinguishes succeeded, limited, partial and failed. complete only becomes true when all targets reach an explicit source end/empty result without diagnostics. The three-row example is correctly limited, with stopReason=max_results and complete=false. A successful platform run does not mean full search coverage. Inspect targets, stopReason and diagnostics before using the output downstream.
Recorded local checks followed two pages each in London, Paris and Tokyo. Paris skipped one listing lacking required details and is explicitly partial. Unavailable details are skipped and diagnosed; short search cards are not substituted for detailed records. Unknown places can receive source recommendations. September 30 anonymous checks confirmed positive children/infants/pets filters through a real cursor transition. More regions/currencies and arbitrary sorting remain unverified.
This is not a reservation guarantee, occupancy or revenue estimator, exact-address service, or full replacement for every competitor feature. Nightly-price-filter equivalence, actual individual-night amounts, source-selected listing sort and complete cohost enrichment remain unresolved contract gaps. The dated HTML can contain null quote/calendar placeholders; the optional public frontend requests described below fetch actual calendar days and stay quote details separately.
Optional daily availability and public stay quote
Set calendarMonths to 1–12 to add calendar to each complete listing. The default is 0: existing input behavior, row values and request count are unchanged. The calendar starts in the requested check-in month, or the run month without dates, and uses one anonymous public PdpAvailabilityCalendar request per listing. Its days and metadata preserve the source fields, including calendarDate, available, availableForCheckin, availableForCheckout, bookable, minNights, maxNights and price.localPriceFormatted. Unavailable dates can be host blocks or booked dates; the response does not distinguish them. The calendar is not party-specific.
calendar.availabilityComplete describes availability coverage only. nightlyPriceComplete is separate, and coverage reports expected/observed days, months and days with a nonempty source price. A complete month with 30 null prices has complete availability and incomplete price coverage. source.requestedCurrency records the request; source.priceCurrencyObserved stays null unless the API itself declares a currency. A request for USD never supplies an observed currency.
Set includeBookingQuote=true with paired dates to add one anonymous StaysPdpBookItQuery request and a separate bookingQuote. It preserves the actual bookIt price details, selected guest option, stay availability and nullable heatmap. explicitStayTotal is populated only from a source Total line; it does not replace the existing price or _pricing values. Taxes, included fees and API-observed currency remain unknown/null unless stated by that source. A source 3 nights x $218.51 label is a stay-window rate, not three dated final nightly amounts. A one-night window rejected for minimum stay has a null quote price and the actual unavailability message; no price is invented.
Both optional requests use the public frontend key shipped in the same listing HTML, fixed public read-only persisted queries, existing TLS/public-IP validation and zero API retries. No login, user cookies or private host-calendar endpoint is used. Request/time/fee limits still apply; calendars and quotes are nested in the same listing row and do not create additional billable rows. If an optional API fails, the detailed listing is retained with calendar/bookingQuote null and a SUMMARY diagnostic. Partial actual calendar data is retained with availabilityComplete=false. Query rotation or an unexpected response fails closed.
These API responses may not echo the listing ID, ISO stay dates or currency. source.identityEvidence explicitly records request-ID binding when the response lacks an ID; the identity is bound by the validated listing URL and outgoing variables, not an independently echoed response ID. Each optional result retains its URL, hash, observation time, request variables and the key-bearing detail source hash. Inspect those fields when joining observations.
In a dated anonymous direct observation on September 30, 2026 UTC, listing 1228272866919264441 returned all 30 November calendar days. November 12 was available but not eligible for check-in; November 13 was unavailable but eligible for check-out. The public three-night quote for November 10–13, two adults, had an explicit Total of $655.54 and a rounded display of $656; the API did not declare a currency and the heatmap was null. November 11–12 returned Minimum stay is 2 nights. Listing 902912917354258483 returned another 30 actual November days, also with null daily prices. These are source observations, not a reservation or deployment acceptance claim.
For example, add "calendarMonths": 1 and "includeBookingQuote": true to the dated search quickstart. Direct room URLs remain unsupported as input; listing IDs are discovered through the existing search traversal.
The cloud example succeeded with 256 MB and a 120-second run limit, using no proxy. That proves this small workload only; larger workloads or higher concurrency may need more memory. Collection is capped at 110 seconds per run. No browser fallback, login or challenge bypass is included. Private destinations, unsafe redirects and credential-bearing target URLs are rejected.
Pricing
The paid unit is one valid listing row saved in the default dataset. Each separately saved record is another row. Inline arrays do not create extra row events. Failed requests, duplicate rows and diagnostic records do not create result events. A valid source record may have nullable optional fields; a row charge does not guarantee every field.
| Apify plan | USD per row | USD per 1,000 rows |
|---|---|---|
| FREE | 0.003 | 3.00 |
| BRONZE | 0.0018 | 1.80 |
| SILVER | 0.00135 | 1.35 |
| GOLD | 0.0009 | 0.90 |
| PLATINUM | 0.0009 | 0.90 |
| DIAMOND | 0.0009 | 0.90 |
There is no startup event fee. FREE names the Apify subscription tier; it does not mean results are free. The Pricing tab shows the active rate before a run.
Apify platform compute, storage and transfer are charged separately, including for failed or empty runs. An explicitly enabled proxy can add provider fees. A row limit is not an all-inclusive dollar cap. Use small inputs first and inspect actual run usage. Historical owner test runs are not customer revenue or cost forecasts.
API example
Install apify-client, save the quickstart JSON as input.json, and supply your Apify token through the APIFY_TOKEN environment variable. This example starts a run and can incur the live Actor/platform charges.
import jsonimport osfrom decimal import Decimalfrom pathlib import Pathfrom apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("SVh5NigvngTp7kOE7").call(run_input=json.loads(Path("input.json").read_text()),memory_mbytes=256,timeout_secs=120,max_total_charge_usd=Decimal("0.05"),)if not run or run["status"] != "SUCCEEDED":raise RuntimeError("Inspect the run status and SUMMARY before using results")record = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("SUMMARY")summary = record["value"] if record else {}print(summary.get("status"), summary.get("complete"))if summary.get("status") in {"partial", "failed"}:raise RuntimeError("Inspect SUMMARY diagnostics before accepting this sample")for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["id"], row["_pricing"])
FAQ
Can I provide a room URL? No. Start with locations or search URLs. The Actor then fetches details for the returned listings.
Why is the total different from an itemized price line? A headline can round up, while a base or discount line has cents. Only an explicit total can be classified as itemized_exact; do not promote a base/discount line into a final total.
Why did I receive fewer rows than requested? The source may be empty, details may be unavailable, or a limit/failure may have stopped collection. Read SUMMARY; zero rows are not automatically a successful empty search.
Is this a drop-in replacement for another Airbnb scraper? No full parity is claimed. Compare field types, trip-price filter semantics, price precision and host-enrichment scope before migrating. Review Output fields, Read prices correctly, and Coverage and limitations for the supported field meanings and migration limits.
Does the Actor use my browser session or guest data? No. It accesses anonymous public pages only. Host information is limited to public source content.
The icon is Airbnb's original 180×180 public website asset, shown without cropping, recoloring or upscaling. Use of the mark identifies the data source and does not imply affiliation or endorsement.
Latest acceptance sample
The quickstart input was checked in Apify Cloud on 2026-09-26 (UTC; run finished at 2026-09-26T18:40:04.708Z). It saved 3 valid rows. The output example on this page copies real source values from that dataset; it is a dated sample, not current inventory or a current quote.
Three London listings returned displayed USD stay totals of 846, 593 and 774 for November 10–13, 2026 and two adults. All totals were display-rounded; final nightly prices and taxes were unknown. SUMMARY was limited, with complete=false and stopReason=max_results.