Airbnb Full-Year Price Scraper avatar

Airbnb Full-Year Price Scraper

Pricing

from $4.00 / 1,000 results

Go to Apify Store
Airbnb Full-Year Price Scraper

Airbnb Full-Year Price Scraper

Returns one row per calendar day for the next 12 months of any Airbnb listing, with the actual nightly price filled in. Unlike availability-only scrapers, this resolves real prices by calling Airbnb's booking API per day.

Pricing

from $4.00 / 1,000 results

Rating

5.0

(1)

Developer

Crikit

Crikit

Maintained by Community

Actor stats

0

Bookmarked

6

Total users

3

Monthly active users

8 days

Issues response

4 days ago

Last modified

Categories

Share

Get the real host-set nightly price for every bookable day of any Airbnb listing, for up to 24 months ahead. One row per calendar date, with availability flags, minimum-stay rules, instant-book status, and the actual booking-quote price (including any host or platform discount) populated for every bookable day.

This is the actor you reach for when you need real Airbnb pricing over a full year for revenue management, comp analysis, market research, or short-term-rental dashboards. It calls Airbnb's calendar API for availability and Airbnb's booking-quote API per window to resolve the exact price your guests see when they click "Reserve."

Why this exists

Other Airbnb calendar scrapers on Apify all use PdpAvailabilityCalendar, which is the obvious endpoint and which returns price: null for every day. They ship that null and call it done.

This actor uses Airbnb's StaysPdpBookItQuery with the right combination of fragment-include flags to unlock the full pricing payload. You get the same numbers a guest sees on the listing page: nightly rate, total, original price, discounted price, discount amount, instant-book eligibility, and host booking tips.

What you give it

FieldTypeRequiredNotes
listingUrlsarray of URLsyesAirbnb listing URLs like https://www.airbnb.com/rooms/18850420. Paste as many as you want; each is processed independently.
currencystringno, default USDISO-4217 currency code. Airbnb does the conversion server-side.
adultsintegerno, default 2Guest count used in booking quotes. Some listings price per guest.
monthsAheadintegerno, default 12How many months of calendar to scrape (1–24).
maxItemsintegernoOptional hard cap on the total number of rows pushed across all listings. Each row is one calendar day billed at the per-row rate, so this is your cost ceiling. Leave empty for no cap.
proxyConfigurationobjectnoDefaults to Apify Residential Proxy. Required for sustained throughput.

Past calendar dates (days before today) are always filtered out, and every bookable day is always priced — there is nothing to configure for that.

What you get back

One row per calendar date per listing. The fields below are grouped by purpose.

The two fields you actually filter on

FieldTypeNotes
isBookablebooleanTrue iff Airbnb returned a real bookable price for this day. This is the field to filter on. (available=true does NOT imply bookable; see "Important: available ≠ bookable" below.)
notBookableReasonstring | nullWhen isBookable=false, machine-readable reason: blocked_by_host, run_shorter_than_min_nights(...), no_checkin_eligible_day_in_run(...), no_checkin_anchor_covers_this_day(...), available_but_no_earlier_checkin_in_run, bookit_rejected:<msg>, bookit_returned_no_price, bookit_probe_failed:<err>.

Identity & calendar

FieldTypeNotes
listingId, listingUrl, listingTitlestringIdentity.
listingLatitude, listingLongitudenumberCoordinates.
calendarDatestringYYYY-MM-DD.
availablebooleanHost's calendar marks this date open. Does not mean bookable — see warning below.
bookablebooleanRaw calendar API field. Less reliable than isBookable; kept for completeness.
availableForCheckin, availableForCheckoutbooleanPer the calendar API.
minNights, maxNightsintegerMin/max stay length anchored on this date.

Pricing (populated when isBookable=true)

FieldTypeNotes
currencystringISO-4217.
nightlyPrice, nightlyPriceFormattednumber, stringThe per-night rate Airbnb's booking page shows for this window.
originalPrice, originalPriceFormattednumber, stringWindow total before any host discount.
discountedPrice, discountedPriceFormattednumber, stringWindow total after the discount.
discountAmountnumberAbsolute discount on the window.
priceAfterDiscount, priceAfterDiscountFormattednumber, stringSubtotal after discount, before taxes.
totalForWindow, totalForWindowFormattednumber, stringTop-line price for the priced window.
priceWindowNightsintegerNumber of nights the priced window covers.
priceWindowCheckin, priceWindowCheckoutstringExact [checkin, checkout] sent to Airbnb's booking API to produce this row's price. Multiple consecutive rows may share these when one BookIt call covers several stay nights.
priceBreakdownarrayItemized: per-night subtotal, discount lines, fees, taxes.
priceQualifier, priceAccessibilityLabelstringDisplay strings, e.g. "for 5 nights", "$5,046 for 5 nights, originally $6,182".
integratedTip, promotionAnnouncementstringBooking tips and promo banners.

Bookability metadata

FieldTypeNotes
bookItAvailablebooleanThe raw availability.isAvailable from BookIt for the probed window. (Use isBookable for filtering; this is the unprocessed flag.)
canInstantBookbooleanInstant-book eligibility.
unavailabilityMessagestringReason Airbnb gives when BookIt rejected the window.
adults, scrapedAtinteger, stringQuote context.

Important: available ≠ bookable

Airbnb's calendar marks a day available=true whenever the host hasn't blocked it — even when the day cannot actually be booked. Common reasons:

  • Host's min-night > the run of open days: a 3-night-minimum listing with two open days between blocks reports both as available=true, but no real guest can book them. We mark these isBookable=false with notBookableReason="run_shorter_than_min_nights(...)".
  • Day is open for staying but not for check-in: the last day of an open run can be a check-out day for someone who arrived earlier, but you can't start a new booking on it. The actor places windows so these days are priced only when an earlier anchor covers them.
  • Host has a 99-night, weekly-only, or monthly-only rule: long-stay-only listings will show most days as available=true even though only check-in-eligible anchors at the start of a long run can produce a booking.

Always filter on isBookable=true if you want days that have a real price. If you also want to understand WHY some available=true days aren't bookable, read notBookableReason.

Coverage you should expect

After this actor's window-builder anchors probes on availableForCheckin=true days, coverage on truly-bookable days is 100% across every listing we've audited. The variance below is in priced / available, not priced / bookable:

Listing patterntypical priced / available
Flexible short-stay (1–2 night min, plenty of open days)95–100%
Standard 2–3 night minimum, open runs of a week or more80–100%
Strict 5-night minimum or weekend-only restrictions50–70%
Mostly-blocked calendars with isolated 1–2 day gaps below the min-stay0–10%
99-night-only minimum listings30–50%

Recent ground-truth audit: 67 random ground-truth probes across 12 listings (Mountain View, NYC, Lisbon, Luxury NYC w/ 99-night min, Paris ×2, London ×2, Tokyo ×2, Sydney ×2). Zero false positives, zero false negatives. Each priced row was verified by re-querying the exact [priceWindowCheckin, priceWindowCheckout] window the actor used and confirming Airbnb still returns the same isAvailable=true plus a non-null price.

Pricing

Flat $0.008 per daily-price row. A full year of one listing is 365 rows = $2.92.

The leading competitor charges $0.003 per row plus $0.01 extra per priced date = $0.013 per priced day. They also return null prices for every day. We are 38% cheaper AND actually deliver the price.

WorkloadRowsCost
1 listing, 12 months365$2.92
10 listings, 12 months3,650$29.20
100 listings, 12 months36,500$292.00

How it works under the hood

  1. Availability grid. One call to PdpAvailabilityCalendar returns 12 months of day-level data (available, availableForCheckin, availableForCheckout, minNights, maxNights, bookable).

  2. Window construction (true per-day pricing). The actor walks the calendar finding contiguous available runs. For each run:

    • Places an M-night booking-quote window at every availableForCheckin=true day, where M is that day's minNights. Each check-in-eligible day's nightlyPrice is the per-night rate of a minimum-length stay starting on that exact day — the same number Airbnb shows on its booking sidebar if you pick that check-in. For minNights=1 listings this collapses to a literal per-day price.
    • Stay-only and trailing days (open for staying but not check-in-eligible) inherit the full price object from the most-recent anchor whose stay range includes them (latest-anchor-wins), so every covered day carries a complete pricing record. Day-of-week price variation (e.g. a Friday check-in pricing higher than a Tuesday) surfaces directly because every check-in day gets its own quote.
    • If the run has no eligible anchor, OR the anchor's minNights exceeds the remaining run, the days are correctly marked isBookable=false with a specific notBookableReason.
    • Adaptive M+1 retry: when Airbnb rejects an M-night probe with a minimum-stay message (common on weekend check-ins, where the effective minimum is higher than the listing's base minNights), the actor automatically retries with M+1 nights.
    • If the calendar reports the run as too short for minNights at an eligible anchor, the actor still pushes a speculative minNights-long probe — Airbnb's calendar and BookIt occasionally disagree, and the speculative probe recovers a small set of real bookings the calendar would otherwise miss.
  3. Booking-quote probe. For each window, the actor calls StaysPdpBookItQuery with all five fragment-include flags set to true (includePdpMigrationBookIt{CalendarSheet,FloatingFooter,Nav,Sidebar}Fragment plus includeOverviewMerchandisingTipsFragment). With those flags, the response carries the full booking-sidebar payload: structuredDisplayPrice with discountedPrice, originalPrice, per-night breakdown, plus availability, instant-book, and merchandising tips. (Without them, the response is the empty node skeleton, which is why competing scrapers ship null prices.)

  4. Row emission. One row per calendar date. Days covered by a successfully-priced window get the full pricing payload; days that aren't get isBookable=false and a notBookableReason.

  5. Rate-limit handling. Airbnb's API sits behind Akamai with per-IP rate limits. The actor uses Apify Residential Proxy with per-request session rotation: every API call gets a fresh upstream IP, so 429s don't cascade.

Limits to be aware of

  • Calendar window cap. Airbnb's calendar endpoint silently clamps count > 12 to 12. The actor stitches multiple calls automatically when monthsAhead > 12.
  • Data freshness. Airbnb's calendar mutates as bookings happen in real time. The actor returns a snapshot at scrape time; if a date gets booked five minutes after your run, your dataset won't reflect that. For ongoing monitoring, schedule the actor on a cadence that matches your use case (hourly for pricing surveillance, daily for revenue tracking).
  • Per-night pricing semantics. nightlyPrice is the per-night rate of a minimum-stay starting on that calendar day — the same number Airbnb shows on its booking sidebar for that check-in. Because the actor anchors a fresh quote on every check-in-eligible day, real day-of-week variation surfaces directly; for minNights ≥ 2 listings a stay-only day reports the rate of the most recent stay that covers it (which is exactly what a guest inside that booking would pay).
  • Currency conversion is server-side. Pass currency=EUR and Airbnb returns EUR prices.

FAQ

Why is this cheaper than the next-best competitor? They charge $0.003 per row plus $0.01 extra per priced row. A priced year is 365 × $0.013 = $4.75. We charge $0.008 flat per row = $2.92, and we actually return the price.

Does the actor return the same price I'd see if I clicked "Reserve" on the listing page? Yes. The booking-quote API the actor hits is the same one your browser hits when it renders the booking sidebar. Discounts, promotional rates, and instant-book status are what a guest would see.

Why are some available=true days unpriced? Because available on Airbnb's calendar just means "host hasn't blocked it" — it doesn't mean a real booking can land there. Check isBookable and read notBookableReason to see why. Common reasons: surrounding run shorter than min-stay, no check-in-eligible day, or BookIt explicitly rejected the probed window.

Can I scrape multiple listings in one run? Yes. Paste any number of URLs into listingUrls. The actor processes up to three listings at a time and fans each one out across many concurrent booking-quote calls, automatically scaling the fan-out so the total number of concurrent proxy sessions stays in a safe range (a single-listing run gets the full session budget, so it runs fastest).

Does this require my login or session cookie? No. Airbnb's public API key is hardcoded into every airbnb.com page; the actor uses that. No authentication, no PII.

Changelog

  • 0.5: stability, cost-control, and speed pass.

    • True per-day pricing is now the only mode. The actor always anchors a booking quote on every check-in-eligible day (what was previously pricingMode: 'perfect'). The pricingMode, priceWindowNights, includePastDates, fetchPrices, and onlyAvailableDays inputs were removed — they no longer existed in the running code, so the documentation was brought in line with reality. listingIds was also removed; pass listings via listingUrls.
    • maxItems cost cap (restored). An optional hard ceiling on total rows pushed across all listings, so a large multi-listing run can't run away on cost.
    • Run-stability fix. A listing that errors out now records a schema-conforming marker row instead of pushing a row that the dataset validator rejects — the previous behavior could fail the entire run (and lose every other listing's data) on a single bad listing.
    • Never-empty guarantee. Empty calendars, all-invalid input, and zero-result runs now emit a clear marker row instead of finishing with zero rows (which Apify scores as a failed daily health check).
    • Faster single-listing runs. BookIt fan-out concurrency now scales to the number of listings in flight, so a single-listing run uses the full proxy-session budget (~2× the previous fixed concurrency) while multi-listing runs stay under the proxy pool's queueing threshold.
    • Removed an unused dependency (smaller, faster builds) and pinned dependency versions for reproducible builds.
  • 0.3.6: pricingMode: 'perfect' — true per-day pricing.

    • Places an M-night booking-quote window at every availableForCheckin=true day, where M = the listing's minNights. Each FCI day's nightlyPrice is the per-night rate for a minimum-length stay starting on that day — the same number Airbnb shows on the booking sidebar if you pick that checkin.
    • Adaptive M+1 retry: when Airbnb rejects an M-night probe with a minimum-stay error (it often does on weekend checkins where the effective minN > the base minN), the actor automatically retries with M+1 nights. This recovered every previously-rejected day in audit testing.
    • Latest-anchor-wins propagation: stay-only days (non-FCI / trailing days) inherit the full price object from the most-recent anchor whose stay range includes them. So every day in a covered run gets the right price with full pricing metadata, not just FCI days.
    • Coverage at parity or above auto mode: on the user-flagged Mountain View listing, perfect mode now prices 63/63 available days (auto prices 62) while ALSO revealing the full day-of-week structure (Mon $1473 trough → Fri $2334 peak, etc).
    • Ground truth: 6/7 priced rows exactly match direct BookIt re-probes across 4 listings in 4 currencies (the one off-by-$2.76 row reflects live host-price changes between the scrape and the verification probe — Airbnb's data is mutable).
    • Cost: roughly 2x auto mode (one window per FCI day vs auto's tiled non-overlapping windows). Worth it whenever day-of-week pricing matters.
  • 0.2.4: speed pass + sliding-window pricing.

    • 2-11x faster on single-listing runs (typical 12-month run drops from ~63s to ~30s; the user-flagged Mountain View listing went from 147s to 13s).
    • 3.5x faster on multi-listing runs via tighter retry budget (3 attempts × 12s timeout, was 4 × 20s) — stops one slow listing from starving the others.
    • Sliding-window pricing (the user-requested feature): an 8-day open run on a 3-night-min listing now produces three 3-night windows (days 1-3, 4-6, 6-8 with overlap), not one 5-night + one 3-night. Per-night prices are derived from windows whose stay length matches the host's minNights instead of a fixed 5-night blend, giving materially better day-by-day resolution. Controlled by pricingMode (auto/fast/accurate/precise) and priceWindowNights override.
    • Past-date filter: rows for dates before today are now suppressed by default (Airbnb's calendar returns the full calendar month containing today). Set includePastDates=true to keep them.
    • Currency fix: CAD/AUD/MXN/SGD/HKD/NZD/BRL listings no longer have currency: "USD" written into rows when the $ symbol appears in price strings. Detection now recognises 2-letter dollar prefixes (CA$, AU$, etc.) and trusts the input currency as the authoritative answer.
    • Calendar + title fetched in parallel: shaves ~3-5s off every listing's wall time.
    • Calendar pagination is now parallel when monthsAhead > 12.
    • Tail-slide windows: when an available run is shorter than the ideal window length, a backward-shifted minNights window covers the tail without leaving days unpriced.
    • Higher worker concurrency (16 BookIt workers per listing, 3 parallel listings) with a calibrated total cap of ~48 concurrent calls — enough to saturate Airbnb's BookIt latency without choking the Apify residential proxy pool.
    • Batch Actor.pushData for ~10x less I/O overhead.
  • 0.1.10: added priceWindowCheckin and priceWindowCheckout to every priced row so customers (and our audit tooling) can reconstruct the exact booking that produced the price.

  • 0.1.9: speculative-probe fallback for calendar/BookIt disagreement on min-stay edges.

  • 0.1.8: added isBookable (computed) and notBookableReason fields. Dataset overview view now surfaces them so customers can see which available=true days are not actually bookable, and why.

  • 0.1.7: availability-aware window builder. Windows now anchor on availableForCheckin=true days inside contiguous available runs; previously windows could start on blocked days, stranding bookable days with null prices.

  • 0.1.3: prefill listing changed to a higher-coverage example.

  • 0.1.2: proxy-undefined guard, leading-zero listing-ID normalization, permanent-error short-circuit on bad IDs.

  • 0.1.1: initial release — calendar + per-window booking-quote pipeline, residential-proxy rotation, multi-listing concurrency.