Airbnb Listing Lookup: airbnb scraper by location from $2/1k avatar

Airbnb Listing Lookup: airbnb scraper by location from $2/1k

Pricing

from $1.52 / 1,000 listing returneds

Go to Apify Store
Airbnb Listing Lookup: airbnb scraper by location from $2/1k

Airbnb Listing Lookup: airbnb scraper by location from $2/1k

Airbnb listings scraper: search a location or paste an Airbnb search URL and get one row per listing, including price, rating, room type, coordinates, superhost status, and a direct link. No login. Pay per listing returned; empty searches are free.

Pricing

from $1.52 / 1,000 listing returneds

Rating

0.0

(0)

Developer

Adrian Voss

Adrian Voss

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Airbnb Listing Lookup

You give this actor a location ("Austin, TX") or a pasted Airbnb search URL. It runs the same search a browser would, reads the listings straight out of Airbnb's own search-results page, and gives you back one row per listing: price, rating, room type, coordinates, a Superhost/Guest Favorite badge, and a direct link. No login, no scraping a listing's own detail page — just the search-results card, the same thing you'd see scrolling the map view yourself.

Who it's for

If you're building a list of short-term-rental comps for a pricing model, sourcing candidate properties for a real-estate or arbitrage screen, or feeding an AI agent a "what's available and at what price in this city" question, this turns an Airbnb search into a table instead of a page you'd have to scroll and copy by hand. It answers "which listings, at what price, where, and how well-rated" for a location — not "tell me everything about this one listing", which is a heavier, separate lookup this actor deliberately doesn't make (see "Why this one").

Why this one

  • Reads the search page's own embedded data, not a scraped-and-guessed DOM. Airbnb's search results ship as a JSON blob inside the page (__typename: "StaySearchResult"), the same data the page's own React code renders from — not text pulled off rendered HTML elements that change with every front-end redesign.
  • Priced per listing, not per search. A search for a big city can return dozens of listings; you pay $0.002 per listing actually returned, not a flat per-search fee, and a search that finds nothing costs nothing.
  • Paginates automatically, up to 50 listings per search. One Airbnb search page ships 18 listings; this actor follows Airbnb's own next-page cursors (on the same residential proxy session, never a bare unproxied request) to gather up to 50 without you writing a page loop.
  • Honest about what a search card can't tell you. Host ID and a full amenities list live only on a listing's own detail page — a much heavier per-listing hop this actor does not make. Rather than fake those fields, they're simply not in the output. See the FAQ for what the search card does carry instead (bedroom/bath counts, Superhost and Guest Favorite badges, rating).
  • Never charged for a miss. A search with no results, a malformed location, or a proxy block all come back as a free row explaining why.

What you get

A parent row per search (columns below), exploded into one row per listing by default (turn off "One row per listing" in the Input tab to get one grouped row per search instead — you're charged the same either way).

FieldTypeDescription
querytextThe search you submitted, echoed back
foundbooleantrue if at least one listing was returned
statustextOK on a match; NOT_FOUND, BLOCKED, BAD_FORMAT, or REQUEST_FAILED on a miss
messagetextPlain-English reason for a miss — only present when found is false
scrapedAtISO 8601 datetimeWhen the search was run
searchInputtextThe location or URL you searched, echoed back
checkin / checkouttextThe dates actually used for this search (from your input or the run's defaults)
guestsnumberThe guest count actually used
listingCountnumberHow many listings this search returned (what you're billed for)
truncatedbooleantrue if Airbnb had more listings than this run returned
listingIdtextAirbnb's own numeric listing ID
urllinkThe listing's airbnb.com/rooms/... page
titletextThe listing's headline
roomTypetexte.g. "Condo", "Private room", "Entire home"
citytextParsed from the listing's category line
lat / lngnumberCoordinates
pricePerNightnumberParsed from the price breakdown when a check-in/check-out range is in effect (see FAQ)
priceCurrencytextThe currency symbol/code as Airbnb displayed it — not a verified ISO-4217 code
priceDisplaytextThe price exactly as Airbnb showed it, for when the parsed number needs a sanity check
ratingnumberOut of 5
reviewCountnumber
isSuperhostboolean
isGuestFavoriteboolean
imageUrlimageCover photo

Deselect any field in the Input tab's column picker to drop it from every row — the first five always stay.

Price

  • Listing returned: $2 per 1,000 listings

Plus a $0.00005 start fee per run. Each event above is billed independently, only when it actually returns data — misses (found:false) are never charged.

$2 per 1,000 listings returned (FREE tier — less on a paid Apify plan), plus a $0.00005 actor-start fee. A search that returns nothing costs nothing. 1,000 listings through this actor: ~$2 if every search finds results. The store's leading incumbent, tri_angle/airbnb-scraper, charges $4 per 1,000 — this actor is half that, for the search-card fields (see "What you get") rather than a full listing-detail crawl.

How to use

  1. In the Apify Console. Open the actor page and click Start — the searches field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
  2. Via the API. Call it directly with a POST request — no Console needed once you have an API token:
    curl "https://api.apify.com/v2/acts/accountable_eel~airbnb-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"searches":["Austin, TX"]}'
  3. On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.

Input

{
"searches": [
"Austin, TX"
]
}

One search per line. Write a location like "Austin, TX" or "Lisbon, Portugal", or paste a full airbnb.com/s/.../homes search URL straight from your browser (dates and guest count in the URL are kept). Accepted formats: Austin, TX, Lisbon, Portugal, https://www.airbnb.com/s/Austin--TX/homes?checkin=2026-10-01&checkout=2026-10-05&adults=2.

Optional run-level settings (Input tab, "Search settings"): maxListings (default 18, capped at 50), checkin/checkout (YYYY-MM-DD), and guests — all ignored for any line that's already a full search URL carrying its own dates and guest count.

Sample output

By default you get one row per listing (turn off "One row per listing" in the Input tab for one grouped row per search instead — you're charged the same either way):

queryfoundstatussearchInputcheckincheckoutguestslistingCounttruncatedlistingslistingIdurltitleroomTypecitylatlngpricePerNightpriceCurrencypriceDisplayratingreviewCountisSuperhostisGuestFavoriteimageUrlscrapedAt
Austin, TXfalseNOT_FOUND<all listings found (full list)><price per night (parsed)><currency (as displayed)><price (as airbnb displayed it)><superhost?><guest favorite?>2026-09-08T17:38:07.912Z

A miss comes back as a row with "found": false and is never charged.

Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

curl "https://api.apify.com/v2/acts/accountable_eel~airbnb-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
-X POST \
-H "Content-Type: application/json" \
-d '{"searches":["Austin, TX"]}'

n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~airbnb-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"searches":["Austin, TX"]} (swap in an expression from an earlier node for a real value).

Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~airbnb-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"searches":["{{search}}"]}, mapping the row's search into the searches array.

MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Airbnb Listings Scraper by Location | Apify" — the agent will find and run this actor.

Tips

  • Paste a full search URL (with your own checkin/checkout/adults params already set) when you want exact control over dates and guests — a URL's own query params always win over the run-level defaults.
  • Leave check-in/check-out blank for a quick "what's generally available and at what price" sweep; Airbnb picks its own default dates and the checkin/checkout output columns tell you what it used.
  • truncated: true means more listings existed than this run returned — raise "Most listings to return per search" (up to 50) and run it again if you need the rest.
  • Keep "Max concurrency" conservative — this target runs on Residential proxy specifically because a bare datacenter request is not proven safe at volume (see "Why this one"), and a search-heavy burst is the fastest way to get a session blocked.
  • If pricePerNight comes back null on a listing that clearly has a price, check priceDisplay — it always carries Airbnb's raw price string even when the parser couldn't confidently split out a nightly rate from a total-for-stay figure.

vs. alternatives

What it costsWhat you getTrade-off
This actor (airbnb-listing-lookup)$0.002 per listing returned (FREE tier, less on paid tiers), $0.00005 actor start, nothing for a search with no resultsOne row per listing — price, rating, room type, coordinates, Superhost/Guest Favorite badges, and a direct link, from a location or a pasted search URLSearch-card data only: no host ID or amenities list (Airbnb doesn't ship either on the search results page — see FAQ), and price is parsed from a display string rather than a guaranteed ISO currency code.
tri_angle/airbnb-scraper$4 per 1,000 resultsThe store's dominant incumbent — broader field coverage, including per-listing detail-page fieldsIf you need full listing-detail fields (complete amenities, host profile), that's a heavier per-listing hop this actor doesn't make. For the "which listings, at what price, where" question, this covers it at a quarter of the price.
Doing it yourselfYour time + reverse-engineering Airbnb's embedded GraphQL JSON (the query-variable key changes per search), cursor-based pagination, and residential-proxy economicsThe same dataThe JSON-path parsing, price-string extraction, pagination, and proxy handling are the maintenance burden this actor absorbs.

Prices for third-party tools are their published list prices as of September 2026 and are not tracked here — check the vendor before relying on the comparison.

FAQ

Why don't I get a host ID or an amenities list? Neither exists anywhere in the search-results page's own data — only on a listing's individual page, a separate and much heavier per-listing fetch this actor doesn't make. Rather than fabricate those fields from something else, they're simply not part of the output. What the search card does carry: bedroom/bathroom counts folded into title/roomType, a rating, a review count, and Superhost/Guest Favorite badges.

Is priceCurrency a real ISO currency code? No — it's the currency symbol or code exactly as Airbnb displayed it (e.g. "Ft", "$", "€"), which depends on the locale Airbnb resolved for the request. priceDisplay keeps the full original string so you can always check it against pricePerNight.

Why is pricePerNight sometimes null? Airbnb's search card only ships a pre-formatted price string, not a structured amount. This actor recovers the nightly rate from the "N nights x [amount]" line in the price breakdown when a check-in/check-out range is active; if that breakdown isn't present, pricePerNight stays null rather than guessing — priceDisplay always has the raw figure regardless.

Am I charged for a search that finds nothing? No. Actor.charge() only fires per listing actually returned. A search with zero results, a malformed location, or a proxy block all produce a free row (unless you turn on "Hide rows with no result").

Does this handle rate limits or blocking? The default proxy is Residential specifically because this target is anti-bot-sensitive at volume. A BLOCKED status means Airbnb returned HTTP 403/429/503 to the request; lowering "Max concurrency" is the first thing to try.

Is this a live check or a stored database? Live. Every run is a fresh Airbnb search — there's no cached snapshot, and prices/availability reflect what Airbnb showed at fetch time, not a stored copy.

Can I schedule this to re-check the same search on a cadence? Yes — save it as an Apify Task with your input and add a Schedule. Each run is a fresh search, so a daily or weekly schedule is how you'd track price or availability changes for a location over time.

Can an AI agent call this directly? Yes. It's registered on the Apify MCP server — an agent in Claude, Cursor, or another MCP client can find and run it by name ("Airbnb Listings Scraper by Location | Apify"), or call the REST endpoint shown above from any script or workflow tool.